initial commit
This commit is contained in:
Executable
+460
@@ -0,0 +1,460 @@
|
||||
(ns ajax.core
|
||||
(:require goog.net.EventType
|
||||
goog.net.ErrorCode
|
||||
[goog.net.XhrIo :as xhr]
|
||||
[goog.net.XhrManager :as xhrm]
|
||||
[goog.Uri :as uri]
|
||||
[goog.json :as goog-json]
|
||||
[goog.Uri.QueryData :as query-data]
|
||||
[goog.json.Serializer]
|
||||
[goog.events :as events]
|
||||
[goog.structs :as structs]
|
||||
[cljs.reader :as reader]
|
||||
[clojure.string :as str]
|
||||
[cognitect.transit :as t])
|
||||
(:require-macros [ajax.macros :as m]
|
||||
[poppea :as p]))
|
||||
|
||||
(defprotocol AjaxImpl
|
||||
"An abstraction for a javascript class that implements
|
||||
Ajax calls."
|
||||
(-js-ajax-request [this uri method body headers handler opts]
|
||||
"Makes an actual ajax request. All parameters except opts
|
||||
are in JS format. Should return an AjaxRequest."))
|
||||
|
||||
(defprotocol AjaxRequest
|
||||
"An abstraction for a running ajax request."
|
||||
(-abort [this]
|
||||
"Aborts a running ajax request, if possible."))
|
||||
|
||||
(defprotocol DirectlySubmittable
|
||||
"A marker interface for types that can be directly sent to XhrIo.")
|
||||
|
||||
(defprotocol AjaxResponse
|
||||
"An abstraction for an ajax response."
|
||||
(-status [this]
|
||||
"Returns the HTTP Status of the response as an integer.")
|
||||
(-status-text [this]
|
||||
"Returns the HTTP Status Text of the response as a string.")
|
||||
(-body [this]
|
||||
"Returns the response body as a string or as type specified in response-format
|
||||
such as a blob or arraybuffer.")
|
||||
(-get-response-header [this header]
|
||||
"Gets the specified response header (specified by a string) as a string.")
|
||||
(-was-aborted [this]
|
||||
"Was the response aborted."))
|
||||
|
||||
(m/register-directly-submittable js/FormData js/ArrayBufferView
|
||||
js/Blob js/Document)
|
||||
|
||||
(defn submittable? [params]
|
||||
(or (satisfies? DirectlySubmittable params)
|
||||
(string? params)))
|
||||
|
||||
(extend-type goog.net.XhrIo
|
||||
AjaxImpl
|
||||
(-js-ajax-request
|
||||
[this uri method body headers handler
|
||||
{:keys [timeout with-credentials]
|
||||
:or {with-credentials false
|
||||
timeout 0}}]
|
||||
(doto this
|
||||
(events/listen goog.net.EventType/COMPLETE
|
||||
#(handler (.-target %)))
|
||||
(.setTimeoutInterval timeout)
|
||||
(.setWithCredentials with-credentials)
|
||||
(.send uri method body (clj->js headers))))
|
||||
AjaxRequest
|
||||
(-abort [this] (.abort this goog.net.ErrorCode/ABORT))
|
||||
AjaxResponse
|
||||
(-body [this] (.getResponseText this))
|
||||
(-status [this] (.getStatus this))
|
||||
(-status-text [this] (.getStatusText this))
|
||||
(-get-response-header [this header]
|
||||
(.getResponseHeader this header))
|
||||
(-was-aborted [this]
|
||||
(= (.getLastErrorCode this) goog.net.ErrorCode/ABORT)))
|
||||
|
||||
(defn ready-state
|
||||
[e]
|
||||
({0 :not-initialized
|
||||
1 :connection-established
|
||||
2 :request-received
|
||||
3 :processing-request
|
||||
4 :response-ready} (.-readyState (.-target e))))
|
||||
|
||||
(extend-type js/XMLHttpRequest
|
||||
AjaxImpl
|
||||
(-js-ajax-request
|
||||
[this uri method body headers handler
|
||||
{:keys [timeout with-credentials response-format]
|
||||
:or {with-credentials false
|
||||
timeout 0}}]
|
||||
(set! (.-withCredentials this) with-credentials)
|
||||
(set! (.-onreadystatechange this) #(when (= :response-ready (ready-state %)) (handler this)))
|
||||
(.open this method uri true)
|
||||
(set! (.-timeout this) timeout)
|
||||
; IE8 needs timeout to be set between open and send
|
||||
; https://msdn.microsoft.com/en-us/library/cc304105(v=vs.85).aspx
|
||||
(when-let [response-type (:type response-format)]
|
||||
(set! (.-responseType this) (name response-type)))
|
||||
(doseq [[k v] headers]
|
||||
(.setRequestHeader this k v))
|
||||
(.send this (or body ""))
|
||||
this)
|
||||
AjaxRequest
|
||||
(-abort [this] (.abort this))
|
||||
AjaxResponse
|
||||
(-body [this] (.-response this))
|
||||
(-status [this] (.-status this))
|
||||
(-status-text [this] (.-statusText this))
|
||||
(-get-response-header [this header]
|
||||
(.getResponseHeader this header))
|
||||
(-was-aborted [this] (= 0 (.-readyState this))))
|
||||
|
||||
(extend-type goog.net.XhrManager
|
||||
AjaxImpl
|
||||
(-js-ajax-request
|
||||
[this uri method body headers handler
|
||||
{:keys [id timeout priority max-retries]}]
|
||||
(.send this id uri method body (clj->js headers)
|
||||
priority handler max-retries)))
|
||||
|
||||
(defn abort ([this] (-abort this)))
|
||||
|
||||
(defn success? [status]
|
||||
(some #{status} [200 201 202 204 205 206]))
|
||||
|
||||
;;; Standard Formats
|
||||
|
||||
(defn read-edn [xhrio]
|
||||
(reader/read-string (-body xhrio)))
|
||||
|
||||
(defn edn-response-format
|
||||
([] {:read read-edn
|
||||
:description "EDN"
|
||||
:content-type "application/edn"})
|
||||
([opts] (edn-response-format)))
|
||||
|
||||
(defn edn-request-format []
|
||||
{:write pr-str
|
||||
:content-type "application/edn"})
|
||||
|
||||
(p/defn-curried transit-write
|
||||
[writer params]
|
||||
(t/write writer params))
|
||||
|
||||
(defn transit-request-format
|
||||
([] (transit-request-format {}))
|
||||
([{:keys [type writer] :as opts}]
|
||||
(let [writer (or writer (t/writer (or type :json) opts))]
|
||||
{:write (transit-write writer)
|
||||
:content-type "application/transit+json"})))
|
||||
|
||||
(p/defn-curried transit-read [reader raw xhrio]
|
||||
(let [text (-body xhrio)
|
||||
data (t/read reader text)]
|
||||
(if raw data (js->clj data))))
|
||||
|
||||
(defn transit-response-format
|
||||
([] (transit-response-format {}))
|
||||
([{:keys [type reader raw] :as opts}]
|
||||
(let [reader (or reader (t/reader (or type :json) opts))]
|
||||
{:read (transit-read reader raw)
|
||||
:description "Transit"
|
||||
:content-type "application/transit+json"})))
|
||||
|
||||
(defn params-to-str [params]
|
||||
(if params
|
||||
(-> params
|
||||
clj->js
|
||||
structs/Map.
|
||||
query-data/createFromMap
|
||||
.toString)))
|
||||
|
||||
(defn url-request-format []
|
||||
{:write params-to-str
|
||||
:content-type "application/x-www-form-urlencoded"})
|
||||
|
||||
(defn raw-response-format
|
||||
([] {:read -body :description "raw text" :content-type "*/*"})
|
||||
([opts] (raw-response-format)))
|
||||
|
||||
(defn write-json [data]
|
||||
(.serialize (goog.json.Serializer.) (clj->js data)))
|
||||
|
||||
(defn json-request-format []
|
||||
{:write write-json
|
||||
:content-type "application/json"})
|
||||
|
||||
(p/defn-curried json-read [prefix raw keywords? xhrio]
|
||||
(let [text (-body xhrio)
|
||||
text (if (and prefix (= 0 (.indexOf text prefix)))
|
||||
(.substring text (.length prefix))
|
||||
text)
|
||||
json (goog-json/parse text)]
|
||||
(if raw
|
||||
json
|
||||
(js->clj json :keywordize-keys keywords?))))
|
||||
|
||||
(defn json-response-format
|
||||
"Returns a JSON response format. Options include
|
||||
:keywords? Returns the keys as keywords
|
||||
:prefix A prefix that needs to be stripped off. This is to
|
||||
combat JSON hijacking. If you're using JSON with GET request,
|
||||
you should think about using this.
|
||||
http://stackoverflow.com/questions/2669690/why-does-google-prepend-while1-to-their-json-responses
|
||||
http://haacked.com/archive/2009/06/24/json-hijacking.aspx"
|
||||
([] (json-response-format {}))
|
||||
([{:keys [prefix keywords? raw]}]
|
||||
{:read (json-read prefix raw keywords?)
|
||||
:description (str "JSON"
|
||||
(if prefix (str " prefix '" prefix "'"))
|
||||
(if keywords? " keywordize"))
|
||||
:content-type "application/json"}))
|
||||
|
||||
;;; Detection and Accept Code
|
||||
|
||||
(def default-formats
|
||||
[json-response-format
|
||||
edn-response-format
|
||||
transit-response-format
|
||||
["text/plain" raw-response-format]
|
||||
["text/html" raw-response-format]
|
||||
raw-response-format])
|
||||
|
||||
(p/defn-curried get-format [opts format-entry]
|
||||
(cond (vector? format-entry) (get-format opts
|
||||
(second format-entry))
|
||||
(map? format-entry) format-entry
|
||||
; Must be a format generating function
|
||||
:else (format-entry opts)))
|
||||
|
||||
(p/defn-curried accept-entry [opts format-entry]
|
||||
(or (if (vector? format-entry)
|
||||
(first format-entry)
|
||||
(:content-type (get-format opts format-entry)))
|
||||
"*/*"))
|
||||
|
||||
(p/defn-curried detect-content-type [content-type opts format-entry]
|
||||
(let [accept (accept-entry opts format-entry)]
|
||||
(or (= accept "*/*")
|
||||
(>= (.indexOf content-type accept) 0))))
|
||||
|
||||
(defn get-default-format [xhrio {:keys [response-format] :as opts}]
|
||||
(let [f (detect-content-type
|
||||
(or (-get-response-header xhrio "Content-Type") "")
|
||||
opts)]
|
||||
(->> response-format
|
||||
(filter f)
|
||||
first
|
||||
(get-format opts))))
|
||||
|
||||
(p/defn-curried detect-response-format-read
|
||||
[opts xhrio]
|
||||
((:read (get-default-format xhrio opts)) xhrio))
|
||||
|
||||
(defn accept-header [{:keys [response-format] :as opts}]
|
||||
(if (vector? response-format)
|
||||
(str/join ", " (map (accept-entry opts) response-format))
|
||||
(accept-entry opts response-format)))
|
||||
|
||||
(defn detect-response-format
|
||||
([] (detect-response-format {:response-format default-formats}))
|
||||
([opts]
|
||||
(let [accept (accept-header opts)]
|
||||
{:read (detect-response-format-read opts)
|
||||
:format (str "(from " accept ")")
|
||||
:content-type accept})))
|
||||
|
||||
;;; AJAX calls
|
||||
|
||||
(defn get-response-format [{:keys [response-format] :as opts}]
|
||||
(cond
|
||||
(vector? response-format) (detect-response-format opts)
|
||||
(map? response-format) response-format
|
||||
(ifn? response-format) {:read response-format
|
||||
:description "custom"
|
||||
:content-type "*/*"}
|
||||
:else (throw (js/Error. (str "unrecognized response format: " response-format)))))
|
||||
|
||||
(defn exception-response [e status {:keys [description]} xhrio]
|
||||
(let [response {:status status
|
||||
:failure :error
|
||||
:response nil}
|
||||
status-text (str (.-message e)
|
||||
" Format should have been "
|
||||
description)
|
||||
parse-error (assoc response
|
||||
:status-text status-text
|
||||
:failure :parse
|
||||
:original-text (-body xhrio))]
|
||||
(if (success? status)
|
||||
parse-error
|
||||
(assoc response
|
||||
:status-text (-status-text xhrio)
|
||||
:parse-error parse-error))))
|
||||
|
||||
(defn fail [status status-text failure & params]
|
||||
(let [response {:status status
|
||||
:status-text status-text
|
||||
:failure failure}]
|
||||
[false (reduce conj
|
||||
response
|
||||
(map vec (partition 2 params)))]))
|
||||
|
||||
(defn interpret-response [{:keys [read] :as format} xhrio]
|
||||
(try
|
||||
(let [status (-status xhrio)
|
||||
fail (partial fail status)]
|
||||
(case status
|
||||
-1 (if (-was-aborted xhrio)
|
||||
(fail "Request aborted by client." :aborted)
|
||||
(fail "Request timed out." :timeout))
|
||||
204 [true nil] ; 204 and 205 should have empty responses
|
||||
205 [true nil]
|
||||
(try
|
||||
(let [response (read xhrio)]
|
||||
(if (success? status)
|
||||
[true response]
|
||||
(fail (-status-text xhrio) :error :response response)))
|
||||
(catch js/Object e
|
||||
[false (exception-response e status format xhrio)]))))
|
||||
(catch js/Object e
|
||||
; These errors should never happen
|
||||
(fail 0 (.-message e) :exception :exception e))))
|
||||
|
||||
(defn no-format [xhrio]
|
||||
(throw (js/Error. "No response format was supplied.")))
|
||||
|
||||
(defn uri-with-params [uri params]
|
||||
(if params
|
||||
(str uri
|
||||
(if (re-find #"\?" uri) "&" "?") ; add & if uri contains ?
|
||||
(params-to-str params))
|
||||
uri))
|
||||
|
||||
(defn get-request-format [format]
|
||||
(cond
|
||||
(map? format) format
|
||||
(ifn? format) {:write format :content-type "text/plain"}
|
||||
:else nil))
|
||||
|
||||
(defn normalize-method [method]
|
||||
(if (keyword? method)
|
||||
(str/upper-case (name method))
|
||||
method))
|
||||
|
||||
(defn process-inputs [{:keys [uri method format params headers]}
|
||||
{:keys [content-type]}]
|
||||
(let [headers (merge {"Accept" content-type}
|
||||
(or headers {}))]
|
||||
(if (= (normalize-method method) "GET")
|
||||
[(uri-with-params uri params) nil headers]
|
||||
(let [{:keys [write content-type]}
|
||||
(get-request-format format)
|
||||
body (cond
|
||||
(not (nil? write)) (write params)
|
||||
(submittable? params) params
|
||||
:else (throw (js/Error. (str "unrecognized request format: " format))))
|
||||
content-type (if content-type
|
||||
{"Content-Type" (str content-type "; charset=utf-8")})
|
||||
headers (merge headers content-type)]
|
||||
[uri body headers]))))
|
||||
|
||||
(p/defn-curried js-handler [response-format handler xhrio]
|
||||
(let [response
|
||||
(interpret-response response-format xhrio)]
|
||||
(handler response)))
|
||||
|
||||
(defn base-handler [response-format {:keys [handler]}]
|
||||
(if handler
|
||||
(js-handler response-format handler)
|
||||
(throw (js/Error. "No ajax handler provided."))))
|
||||
|
||||
(defn ajax-request
|
||||
[{:keys [method api] :as opts}]
|
||||
(let [response-format (get-response-format opts)
|
||||
method (normalize-method method)
|
||||
[uri body headers] (process-inputs opts response-format)
|
||||
handler (base-handler response-format opts)
|
||||
api (or api (new goog.net.XhrIo))]
|
||||
(-js-ajax-request api uri method body
|
||||
headers handler opts)))
|
||||
|
||||
;;; "Easy" API beyond this point
|
||||
|
||||
(defn keyword-request-format [format format-params]
|
||||
(cond
|
||||
(map? format) format
|
||||
(fn? format) {:write format}
|
||||
(nil? format) (transit-request-format format-params)
|
||||
:else (case format
|
||||
:transit (transit-request-format format-params)
|
||||
:json (json-request-format)
|
||||
:edn (edn-request-format)
|
||||
:raw (url-request-format)
|
||||
:url (url-request-format)
|
||||
nil)))
|
||||
|
||||
(defn keyword-response-format-2 [format format-params]
|
||||
(cond
|
||||
(vector? format) [(first format)
|
||||
(keyword-response-format-2 (second format)
|
||||
format-params)]
|
||||
(map? format) format
|
||||
(fn? format) {:read format :description "custom"}
|
||||
(nil? format) (detect-response-format)
|
||||
:else (case format
|
||||
:transit (transit-response-format format-params)
|
||||
:json (json-response-format format-params)
|
||||
:edn (edn-response-format)
|
||||
:raw (raw-response-format)
|
||||
:detect (detect-response-format)
|
||||
nil)))
|
||||
|
||||
(defn keyword-response-format [format format-params]
|
||||
(if (vector? format)
|
||||
(->> format
|
||||
(map #(keyword-response-format-2 % format-params))
|
||||
(apply vector))
|
||||
(keyword-response-format-2 format format-params)))
|
||||
|
||||
(p/defn-curried transform-handler
|
||||
[{:keys [handler error-handler finally]} [ok result]]
|
||||
(if-let [h (if ok handler error-handler)]
|
||||
(h result))
|
||||
(when (fn? finally)
|
||||
(finally)))
|
||||
|
||||
(defn transform-opts [{:keys [method format response-format params]
|
||||
:as opts}]
|
||||
"Note that if you call GET, POST et al, this function gets
|
||||
called and will include JSON and EDN code in your JS.
|
||||
If you don't want this to happen, use ajax-request directly
|
||||
(and use advanced optimisation)."
|
||||
(let [needs-format
|
||||
(not (or (submittable? params)
|
||||
(= method "GET")))
|
||||
rf (if (or format needs-format)
|
||||
(keyword-request-format format opts))]
|
||||
(assoc opts
|
||||
:handler (transform-handler opts)
|
||||
:format rf
|
||||
:response-format (keyword-response-format response-format opts))))
|
||||
|
||||
(defn easy-ajax-request [uri method opts]
|
||||
(-> opts
|
||||
(assoc :uri uri
|
||||
:method method)
|
||||
ajax.core/transform-opts
|
||||
ajax.core/ajax-request))
|
||||
|
||||
(m/easy-api GET)
|
||||
(m/easy-api HEAD)
|
||||
(m/easy-api POST)
|
||||
(m/easy-api PUT)
|
||||
(m/easy-api DELETE)
|
||||
(m/easy-api OPTIONS)
|
||||
(m/easy-api TRACE)
|
||||
(m/easy-api PATCH)
|
||||
Executable
+1891
File diff suppressed because it is too large
Load Diff
Executable
+1
File diff suppressed because one or more lines are too long
Executable
+12131
File diff suppressed because it is too large
Load Diff
Executable
+39030
File diff suppressed because it is too large
Load Diff
Executable
+886
@@ -0,0 +1,886 @@
|
||||
(ns cljs.core.async
|
||||
(:refer-clojure :exclude [reduce into merge map take partition partition-by])
|
||||
(:require [cljs.core.async.impl.protocols :as impl]
|
||||
[cljs.core.async.impl.channels :as channels]
|
||||
[cljs.core.async.impl.buffers :as buffers]
|
||||
[cljs.core.async.impl.timers :as timers]
|
||||
[cljs.core.async.impl.dispatch :as dispatch]
|
||||
[cljs.core.async.impl.ioc-helpers :as helpers])
|
||||
(:require-macros [cljs.core.async.impl.ioc-macros :as ioc]
|
||||
[cljs.core.async.macros :refer [go go-loop]]))
|
||||
|
||||
(defn- fn-handler [f]
|
||||
(reify
|
||||
impl/Handler
|
||||
(active? [_] true)
|
||||
(commit [_] f)))
|
||||
|
||||
(defn buffer
|
||||
"Returns a fixed buffer of size n. When full, puts will block/park."
|
||||
[n]
|
||||
(buffers/fixed-buffer n))
|
||||
|
||||
(defn dropping-buffer
|
||||
"Returns a buffer of size n. When full, puts will complete but
|
||||
val will be dropped (no transfer)."
|
||||
[n]
|
||||
(buffers/dropping-buffer n))
|
||||
|
||||
(defn sliding-buffer
|
||||
"Returns a buffer of size n. When full, puts will complete, and be
|
||||
buffered, but oldest elements in buffer will be dropped (not
|
||||
transferred)."
|
||||
[n]
|
||||
(buffers/sliding-buffer n))
|
||||
|
||||
(defn unblocking-buffer?
|
||||
"Returns true if a channel created with buff will never block. That is to say,
|
||||
puts into this buffer will never cause the buffer to be full. "
|
||||
[buff]
|
||||
(satisfies? impl/UnblockingBuffer buff))
|
||||
|
||||
(defn chan
|
||||
"Creates a channel with an optional buffer, an optional transducer (like (map f),
|
||||
(filter p) etc or a composition thereof), and an optional exception handler.
|
||||
If buf-or-n is a number, will create and use a fixed buffer of that size. If a
|
||||
transducer is supplied a buffer must be specified. ex-handler must be a
|
||||
fn of one argument - if an exception occurs during transformation it will be called
|
||||
with the thrown value as an argument, and any non-nil return value will be placed
|
||||
in the channel."
|
||||
([] (chan nil))
|
||||
([buf-or-n] (chan buf-or-n nil nil))
|
||||
([buf-or-n xform] (chan buf-or-n xform nil))
|
||||
([buf-or-n xform ex-handler]
|
||||
(let [buf-or-n (if (= buf-or-n 0)
|
||||
nil
|
||||
buf-or-n)]
|
||||
(when xform (assert buf-or-n "buffer must be supplied when transducer is"))
|
||||
(channels/chan (if (number? buf-or-n)
|
||||
(buffer buf-or-n)
|
||||
buf-or-n)
|
||||
xform
|
||||
ex-handler))))
|
||||
|
||||
(defn timeout
|
||||
"Returns a channel that will close after msecs"
|
||||
[msecs]
|
||||
(timers/timeout msecs))
|
||||
|
||||
(defn <!
|
||||
"takes a val from port. Must be called inside a (go ...) block. Will
|
||||
return nil if closed. Will park if nothing is available.
|
||||
Returns true unless port is already closed"
|
||||
[port]
|
||||
(throw (js/Error. "<! used not in (go ...) block")))
|
||||
|
||||
(defn take!
|
||||
"Asynchronously takes a val from port, passing to fn1. Will pass nil
|
||||
if closed. If on-caller? (default true) is true, and value is
|
||||
immediately available, will call fn1 on calling thread.
|
||||
Returns nil."
|
||||
([port fn1] (take! port fn1 true))
|
||||
([port fn1 on-caller?]
|
||||
(let [ret (impl/take! port (fn-handler fn1))]
|
||||
(when ret
|
||||
(let [val @ret]
|
||||
(if on-caller?
|
||||
(fn1 val)
|
||||
(dispatch/run #(fn1 val)))))
|
||||
nil)))
|
||||
|
||||
(defn- nop [_])
|
||||
(def ^:private fhnop (fn-handler nop))
|
||||
|
||||
(defn >!
|
||||
"puts a val into port. nil values are not allowed. Must be called
|
||||
inside a (go ...) block. Will park if no buffer space is available.
|
||||
Returns true unless port is already closed."
|
||||
[port val]
|
||||
(throw (js/Error. ">! used not in (go ...) block")))
|
||||
|
||||
(defn put!
|
||||
"Asynchronously puts a val into port, calling fn0 (if supplied) when
|
||||
complete. nil values are not allowed. Will throw if closed. If
|
||||
on-caller? (default true) is true, and the put is immediately
|
||||
accepted, will call fn0 on calling thread. Returns nil."
|
||||
([port val]
|
||||
(if-let [ret (impl/put! port val fhnop)]
|
||||
@ret
|
||||
true))
|
||||
([port val fn1] (put! port val fn1 true))
|
||||
([port val fn1 on-caller?]
|
||||
(if-let [retb (impl/put! port val (fn-handler fn1))]
|
||||
(let [ret @retb]
|
||||
(if on-caller?
|
||||
(fn1 ret)
|
||||
(dispatch/run #(fn1 ret)))
|
||||
ret)
|
||||
true)))
|
||||
|
||||
(defn close!
|
||||
([port]
|
||||
(impl/close! port)))
|
||||
|
||||
|
||||
(defn- random-array
|
||||
[n]
|
||||
(let [a (make-array n)]
|
||||
(dotimes [x n]
|
||||
(aset a x 0))
|
||||
(loop [i 1]
|
||||
(if (= i n)
|
||||
a
|
||||
(do
|
||||
(let [j (rand-int i)]
|
||||
(aset a i (aget a j))
|
||||
(aset a j i)
|
||||
(recur (inc i))))))))
|
||||
|
||||
(defn- alt-flag []
|
||||
(let [flag (atom true)]
|
||||
(reify
|
||||
impl/Handler
|
||||
(active? [_] @flag)
|
||||
(commit [_]
|
||||
(reset! flag nil)
|
||||
true))))
|
||||
|
||||
(defn- alt-handler [flag cb]
|
||||
(reify
|
||||
impl/Handler
|
||||
(active? [_] (impl/active? flag))
|
||||
(commit [_]
|
||||
(impl/commit flag)
|
||||
cb)))
|
||||
|
||||
(defn do-alts
|
||||
"returns derefable [val port] if immediate, nil if enqueued"
|
||||
[fret ports opts]
|
||||
(let [flag (alt-flag)
|
||||
n (count ports)
|
||||
idxs (random-array n)
|
||||
priority (:priority opts)
|
||||
ret
|
||||
(loop [i 0]
|
||||
(when (< i n)
|
||||
(let [idx (if priority i (aget idxs i))
|
||||
port (nth ports idx)
|
||||
wport (when (vector? port) (port 0))
|
||||
vbox (if wport
|
||||
(let [val (port 1)]
|
||||
(impl/put! wport val (alt-handler flag #(fret [% wport]))))
|
||||
(impl/take! port (alt-handler flag #(fret [% port]))))]
|
||||
(if vbox
|
||||
(channels/box [@vbox (or wport port)])
|
||||
(recur (inc i))))))]
|
||||
(or
|
||||
ret
|
||||
(when (contains? opts :default)
|
||||
(when-let [got (and (impl/active? flag) (impl/commit flag))]
|
||||
(channels/box [(:default opts) :default]))))))
|
||||
|
||||
(defn alts!
|
||||
"Completes at most one of several channel operations. Must be called
|
||||
inside a (go ...) block. ports is a vector of channel endpoints,
|
||||
which can be either a channel to take from or a vector of
|
||||
[channel-to-put-to val-to-put], in any combination. Takes will be
|
||||
made as if by <!, and puts will be made as if by >!. Unless
|
||||
the :priority option is true, if more than one port operation is
|
||||
ready a non-deterministic choice will be made. If no operation is
|
||||
ready and a :default value is supplied, [default-val :default] will
|
||||
be returned, otherwise alts! will park until the first operation to
|
||||
become ready completes. Returns [val port] of the completed
|
||||
operation, where val is the value taken for takes, and a
|
||||
boolean (true unless already closed, as per put!) for puts.
|
||||
|
||||
opts are passed as :key val ... Supported options:
|
||||
|
||||
:default val - the value to use if none of the operations are immediately ready
|
||||
:priority true - (default nil) when true, the operations will be tried in order.
|
||||
|
||||
Note: there is no guarantee that the port exps or val exprs will be
|
||||
used, nor in what order should they be, so they should not be
|
||||
depended upon for side effects."
|
||||
|
||||
[ports & {:as opts}]
|
||||
(throw (js/Error. "alts! used not in (go ...) block")))
|
||||
|
||||
;;;;;;; channel ops
|
||||
|
||||
(defn pipe
|
||||
"Takes elements from the from channel and supplies them to the to
|
||||
channel. By default, the to channel will be closed when the from
|
||||
channel closes, but can be determined by the close? parameter. Will
|
||||
stop consuming the from channel if the to channel closes"
|
||||
|
||||
([from to] (pipe from to true))
|
||||
([from to close?]
|
||||
(go-loop []
|
||||
(let [v (<! from)]
|
||||
(if (nil? v)
|
||||
(when close? (close! to))
|
||||
(when (>! to v)
|
||||
(recur)))))
|
||||
to))
|
||||
|
||||
(defn- pipeline*
|
||||
([n to xf from close? ex-handler type]
|
||||
(assert (pos? n))
|
||||
(let [jobs (chan n)
|
||||
results (chan n)
|
||||
process (fn [[v p :as job]]
|
||||
(if (nil? job)
|
||||
(do (close! results) nil)
|
||||
(let [res (chan 1 xf ex-handler)]
|
||||
(go
|
||||
(>! res v)
|
||||
(close! res))
|
||||
(put! p res)
|
||||
true)))
|
||||
async (fn [[v p :as job]]
|
||||
(if (nil? job)
|
||||
(do (close! results) nil)
|
||||
(let [res (chan 1)]
|
||||
(xf v res)
|
||||
(put! p res)
|
||||
true)))]
|
||||
(dotimes [_ n]
|
||||
(case type
|
||||
:compute (go-loop []
|
||||
(let [job (<! jobs)]
|
||||
(when (process job)
|
||||
(recur))))
|
||||
:async (go-loop []
|
||||
(let [job (<! jobs)]
|
||||
(when (async job)
|
||||
(recur))))))
|
||||
(go-loop []
|
||||
(let [v (<! from)]
|
||||
(if (nil? v)
|
||||
(close! jobs)
|
||||
(let [p (chan 1)]
|
||||
(>! jobs [v p])
|
||||
(>! results p)
|
||||
(recur)))))
|
||||
(go-loop []
|
||||
(let [p (<! results)]
|
||||
(if (nil? p)
|
||||
(when close? (close! to))
|
||||
(let [res (<! p)]
|
||||
(loop []
|
||||
(let [v (<! res)]
|
||||
(when (and (not (nil? v)) (>! to v))
|
||||
(recur))))
|
||||
(recur))))))))
|
||||
|
||||
(defn pipeline-async
|
||||
"Takes elements from the from channel and supplies them to the to
|
||||
channel, subject to the async function af, with parallelism n. af
|
||||
must be a function of two arguments, the first an input value and
|
||||
the second a channel on which to place the result(s). af must close!
|
||||
the channel before returning. The presumption is that af will
|
||||
return immediately, having launched some asynchronous operation
|
||||
whose completion/callback will manipulate the result channel. Outputs
|
||||
will be returned in order relative to the inputs. By default, the to
|
||||
channel will be closed when the from channel closes, but can be
|
||||
determined by the close? parameter. Will stop consuming the from
|
||||
channel if the to channel closes."
|
||||
([n to af from] (pipeline-async n to af from true))
|
||||
([n to af from close?] (pipeline* n to af from close? nil :async)))
|
||||
|
||||
(defn pipeline
|
||||
"Takes elements from the from channel and supplies them to the to
|
||||
channel, subject to the transducer xf, with parallelism n. Because
|
||||
it is parallel, the transducer will be applied independently to each
|
||||
element, not across elements, and may produce zero or more outputs
|
||||
per input. Outputs will be returned in order relative to the
|
||||
inputs. By default, the to channel will be closed when the from
|
||||
channel closes, but can be determined by the close? parameter. Will
|
||||
stop consuming the from channel if the to channel closes.
|
||||
|
||||
Note this is supplied for API compatibility with the Clojure version.
|
||||
Values of N > 1 will not result in actual concurrency in a
|
||||
single-threaded runtime."
|
||||
([n to xf from] (pipeline n to xf from true))
|
||||
([n to xf from close?] (pipeline n to xf from close? nil))
|
||||
([n to xf from close? ex-handler] (pipeline* n to xf from close? ex-handler :compute)))
|
||||
|
||||
(defn split
|
||||
"Takes a predicate and a source channel and returns a vector of two
|
||||
channels, the first of which will contain the values for which the
|
||||
predicate returned true, the second those for which it returned
|
||||
false.
|
||||
|
||||
The out channels will be unbuffered by default, or two buf-or-ns can
|
||||
be supplied. The channels will close after the source channel has
|
||||
closed."
|
||||
([p ch] (split p ch nil nil))
|
||||
([p ch t-buf-or-n f-buf-or-n]
|
||||
(let [tc (chan t-buf-or-n)
|
||||
fc (chan f-buf-or-n)]
|
||||
(go-loop []
|
||||
(let [v (<! ch)]
|
||||
(if (nil? v)
|
||||
(do (close! tc) (close! fc))
|
||||
(when (>! (if (p v) tc fc) v)
|
||||
(recur)))))
|
||||
[tc fc])))
|
||||
|
||||
(defn reduce
|
||||
"f should be a function of 2 arguments. Returns a channel containing
|
||||
the single result of applying f to init and the first item from the
|
||||
channel, then applying f to that result and the 2nd item, etc. If
|
||||
the channel closes without yielding items, returns init and f is not
|
||||
called. ch must close before reduce produces a result."
|
||||
[f init ch]
|
||||
(go-loop [ret init]
|
||||
(let [v (<! ch)]
|
||||
(if (nil? v)
|
||||
ret
|
||||
(recur (f ret v))))))
|
||||
|
||||
|
||||
(defn onto-chan
|
||||
"Puts the contents of coll into the supplied channel.
|
||||
|
||||
By default the channel will be closed after the items are copied,
|
||||
but can be determined by the close? parameter.
|
||||
|
||||
Returns a channel which will close after the items are copied."
|
||||
([ch coll] (onto-chan ch coll true))
|
||||
([ch coll close?]
|
||||
(go-loop [vs (seq coll)]
|
||||
(if (and vs (>! ch (first vs)))
|
||||
(recur (next vs))
|
||||
(when close?
|
||||
(close! ch))))))
|
||||
|
||||
|
||||
(defn to-chan
|
||||
"Creates and returns a channel which contains the contents of coll,
|
||||
closing when exhausted."
|
||||
[coll]
|
||||
(let [ch (chan (bounded-count 100 coll))]
|
||||
(onto-chan ch coll)
|
||||
ch))
|
||||
|
||||
|
||||
(defprotocol Mux
|
||||
(muxch* [_]))
|
||||
|
||||
(defprotocol Mult
|
||||
(tap* [m ch close?])
|
||||
(untap* [m ch])
|
||||
(untap-all* [m]))
|
||||
|
||||
(defn mult
|
||||
"Creates and returns a mult(iple) of the supplied channel. Channels
|
||||
containing copies of the channel can be created with 'tap', and
|
||||
detached with 'untap'.
|
||||
|
||||
Each item is distributed to all taps in parallel and synchronously,
|
||||
i.e. each tap must accept before the next item is distributed. Use
|
||||
buffering/windowing to prevent slow taps from holding up the mult.
|
||||
|
||||
Items received when there are no taps get dropped.
|
||||
|
||||
If a tap puts to a closed channel, it will be removed from the mult."
|
||||
[ch]
|
||||
(let [cs (atom {}) ;;ch->close?
|
||||
m (reify
|
||||
Mux
|
||||
(muxch* [_] ch)
|
||||
|
||||
Mult
|
||||
(tap* [_ ch close?] (swap! cs assoc ch close?) nil)
|
||||
(untap* [_ ch] (swap! cs dissoc ch) nil)
|
||||
(untap-all* [_] (reset! cs {}) nil))
|
||||
dchan (chan 1)
|
||||
dctr (atom nil)
|
||||
done (fn [_] (when (zero? (swap! dctr dec))
|
||||
(put! dchan true)))]
|
||||
(go-loop []
|
||||
(let [val (<! ch)]
|
||||
(if (nil? val)
|
||||
(doseq [[c close?] @cs]
|
||||
(when close? (close! c)))
|
||||
(let [chs (keys @cs)]
|
||||
(reset! dctr (count chs))
|
||||
(doseq [c chs]
|
||||
(when-not (put! c val done)
|
||||
(done nil)
|
||||
(untap* m c)))
|
||||
;;wait for all
|
||||
(when (seq chs)
|
||||
(<! dchan))
|
||||
(recur)))))
|
||||
m))
|
||||
|
||||
(defn tap
|
||||
"Copies the mult source onto the supplied channel.
|
||||
|
||||
By default the channel will be closed when the source closes,
|
||||
but can be determined by the close? parameter."
|
||||
([mult ch] (tap mult ch true))
|
||||
([mult ch close?] (tap* mult ch close?) ch))
|
||||
|
||||
(defn untap
|
||||
"Disconnects a target channel from a mult"
|
||||
[mult ch]
|
||||
(untap* mult ch))
|
||||
|
||||
(defn untap-all
|
||||
"Disconnects all target channels from a mult"
|
||||
[mult] (untap-all* mult))
|
||||
|
||||
(defprotocol Mix
|
||||
(admix* [m ch])
|
||||
(unmix* [m ch])
|
||||
(unmix-all* [m])
|
||||
(toggle* [m state-map])
|
||||
(solo-mode* [m mode]))
|
||||
|
||||
(defn ioc-alts! [state cont-block ports & {:as opts}]
|
||||
(ioc/aset-all! state helpers/STATE-IDX cont-block)
|
||||
(when-let [cb (cljs.core.async/do-alts
|
||||
(fn [val]
|
||||
(ioc/aset-all! state helpers/VALUE-IDX val)
|
||||
(helpers/run-state-machine-wrapped state))
|
||||
ports
|
||||
opts)]
|
||||
(ioc/aset-all! state helpers/VALUE-IDX @cb)
|
||||
:recur))
|
||||
|
||||
(defn mix
|
||||
"Creates and returns a mix of one or more input channels which will
|
||||
be put on the supplied out channel. Input sources can be added to
|
||||
the mix with 'admix', and removed with 'unmix'. A mix supports
|
||||
soloing, muting and pausing multiple inputs atomically using
|
||||
'toggle', and can solo using either muting or pausing as determined
|
||||
by 'solo-mode'.
|
||||
|
||||
Each channel can have zero or more boolean modes set via 'toggle':
|
||||
|
||||
:solo - when true, only this (ond other soloed) channel(s) will appear
|
||||
in the mix output channel. :mute and :pause states of soloed
|
||||
channels are ignored. If solo-mode is :mute, non-soloed
|
||||
channels are muted, if :pause, non-soloed channels are
|
||||
paused.
|
||||
|
||||
:mute - muted channels will have their contents consumed but not included in the mix
|
||||
:pause - paused channels will not have their contents consumed (and thus also not included in the mix)
|
||||
"
|
||||
[out]
|
||||
(let [cs (atom {}) ;;ch->attrs-map
|
||||
solo-modes #{:mute :pause}
|
||||
attrs (conj solo-modes :solo)
|
||||
solo-mode (atom :mute)
|
||||
change (chan)
|
||||
changed #(put! change true)
|
||||
pick (fn [attr chs]
|
||||
(reduce-kv
|
||||
(fn [ret c v]
|
||||
(if (attr v)
|
||||
(conj ret c)
|
||||
ret))
|
||||
#{} chs))
|
||||
calc-state (fn []
|
||||
(let [chs @cs
|
||||
mode @solo-mode
|
||||
solos (pick :solo chs)
|
||||
pauses (pick :pause chs)]
|
||||
{:solos solos
|
||||
:mutes (pick :mute chs)
|
||||
:reads (conj
|
||||
(if (and (= mode :pause) (not (empty? solos)))
|
||||
(vec solos)
|
||||
(vec (remove pauses (keys chs))))
|
||||
change)}))
|
||||
m (reify
|
||||
Mux
|
||||
(muxch* [_] out)
|
||||
Mix
|
||||
(admix* [_ ch] (swap! cs assoc ch {}) (changed))
|
||||
(unmix* [_ ch] (swap! cs dissoc ch) (changed))
|
||||
(unmix-all* [_] (reset! cs {}) (changed))
|
||||
(toggle* [_ state-map] (swap! cs (partial merge-with cljs.core/merge) state-map) (changed))
|
||||
(solo-mode* [_ mode]
|
||||
(assert (solo-modes mode) (str "mode must be one of: " solo-modes))
|
||||
(reset! solo-mode mode)
|
||||
(changed)))]
|
||||
(go-loop [{:keys [solos mutes reads] :as state} (calc-state)]
|
||||
(let [[v c] (alts! reads)]
|
||||
(if (or (nil? v) (= c change))
|
||||
(do (when (nil? v)
|
||||
(swap! cs dissoc c))
|
||||
(recur (calc-state)))
|
||||
(if (or (solos c)
|
||||
(and (empty? solos) (not (mutes c))))
|
||||
(when (>! out v)
|
||||
(recur state))
|
||||
(recur state)))))
|
||||
m))
|
||||
|
||||
(defn admix
|
||||
"Adds ch as an input to the mix"
|
||||
[mix ch]
|
||||
(admix* mix ch))
|
||||
|
||||
(defn unmix
|
||||
"Removes ch as an input to the mix"
|
||||
[mix ch]
|
||||
(unmix* mix ch))
|
||||
|
||||
(defn unmix-all
|
||||
"removes all inputs from the mix"
|
||||
[mix]
|
||||
(unmix-all* mix))
|
||||
|
||||
(defn toggle
|
||||
"Atomically sets the state(s) of one or more channels in a mix. The
|
||||
state map is a map of channels -> channel-state-map. A
|
||||
channel-state-map is a map of attrs -> boolean, where attr is one or
|
||||
more of :mute, :pause or :solo. Any states supplied are merged with
|
||||
the current state.
|
||||
|
||||
Note that channels can be added to a mix via toggle, which can be
|
||||
used to add channels in a particular (e.g. paused) state."
|
||||
[mix state-map]
|
||||
(toggle* mix state-map))
|
||||
|
||||
(defn solo-mode
|
||||
"Sets the solo mode of the mix. mode must be one of :mute or :pause"
|
||||
[mix mode]
|
||||
(solo-mode* mix mode))
|
||||
|
||||
|
||||
(defprotocol Pub
|
||||
(sub* [p v ch close?])
|
||||
(unsub* [p v ch])
|
||||
(unsub-all* [p] [p v]))
|
||||
|
||||
(defn pub
|
||||
"Creates and returns a pub(lication) of the supplied channel,
|
||||
partitioned into topics by the topic-fn. topic-fn will be applied to
|
||||
each value on the channel and the result will determine the 'topic'
|
||||
on which that value will be put. Channels can be subscribed to
|
||||
receive copies of topics using 'sub', and unsubscribed using
|
||||
'unsub'. Each topic will be handled by an internal mult on a
|
||||
dedicated channel. By default these internal channels are
|
||||
unbuffered, but a buf-fn can be supplied which, given a topic,
|
||||
creates a buffer with desired properties.
|
||||
|
||||
Each item is distributed to all subs in parallel and synchronously,
|
||||
i.e. each sub must accept before the next item is distributed. Use
|
||||
buffering/windowing to prevent slow subs from holding up the pub.
|
||||
|
||||
Items received when there are no matching subs get dropped.
|
||||
|
||||
Note that if buf-fns are used then each topic is handled
|
||||
asynchronously, i.e. if a channel is subscribed to more than one
|
||||
topic it should not expect them to be interleaved identically with
|
||||
the source."
|
||||
([ch topic-fn] (pub ch topic-fn (constantly nil)))
|
||||
([ch topic-fn buf-fn]
|
||||
(let [mults (atom {}) ;;topic->mult
|
||||
ensure-mult (fn [topic]
|
||||
(or (get @mults topic)
|
||||
(get (swap! mults
|
||||
#(if (% topic) % (assoc % topic (mult (chan (buf-fn topic))))))
|
||||
topic)))
|
||||
p (reify
|
||||
Mux
|
||||
(muxch* [_] ch)
|
||||
|
||||
Pub
|
||||
(sub* [p topic ch close?]
|
||||
(let [m (ensure-mult topic)]
|
||||
(tap m ch close?)))
|
||||
(unsub* [p topic ch]
|
||||
(when-let [m (get @mults topic)]
|
||||
(untap m ch)))
|
||||
(unsub-all* [_] (reset! mults {}))
|
||||
(unsub-all* [_ topic] (swap! mults dissoc topic)))]
|
||||
(go-loop []
|
||||
(let [val (<! ch)]
|
||||
(if (nil? val)
|
||||
(doseq [m (vals @mults)]
|
||||
(close! (muxch* m)))
|
||||
(let [topic (topic-fn val)
|
||||
m (get @mults topic)]
|
||||
(when m
|
||||
(when-not (>! (muxch* m) val)
|
||||
(swap! mults dissoc topic)))
|
||||
(recur)))))
|
||||
p)))
|
||||
|
||||
(defn sub
|
||||
"Subscribes a channel to a topic of a pub.
|
||||
|
||||
By default the channel will be closed when the source closes,
|
||||
but can be determined by the close? parameter."
|
||||
([p topic ch] (sub p topic ch true))
|
||||
([p topic ch close?] (sub* p topic ch close?)))
|
||||
|
||||
(defn unsub
|
||||
"Unsubscribes a channel from a topic of a pub"
|
||||
[p topic ch]
|
||||
(unsub* p topic ch))
|
||||
|
||||
(defn unsub-all
|
||||
"Unsubscribes all channels from a pub, or a topic of a pub"
|
||||
([p] (unsub-all* p))
|
||||
([p topic] (unsub-all* p topic)))
|
||||
|
||||
|
||||
;;;;
|
||||
|
||||
(defn map
|
||||
"Takes a function and a collection of source channels, and returns a
|
||||
channel which contains the values produced by applying f to the set
|
||||
of first items taken from each source channel, followed by applying
|
||||
f to the set of second items from each channel, until any one of the
|
||||
channels is closed, at which point the output channel will be
|
||||
closed. The returned channel will be unbuffered by default, or a
|
||||
buf-or-n can be supplied"
|
||||
([f chs] (map f chs nil))
|
||||
([f chs buf-or-n]
|
||||
(let [chs (vec chs)
|
||||
out (chan buf-or-n)
|
||||
cnt (count chs)
|
||||
rets (object-array cnt)
|
||||
dchan (chan 1)
|
||||
dctr (atom nil)
|
||||
done (mapv (fn [i]
|
||||
(fn [ret]
|
||||
(aset rets i ret)
|
||||
(when (zero? (swap! dctr dec))
|
||||
(put! dchan (.slice rets 0)))))
|
||||
(range cnt))]
|
||||
(go-loop []
|
||||
(reset! dctr cnt)
|
||||
(dotimes [i cnt]
|
||||
(try
|
||||
(take! (chs i) (done i))
|
||||
(catch js/Object e
|
||||
(swap! dctr dec))))
|
||||
(let [rets (<! dchan)]
|
||||
(if (some nil? rets)
|
||||
(close! out)
|
||||
(do (>! out (apply f rets))
|
||||
(recur)))))
|
||||
out)))
|
||||
|
||||
(defn merge
|
||||
"Takes a collection of source channels and returns a channel which
|
||||
contains all values taken from them. The returned channel will be
|
||||
unbuffered by default, or a buf-or-n can be supplied. The channel
|
||||
will close after all the source channels have closed."
|
||||
([chs] (merge chs nil))
|
||||
([chs buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(go-loop [cs (vec chs)]
|
||||
(if (pos? (count cs))
|
||||
(let [[v c] (alts! cs)]
|
||||
(if (nil? v)
|
||||
(recur (filterv #(not= c %) cs))
|
||||
(do (>! out v)
|
||||
(recur cs))))
|
||||
(close! out)))
|
||||
out)))
|
||||
|
||||
(defn into
|
||||
"Returns a channel containing the single (collection) result of the
|
||||
items taken from the channel conjoined to the supplied
|
||||
collection. ch must close before into produces a result."
|
||||
[coll ch]
|
||||
(reduce conj coll ch))
|
||||
|
||||
(defn take
|
||||
"Returns a channel that will return, at most, n items from ch. After n items
|
||||
have been returned, or ch has been closed, the return chanel will close.
|
||||
|
||||
The output channel is unbuffered by default, unless buf-or-n is given."
|
||||
([n ch]
|
||||
(take n ch nil))
|
||||
([n ch buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(go (loop [x 0]
|
||||
(when (< x n)
|
||||
(let [v (<! ch)]
|
||||
(when (not (nil? v))
|
||||
(>! out v)
|
||||
(recur (inc x))))))
|
||||
(close! out))
|
||||
out)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; deprecated - do not use ;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn map<
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
[f ch]
|
||||
(reify
|
||||
impl/Channel
|
||||
(close! [_] (impl/close! ch))
|
||||
(closed? [_] (impl/closed? ch))
|
||||
|
||||
impl/ReadPort
|
||||
(take! [_ fn1]
|
||||
(let [ret
|
||||
(impl/take! ch
|
||||
(reify
|
||||
impl/Handler
|
||||
(active? [_] (impl/active? fn1))
|
||||
#_(lock-id [_] (impl/lock-id fn1))
|
||||
(commit [_]
|
||||
(let [f1 (impl/commit fn1)]
|
||||
#(f1 (if (nil? %) nil (f %)))))))]
|
||||
(if (and ret (not (nil? @ret)))
|
||||
(channels/box (f @ret))
|
||||
ret)))
|
||||
|
||||
impl/WritePort
|
||||
(put! [_ val fn1] (impl/put! ch val fn1))))
|
||||
|
||||
(defn map>
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
[f ch]
|
||||
(reify
|
||||
impl/Channel
|
||||
(close! [_] (impl/close! ch))
|
||||
|
||||
impl/ReadPort
|
||||
(take! [_ fn1] (impl/take! ch fn1))
|
||||
|
||||
impl/WritePort
|
||||
(put! [_ val fn1]
|
||||
(impl/put! ch (f val) fn1))))
|
||||
|
||||
(defn filter>
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
[p ch]
|
||||
(reify
|
||||
impl/Channel
|
||||
(close! [_] (impl/close! ch))
|
||||
(closed? [_] (impl/closed? ch))
|
||||
|
||||
impl/ReadPort
|
||||
(take! [_ fn1] (impl/take! ch fn1))
|
||||
|
||||
impl/WritePort
|
||||
(put! [_ val fn1]
|
||||
(if (p val)
|
||||
(impl/put! ch val fn1)
|
||||
(channels/box (not (impl/closed? ch)))))))
|
||||
|
||||
(defn remove>
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
[p ch]
|
||||
(filter> (complement p) ch))
|
||||
|
||||
(defn filter<
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([p ch] (filter< p ch nil))
|
||||
([p ch buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(go-loop []
|
||||
(let [val (<! ch)]
|
||||
(if (nil? val)
|
||||
(close! out)
|
||||
(do (when (p val)
|
||||
(>! out val))
|
||||
(recur)))))
|
||||
out)))
|
||||
|
||||
(defn remove<
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([p ch] (remove< p ch nil))
|
||||
([p ch buf-or-n] (filter< (complement p) ch buf-or-n)))
|
||||
|
||||
(defn- mapcat* [f in out]
|
||||
(go-loop []
|
||||
(let [val (<! in)]
|
||||
(if (nil? val)
|
||||
(close! out)
|
||||
(do (doseq [v (f val)]
|
||||
(>! out v))
|
||||
(when-not (impl/closed? out)
|
||||
(recur)))))))
|
||||
|
||||
(defn mapcat<
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([f in] (mapcat< f in nil))
|
||||
([f in buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(mapcat* f in out)
|
||||
out)))
|
||||
|
||||
(defn mapcat>
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([f out] (mapcat> f out nil))
|
||||
([f out buf-or-n]
|
||||
(let [in (chan buf-or-n)]
|
||||
(mapcat* f in out)
|
||||
in)))
|
||||
|
||||
(defn unique
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([ch]
|
||||
(unique ch nil))
|
||||
([ch buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(go (loop [last nil]
|
||||
(let [v (<! ch)]
|
||||
(when (not (nil? v))
|
||||
(if (= v last)
|
||||
(recur last)
|
||||
(do (>! out v)
|
||||
(recur v))))))
|
||||
(close! out))
|
||||
out)))
|
||||
|
||||
(defn partition
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([n ch]
|
||||
(partition n ch nil))
|
||||
([n ch buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(go (loop [arr (make-array n)
|
||||
idx 0]
|
||||
(let [v (<! ch)]
|
||||
(if (not (nil? v))
|
||||
(do (aset ^objects arr idx v)
|
||||
(let [new-idx (inc idx)]
|
||||
(if (< new-idx n)
|
||||
(recur arr new-idx)
|
||||
(do (>! out (vec arr))
|
||||
(recur (make-array n) 0)))))
|
||||
(do (when (> idx 0)
|
||||
(>! out (vec arr)))
|
||||
(close! out))))))
|
||||
out)))
|
||||
|
||||
|
||||
(defn partition-by
|
||||
"Deprecated - this function will be removed. Use transducer instead"
|
||||
([f ch]
|
||||
(partition-by f ch nil))
|
||||
([f ch buf-or-n]
|
||||
(let [out (chan buf-or-n)]
|
||||
(go (loop [lst (make-array 0)
|
||||
last ::nothing]
|
||||
(let [v (<! ch)]
|
||||
(if (not (nil? v))
|
||||
(let [new-itm (f v)]
|
||||
(if (or (= new-itm last)
|
||||
(keyword-identical? last ::nothing))
|
||||
(do (.push lst v)
|
||||
(recur lst new-itm))
|
||||
(do (>! out (vec lst))
|
||||
(let [new-lst (make-array 0)]
|
||||
(.push new-lst v)
|
||||
(recur new-lst new-itm)))))
|
||||
(do (when (> (alength lst) 0)
|
||||
(>! out (vec lst)))
|
||||
(close! out))))))
|
||||
out)))
|
||||
Executable
+8486
File diff suppressed because it is too large
Load Diff
Executable
+131
@@ -0,0 +1,131 @@
|
||||
;; Copyright (c) Rich Hickey and contributors. All rights reserved.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.core.async.impl.buffers
|
||||
(:require [cljs.core.async.impl.protocols :as impl]))
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
;; DO NOT USE, this is internal buffer representation
|
||||
|
||||
(defn acopy [src src-start dest dest-start len]
|
||||
(loop [cnt 0]
|
||||
(when (< cnt len)
|
||||
(aset dest
|
||||
(+ dest-start cnt)
|
||||
(aget src (+ src-start cnt)))
|
||||
(recur (inc cnt)))))
|
||||
|
||||
(deftype RingBuffer [^:mutable head ^:mutable tail ^:mutable length ^:mutable arr]
|
||||
Object
|
||||
(pop [_]
|
||||
(when-not (zero? length)
|
||||
(let [x (aget arr tail)]
|
||||
(aset arr tail nil)
|
||||
(set! tail (js-mod (inc tail) (alength arr)))
|
||||
(set! length (dec length))
|
||||
x)))
|
||||
|
||||
(unshift [_ x]
|
||||
(aset arr head x)
|
||||
(set! head (js-mod (inc head) (alength arr)))
|
||||
(set! length (inc length))
|
||||
nil)
|
||||
|
||||
(unbounded-unshift [this x]
|
||||
(if (== (inc length) (alength arr))
|
||||
(.resize this))
|
||||
(.unshift this x))
|
||||
|
||||
;; Doubles the size of the buffer while retaining all the existing values
|
||||
(resize
|
||||
[_]
|
||||
(let [new-arr-size (* (alength arr) 2)
|
||||
new-arr (make-array new-arr-size)]
|
||||
(cond
|
||||
(< tail head)
|
||||
(do (acopy arr tail new-arr 0 length)
|
||||
(set! tail 0)
|
||||
(set! head length)
|
||||
(set! arr new-arr))
|
||||
|
||||
(> tail head)
|
||||
(do (acopy arr tail new-arr 0 (- (alength arr) tail))
|
||||
(acopy arr 0 new-arr (- (alength arr) tail) head)
|
||||
(set! tail 0)
|
||||
(set! head length)
|
||||
(set! arr new-arr))
|
||||
|
||||
(== tail head)
|
||||
(do (set! tail 0)
|
||||
(set! head 0)
|
||||
(set! arr new-arr)))))
|
||||
|
||||
(cleanup [this keep?]
|
||||
(dotimes [x length]
|
||||
(let [v (.pop this)]
|
||||
(when ^boolean (keep? v)
|
||||
(.unshift this v))))))
|
||||
|
||||
(defn ring-buffer [n]
|
||||
(assert (> n 0) "Can't create a ring buffer of size 0")
|
||||
(RingBuffer. 0 0 0 (make-array n)))
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
|
||||
(deftype FixedBuffer [buf n]
|
||||
impl/Buffer
|
||||
(full? [this]
|
||||
(== (.-length buf) n))
|
||||
(remove! [this]
|
||||
(.pop buf))
|
||||
(add!* [this itm]
|
||||
(.unbounded-unshift buf itm)
|
||||
this)
|
||||
cljs.core/ICounted
|
||||
(-count [this]
|
||||
(.-length buf)))
|
||||
|
||||
(defn fixed-buffer [n]
|
||||
(FixedBuffer. (ring-buffer n) n))
|
||||
|
||||
(deftype DroppingBuffer [buf n]
|
||||
impl/UnblockingBuffer
|
||||
impl/Buffer
|
||||
(full? [this]
|
||||
false)
|
||||
(remove! [this]
|
||||
(.pop buf))
|
||||
(add!* [this itm]
|
||||
(when-not (== (.-length buf) n)
|
||||
(.unshift buf itm))
|
||||
this)
|
||||
cljs.core/ICounted
|
||||
(-count [this]
|
||||
(.-length buf)))
|
||||
|
||||
(defn dropping-buffer [n]
|
||||
(DroppingBuffer. (ring-buffer n) n))
|
||||
|
||||
(deftype SlidingBuffer [buf n]
|
||||
impl/UnblockingBuffer
|
||||
impl/Buffer
|
||||
(full? [this]
|
||||
false)
|
||||
(remove! [this]
|
||||
(.pop buf))
|
||||
(add!* [this itm]
|
||||
(when (== (.-length buf) n)
|
||||
(impl/remove! this))
|
||||
(.unshift buf itm)
|
||||
this)
|
||||
cljs.core/ICounted
|
||||
(-count [this]
|
||||
(.-length buf)))
|
||||
|
||||
(defn sliding-buffer [n]
|
||||
(SlidingBuffer. (ring-buffer n) n))
|
||||
Executable
+359
@@ -0,0 +1,359 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.core.async.impl.buffers');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.core.async.impl.protocols');
|
||||
cljs.core.async.impl.buffers.acopy = (function cljs$core$async$impl$buffers$acopy(src,src_start,dest,dest_start,len){
|
||||
var cnt = (0);
|
||||
while(true){
|
||||
if((cnt < len)){
|
||||
(dest[(dest_start + cnt)] = (src[(src_start + cnt)]));
|
||||
|
||||
var G__5703 = (cnt + (1));
|
||||
cnt = G__5703;
|
||||
continue;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.async.impl.buffers.Object}
|
||||
*/
|
||||
cljs.core.async.impl.buffers.RingBuffer = (function (head,tail,length,arr){
|
||||
this.head = head;
|
||||
this.tail = tail;
|
||||
this.length = length;
|
||||
this.arr = arr;
|
||||
});
|
||||
(cljs.core.async.impl.buffers.RingBuffer.prototype.pop = (function (){
|
||||
var self__ = this;
|
||||
var _ = this;
|
||||
if((self__.length === (0))){
|
||||
return null;
|
||||
} else {
|
||||
var x = (self__.arr[self__.tail]);
|
||||
(self__.arr[self__.tail] = null);
|
||||
|
||||
(self__.tail = ((self__.tail + (1)) % self__.arr.length));
|
||||
|
||||
(self__.length = (self__.length - (1)));
|
||||
|
||||
return x;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.prototype.unshift = (function (x){
|
||||
var self__ = this;
|
||||
var _ = this;
|
||||
(self__.arr[self__.head] = x);
|
||||
|
||||
(self__.head = ((self__.head + (1)) % self__.arr.length));
|
||||
|
||||
(self__.length = (self__.length + (1)));
|
||||
|
||||
return null;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.prototype.unbounded_unshift = (function (x){
|
||||
var self__ = this;
|
||||
var this$ = this;
|
||||
if(((self__.length + (1)) === self__.arr.length)){
|
||||
this$.resize();
|
||||
} else {
|
||||
}
|
||||
|
||||
return this$.unshift(x);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.prototype.resize = (function (){
|
||||
var self__ = this;
|
||||
var _ = this;
|
||||
var new_arr_size = (self__.arr.length * (2));
|
||||
var new_arr = (new Array(new_arr_size));
|
||||
if((self__.tail < self__.head)){
|
||||
cljs.core.async.impl.buffers.acopy(self__.arr,self__.tail,new_arr,(0),self__.length);
|
||||
|
||||
(self__.tail = (0));
|
||||
|
||||
(self__.head = self__.length);
|
||||
|
||||
return (self__.arr = new_arr);
|
||||
} else {
|
||||
if((self__.tail > self__.head)){
|
||||
cljs.core.async.impl.buffers.acopy(self__.arr,self__.tail,new_arr,(0),(self__.arr.length - self__.tail));
|
||||
|
||||
cljs.core.async.impl.buffers.acopy(self__.arr,(0),new_arr,(self__.arr.length - self__.tail),self__.head);
|
||||
|
||||
(self__.tail = (0));
|
||||
|
||||
(self__.head = self__.length);
|
||||
|
||||
return (self__.arr = new_arr);
|
||||
} else {
|
||||
if((self__.tail === self__.head)){
|
||||
(self__.tail = (0));
|
||||
|
||||
(self__.head = (0));
|
||||
|
||||
return (self__.arr = new_arr);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.prototype.cleanup = (function (keep_QMARK_){
|
||||
var self__ = this;
|
||||
var this$ = this;
|
||||
var n__5636__auto__ = self__.length;
|
||||
var x = (0);
|
||||
while(true){
|
||||
if((x < n__5636__auto__)){
|
||||
var v_5704 = this$.pop();
|
||||
if((keep_QMARK_.cljs$core$IFn$_invoke$arity$1 ? keep_QMARK_.cljs$core$IFn$_invoke$arity$1(v_5704) : keep_QMARK_.call(null,v_5704))){
|
||||
this$.unshift(v_5704);
|
||||
} else {
|
||||
}
|
||||
|
||||
var G__5705 = (x + (1));
|
||||
x = G__5705;
|
||||
continue;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 4, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.with_meta(cljs.core.cst$sym$head,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$tail,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$length,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$arr,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null))], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.cljs$lang$ctorStr = "cljs.core.async.impl.buffers/RingBuffer");
|
||||
|
||||
(cljs.core.async.impl.buffers.RingBuffer.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.buffers/RingBuffer");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.buffers/RingBuffer.
|
||||
*/
|
||||
cljs.core.async.impl.buffers.__GT_RingBuffer = (function cljs$core$async$impl$buffers$__GT_RingBuffer(head,tail,length,arr){
|
||||
return (new cljs.core.async.impl.buffers.RingBuffer(head,tail,length,arr));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.buffers.ring_buffer = (function cljs$core$async$impl$buffers$ring_buffer(n){
|
||||
if((n > (0))){
|
||||
} else {
|
||||
throw (new Error(["Assert failed: ","Can't create a ring buffer of size 0","\n","(> n 0)"].join('')));
|
||||
}
|
||||
|
||||
return (new cljs.core.async.impl.buffers.RingBuffer((0),(0),(0),(new Array(n))));
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.ICounted}
|
||||
* @implements {cljs.core.async.impl.protocols.Buffer}
|
||||
*/
|
||||
cljs.core.async.impl.buffers.FixedBuffer = (function (buf,n){
|
||||
this.buf = buf;
|
||||
this.n = n;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.prototype.cljs$core$async$impl$protocols$Buffer$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.prototype.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return (self__.buf.length === self__.n);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.prototype.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return self__.buf.pop();
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.prototype.cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$arity$2 = (function (this$,itm){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
self__.buf.unbounded_unshift(itm);
|
||||
|
||||
return this$__$1;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.prototype.cljs$core$ICounted$_count$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return self__.buf.length;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$buf,cljs.core.cst$sym$n], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.cljs$lang$ctorStr = "cljs.core.async.impl.buffers/FixedBuffer");
|
||||
|
||||
(cljs.core.async.impl.buffers.FixedBuffer.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.buffers/FixedBuffer");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.buffers/FixedBuffer.
|
||||
*/
|
||||
cljs.core.async.impl.buffers.__GT_FixedBuffer = (function cljs$core$async$impl$buffers$__GT_FixedBuffer(buf,n){
|
||||
return (new cljs.core.async.impl.buffers.FixedBuffer(buf,n));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.buffers.fixed_buffer = (function cljs$core$async$impl$buffers$fixed_buffer(n){
|
||||
return (new cljs.core.async.impl.buffers.FixedBuffer(cljs.core.async.impl.buffers.ring_buffer(n),n));
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.ICounted}
|
||||
* @implements {cljs.core.async.impl.protocols.UnblockingBuffer}
|
||||
* @implements {cljs.core.async.impl.protocols.Buffer}
|
||||
*/
|
||||
cljs.core.async.impl.buffers.DroppingBuffer = (function (buf,n){
|
||||
this.buf = buf;
|
||||
this.n = n;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.prototype.cljs$core$async$impl$protocols$UnblockingBuffer$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return false;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return self__.buf.pop();
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$arity$2 = (function (this$,itm){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
if((self__.buf.length === self__.n)){
|
||||
} else {
|
||||
self__.buf.unshift(itm);
|
||||
}
|
||||
|
||||
return this$__$1;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.prototype.cljs$core$ICounted$_count$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return self__.buf.length;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$buf,cljs.core.cst$sym$n], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.cljs$lang$ctorStr = "cljs.core.async.impl.buffers/DroppingBuffer");
|
||||
|
||||
(cljs.core.async.impl.buffers.DroppingBuffer.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.buffers/DroppingBuffer");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.buffers/DroppingBuffer.
|
||||
*/
|
||||
cljs.core.async.impl.buffers.__GT_DroppingBuffer = (function cljs$core$async$impl$buffers$__GT_DroppingBuffer(buf,n){
|
||||
return (new cljs.core.async.impl.buffers.DroppingBuffer(buf,n));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.buffers.dropping_buffer = (function cljs$core$async$impl$buffers$dropping_buffer(n){
|
||||
return (new cljs.core.async.impl.buffers.DroppingBuffer(cljs.core.async.impl.buffers.ring_buffer(n),n));
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.ICounted}
|
||||
* @implements {cljs.core.async.impl.protocols.UnblockingBuffer}
|
||||
* @implements {cljs.core.async.impl.protocols.Buffer}
|
||||
*/
|
||||
cljs.core.async.impl.buffers.SlidingBuffer = (function (buf,n){
|
||||
this.buf = buf;
|
||||
this.n = n;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.prototype.cljs$core$async$impl$protocols$UnblockingBuffer$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return false;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return self__.buf.pop();
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.prototype.cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$arity$2 = (function (this$,itm){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
if((self__.buf.length === self__.n)){
|
||||
this$__$1.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1(null);
|
||||
} else {
|
||||
}
|
||||
|
||||
self__.buf.unshift(itm);
|
||||
|
||||
return this$__$1;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.prototype.cljs$core$ICounted$_count$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
return self__.buf.length;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$buf,cljs.core.cst$sym$n], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.cljs$lang$ctorStr = "cljs.core.async.impl.buffers/SlidingBuffer");
|
||||
|
||||
(cljs.core.async.impl.buffers.SlidingBuffer.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.buffers/SlidingBuffer");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.buffers/SlidingBuffer.
|
||||
*/
|
||||
cljs.core.async.impl.buffers.__GT_SlidingBuffer = (function cljs$core$async$impl$buffers$__GT_SlidingBuffer(buf,n){
|
||||
return (new cljs.core.async.impl.buffers.SlidingBuffer(buf,n));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.buffers.sliding_buffer = (function cljs$core$async$impl$buffers$sliding_buffer(n){
|
||||
return (new cljs.core.async.impl.buffers.SlidingBuffer(cljs.core.async.impl.buffers.ring_buffer(n),n));
|
||||
});
|
||||
Executable
+182
@@ -0,0 +1,182 @@
|
||||
;; Copyright (c) Rich Hickey and contributors. All rights reserved.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.core.async.impl.channels
|
||||
(:require [cljs.core.async.impl.protocols :as impl]
|
||||
[cljs.core.async.impl.dispatch :as dispatch]
|
||||
[cljs.core.async.impl.buffers :as buffers]))
|
||||
|
||||
|
||||
|
||||
(defn box [val]
|
||||
(reify cljs.core/IDeref
|
||||
(-deref [_] val)))
|
||||
|
||||
(deftype PutBox [handler val])
|
||||
|
||||
(defn put-active? [box]
|
||||
(impl/active? (.-handler box)))
|
||||
|
||||
(def ^:const MAX_DIRTY 64)
|
||||
|
||||
(defprotocol MMC
|
||||
(abort [this]))
|
||||
|
||||
(deftype ManyToManyChannel [takes ^:mutable dirty-takes puts ^:mutable dirty-puts ^not-native buf ^:mutable closed add!]
|
||||
MMC
|
||||
(abort [this]
|
||||
(loop []
|
||||
(let [putter (.pop puts)]
|
||||
(when-not (nil? putter)
|
||||
(let [^not-native put-handler (.-handler putter)
|
||||
val (.-val putter)]
|
||||
(if ^boolean (impl/active? put-handler)
|
||||
(let [put-cb (impl/commit put-handler)]
|
||||
(dispatch/run #(put-cb true)))
|
||||
(recur))))))
|
||||
(.cleanup puts (constantly false))
|
||||
(impl/close! this))
|
||||
impl/WritePort
|
||||
(put! [this val ^not-native handler]
|
||||
(assert (not (nil? val)) "Can't put nil in on a channel")
|
||||
;; bug in CLJS compiler boolean inference - David
|
||||
(let [^boolean closed closed]
|
||||
(if (or closed (not ^boolean (impl/active? handler)))
|
||||
(box (not closed))
|
||||
(if (and buf (not (impl/full? buf)))
|
||||
(do
|
||||
(impl/commit handler)
|
||||
(let [done? (reduced? (add! buf val))]
|
||||
(loop []
|
||||
(when (and (pos? (.-length takes)) (pos? (count buf)))
|
||||
(let [^not-native taker (.pop takes)]
|
||||
(if ^boolean (impl/active? taker)
|
||||
(let [take-cb (impl/commit taker)
|
||||
val (impl/remove! buf)]
|
||||
(dispatch/run (fn [] (take-cb val))))
|
||||
(recur)))))
|
||||
(when done? (abort this))
|
||||
(box true)))
|
||||
(let [taker (loop []
|
||||
(let [^not-native taker (.pop takes)]
|
||||
(when taker
|
||||
(if (impl/active? taker)
|
||||
taker
|
||||
(recur)))))]
|
||||
(if taker
|
||||
(let [take-cb (impl/commit taker)]
|
||||
(impl/commit handler)
|
||||
(dispatch/run (fn [] (take-cb val)))
|
||||
(box true))
|
||||
(do
|
||||
(if (> dirty-puts MAX_DIRTY)
|
||||
(do (set! dirty-puts 0)
|
||||
(.cleanup puts put-active?))
|
||||
(set! dirty-puts (inc dirty-puts)))
|
||||
(assert (< (.-length puts) impl/MAX-QUEUE-SIZE)
|
||||
(str "No more than " impl/MAX-QUEUE-SIZE
|
||||
" pending puts are allowed on a single channel."
|
||||
" Consider using a windowed buffer."))
|
||||
(.unbounded-unshift puts (PutBox. handler val))
|
||||
nil)))))))
|
||||
impl/ReadPort
|
||||
(take! [this ^not-native handler]
|
||||
(if (not ^boolean (impl/active? handler))
|
||||
nil
|
||||
(if (and (not (nil? buf)) (pos? (count buf)))
|
||||
(let [_ (impl/commit handler)
|
||||
retval (box (impl/remove! buf))]
|
||||
(loop []
|
||||
(when-not (impl/full? buf)
|
||||
(let [putter (.pop puts)]
|
||||
(when-not (nil? putter)
|
||||
(let [^not-native put-handler (.-handler putter)
|
||||
val (.-val putter)]
|
||||
(when ^boolean (impl/active? put-handler)
|
||||
(let [put-cb (impl/commit put-handler)]
|
||||
(impl/commit handler)
|
||||
(dispatch/run #(put-cb true))
|
||||
(when (reduced? (add! buf val))
|
||||
(abort this)))))
|
||||
(recur)))))
|
||||
retval)
|
||||
(let [putter (loop []
|
||||
(let [putter (.pop puts)]
|
||||
(when putter
|
||||
(if ^boolean (impl/active? (.-handler putter))
|
||||
putter
|
||||
(recur)))))]
|
||||
(if putter
|
||||
(let [put-cb (impl/commit (.-handler putter))]
|
||||
(impl/commit handler)
|
||||
(dispatch/run #(put-cb true))
|
||||
(box (.-val putter)))
|
||||
(if closed
|
||||
(do
|
||||
(when buf (add! buf))
|
||||
(if (and (impl/active? handler) (impl/commit handler))
|
||||
(let [has-val (and buf (pos? (count buf)))]
|
||||
(let [val (when has-val (impl/remove! buf))]
|
||||
(box val)))
|
||||
nil))
|
||||
(do
|
||||
(if (> dirty-takes MAX_DIRTY)
|
||||
(do (set! dirty-takes 0)
|
||||
(.cleanup takes impl/active?))
|
||||
(set! dirty-takes (inc dirty-takes)))
|
||||
(assert (< (.-length takes) impl/MAX-QUEUE-SIZE)
|
||||
(str "No more than " impl/MAX-QUEUE-SIZE
|
||||
" pending takes are allowed on a single channel."))
|
||||
(.unbounded-unshift takes handler)
|
||||
nil)))))))
|
||||
impl/Channel
|
||||
(closed? [_] closed)
|
||||
(close! [this]
|
||||
(if ^boolean closed
|
||||
nil
|
||||
(do (set! closed true)
|
||||
(when (and buf (zero? (.-length puts)))
|
||||
(add! buf))
|
||||
(loop []
|
||||
(let [^not-native taker (.pop takes)]
|
||||
(when-not (nil? taker)
|
||||
(when ^boolean (impl/active? taker)
|
||||
(let [take-cb (impl/commit taker)
|
||||
val (when (and buf (pos? (count buf))) (impl/remove! buf))]
|
||||
(dispatch/run (fn [] (take-cb val)))))
|
||||
(recur))))
|
||||
nil))))
|
||||
|
||||
(defn- ex-handler [ex]
|
||||
(.log js/console ex)
|
||||
nil)
|
||||
|
||||
(defn- handle [buf exh t]
|
||||
(let [else ((or exh ex-handler) t)]
|
||||
(if (nil? else)
|
||||
buf
|
||||
(impl/add! buf else))))
|
||||
|
||||
(defn chan
|
||||
([buf] (chan buf nil))
|
||||
([buf xform] (chan buf xform nil))
|
||||
([buf xform exh]
|
||||
(ManyToManyChannel. (buffers/ring-buffer 32) 0 (buffers/ring-buffer 32)
|
||||
0 buf false
|
||||
(let [add! (if xform (xform impl/add!) impl/add!)]
|
||||
(fn
|
||||
([buf]
|
||||
(try
|
||||
(add! buf)
|
||||
(catch :default t
|
||||
(handle buf exh t))))
|
||||
([buf val]
|
||||
(try
|
||||
(add! buf val)
|
||||
(catch :default t
|
||||
(handle buf exh t)))))))))
|
||||
Executable
+540
@@ -0,0 +1,540 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.core.async.impl.channels');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.core.async.impl.protocols');
|
||||
goog.require('cljs.core.async.impl.dispatch');
|
||||
goog.require('cljs.core.async.impl.buffers');
|
||||
cljs.core.async.impl.channels.box = (function cljs$core$async$impl$channels$box(val){
|
||||
if((typeof cljs !== 'undefined') && (typeof cljs.core !== 'undefined') && (typeof cljs.core.async !== 'undefined') && (typeof cljs.core.async.impl !== 'undefined') && (typeof cljs.core.async.impl.channels !== 'undefined') && (typeof cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713 !== 'undefined')){
|
||||
} else {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.IMeta}
|
||||
* @implements {cljs.core.IDeref}
|
||||
* @implements {cljs.core.IWithMeta}
|
||||
*/
|
||||
cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713 = (function (val,meta5714){
|
||||
this.val = val;
|
||||
this.meta5714 = meta5714;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 425984;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.prototype.cljs$core$IWithMeta$_with_meta$arity$2 = (function (_5715,meta5714__$1){
|
||||
var self__ = this;
|
||||
var _5715__$1 = this;
|
||||
return (new cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713(self__.val,meta5714__$1));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.prototype.cljs$core$IMeta$_meta$arity$1 = (function (_5715){
|
||||
var self__ = this;
|
||||
var _5715__$1 = this;
|
||||
return self__.meta5714;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.prototype.cljs$core$IDeref$_deref$arity$1 = (function (_){
|
||||
var self__ = this;
|
||||
var ___$1 = this;
|
||||
return self__.val;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$val,cljs.core.cst$sym$meta5714], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.cljs$lang$ctorStr = "cljs.core.async.impl.channels/t_cljs$core$async$impl$channels5713");
|
||||
|
||||
(cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.channels/t_cljs$core$async$impl$channels5713");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.channels/t_cljs$core$async$impl$channels5713.
|
||||
*/
|
||||
cljs.core.async.impl.channels.__GT_t_cljs$core$async$impl$channels5713 = (function cljs$core$async$impl$channels$box_$___GT_t_cljs$core$async$impl$channels5713(val__$1,meta5714){
|
||||
return (new cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713(val__$1,meta5714));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return (new cljs.core.async.impl.channels.t_cljs$core$async$impl$channels5713(val,cljs.core.PersistentArrayMap.EMPTY));
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
cljs.core.async.impl.channels.PutBox = (function (handler,val){
|
||||
this.handler = handler;
|
||||
this.val = val;
|
||||
});
|
||||
|
||||
(cljs.core.async.impl.channels.PutBox.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$handler,cljs.core.cst$sym$val], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.PutBox.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.channels.PutBox.cljs$lang$ctorStr = "cljs.core.async.impl.channels/PutBox");
|
||||
|
||||
(cljs.core.async.impl.channels.PutBox.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.channels/PutBox");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.channels/PutBox.
|
||||
*/
|
||||
cljs.core.async.impl.channels.__GT_PutBox = (function cljs$core$async$impl$channels$__GT_PutBox(handler,val){
|
||||
return (new cljs.core.async.impl.channels.PutBox(handler,val));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.channels.put_active_QMARK_ = (function cljs$core$async$impl$channels$put_active_QMARK_(box){
|
||||
return cljs.core.async.impl.protocols.active_QMARK_(box.handler);
|
||||
});
|
||||
cljs.core.async.impl.channels.MAX_DIRTY = (64);
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.channels.MMC = function(){};
|
||||
|
||||
var cljs$core$async$impl$channels$MMC$abort$dyn_5716 = (function (this$){
|
||||
var x__5393__auto__ = (((this$ == null))?null:this$);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.channels.abort[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(this$) : m__5394__auto__.call(null,this$));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.channels.abort["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(this$) : m__5392__auto__.call(null,this$));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("MMC.abort",this$);
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.channels.abort = (function cljs$core$async$impl$channels$abort(this$){
|
||||
if((((!((this$ == null)))) && ((!((this$.cljs$core$async$impl$channels$MMC$abort$arity$1 == null)))))){
|
||||
return this$.cljs$core$async$impl$channels$MMC$abort$arity$1(this$);
|
||||
} else {
|
||||
return cljs$core$async$impl$channels$MMC$abort$dyn_5716(this$);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.async.impl.channels.MMC}
|
||||
* @implements {cljs.core.async.impl.protocols.Channel}
|
||||
* @implements {cljs.core.async.impl.protocols.WritePort}
|
||||
* @implements {cljs.core.async.impl.protocols.ReadPort}
|
||||
*/
|
||||
cljs.core.async.impl.channels.ManyToManyChannel = (function (takes,dirty_takes,puts,dirty_puts,buf,closed,add_BANG_){
|
||||
this.takes = takes;
|
||||
this.dirty_takes = dirty_takes;
|
||||
this.puts = puts;
|
||||
this.dirty_puts = dirty_puts;
|
||||
this.buf = buf;
|
||||
this.closed = closed;
|
||||
this.add_BANG_ = add_BANG_;
|
||||
});
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$channels$MMC$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$channels$MMC$abort$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
while(true){
|
||||
var putter_5717 = self__.puts.pop();
|
||||
if((putter_5717 == null)){
|
||||
} else {
|
||||
var put_handler_5718 = putter_5717.handler;
|
||||
var val_5719 = putter_5717.val;
|
||||
if(put_handler_5718.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null)){
|
||||
var put_cb_5720 = put_handler_5718.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
cljs.core.async.impl.dispatch.run(((function (put_cb_5720,put_handler_5718,val_5719,putter_5717,this$__$1){
|
||||
return (function (){
|
||||
return (put_cb_5720.cljs$core$IFn$_invoke$arity$1 ? put_cb_5720.cljs$core$IFn$_invoke$arity$1(true) : put_cb_5720.call(null,true));
|
||||
});})(put_cb_5720,put_handler_5718,val_5719,putter_5717,this$__$1))
|
||||
);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
self__.puts.cleanup(cljs.core.constantly(false));
|
||||
|
||||
return this$__$1.cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1(null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$WritePort$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$WritePort$put_BANG_$arity$3 = (function (this$,val,handler){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
if((!((val == null)))){
|
||||
} else {
|
||||
throw (new Error(["Assert failed: ","Can't put nil in on a channel","\n","(not (nil? val))"].join('')));
|
||||
}
|
||||
|
||||
var closed__$1 = self__.closed;
|
||||
if(((closed__$1) || ((!(handler.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null)))))){
|
||||
return cljs.core.async.impl.channels.box((!(closed__$1)));
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = self__.buf;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return cljs.core.not(self__.buf.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1(null));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
handler.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
|
||||
var done_QMARK_ = cljs.core.reduced_QMARK_((self__.add_BANG_.cljs$core$IFn$_invoke$arity$2 ? self__.add_BANG_.cljs$core$IFn$_invoke$arity$2(self__.buf,val) : self__.add_BANG_.call(null,self__.buf,val)));
|
||||
while(true){
|
||||
if((((self__.takes.length > (0))) && ((cljs.core.count(self__.buf) > (0))))){
|
||||
var taker_5721 = self__.takes.pop();
|
||||
if(taker_5721.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null)){
|
||||
var take_cb_5722 = taker_5721.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
var val_5723__$1 = self__.buf.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1(null);
|
||||
cljs.core.async.impl.dispatch.run(((function (take_cb_5722,val_5723__$1,taker_5721,done_QMARK_,closed__$1,this$__$1){
|
||||
return (function (){
|
||||
return (take_cb_5722.cljs$core$IFn$_invoke$arity$1 ? take_cb_5722.cljs$core$IFn$_invoke$arity$1(val_5723__$1) : take_cb_5722.call(null,val_5723__$1));
|
||||
});})(take_cb_5722,val_5723__$1,taker_5721,done_QMARK_,closed__$1,this$__$1))
|
||||
);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(done_QMARK_){
|
||||
this$__$1.cljs$core$async$impl$channels$MMC$abort$arity$1(null);
|
||||
} else {
|
||||
}
|
||||
|
||||
return cljs.core.async.impl.channels.box(true);
|
||||
} else {
|
||||
var taker = (function (){while(true){
|
||||
var taker = self__.takes.pop();
|
||||
if(cljs.core.truth_(taker)){
|
||||
if(cljs.core.truth_(taker.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null))){
|
||||
return taker;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})();
|
||||
if(cljs.core.truth_(taker)){
|
||||
var take_cb = taker.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
handler.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
|
||||
cljs.core.async.impl.dispatch.run((function (){
|
||||
return (take_cb.cljs$core$IFn$_invoke$arity$1 ? take_cb.cljs$core$IFn$_invoke$arity$1(val) : take_cb.call(null,val));
|
||||
}));
|
||||
|
||||
return cljs.core.async.impl.channels.box(true);
|
||||
} else {
|
||||
if((self__.dirty_puts > (64))){
|
||||
(self__.dirty_puts = (0));
|
||||
|
||||
self__.puts.cleanup(cljs.core.async.impl.channels.put_active_QMARK_);
|
||||
} else {
|
||||
(self__.dirty_puts = (self__.dirty_puts + (1)));
|
||||
}
|
||||
|
||||
if((self__.puts.length < (1024))){
|
||||
} else {
|
||||
throw (new Error(["Assert failed: ",["No more than ",cljs.core.str.cljs$core$IFn$_invoke$arity$1((1024))," pending puts are allowed on a single channel."," Consider using a windowed buffer."].join(''),"\n","(< (.-length puts) impl/MAX-QUEUE-SIZE)"].join('')));
|
||||
}
|
||||
|
||||
self__.puts.unbounded_unshift((new cljs.core.async.impl.channels.PutBox(handler,val)));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$ReadPort$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$ReadPort$take_BANG_$arity$2 = (function (this$,handler){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
if((!(handler.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null)))){
|
||||
return null;
|
||||
} else {
|
||||
if((((!((self__.buf == null)))) && ((cljs.core.count(self__.buf) > (0))))){
|
||||
var _ = handler.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
var retval = cljs.core.async.impl.channels.box(self__.buf.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1(null));
|
||||
while(true){
|
||||
if(cljs.core.truth_(self__.buf.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1(null))){
|
||||
} else {
|
||||
var putter_5724 = self__.puts.pop();
|
||||
if((putter_5724 == null)){
|
||||
} else {
|
||||
var put_handler_5725 = putter_5724.handler;
|
||||
var val_5726 = putter_5724.val;
|
||||
if(put_handler_5725.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null)){
|
||||
var put_cb_5727 = put_handler_5725.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
handler.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
|
||||
cljs.core.async.impl.dispatch.run(((function (put_cb_5727,put_handler_5725,val_5726,putter_5724,_,retval,this$__$1){
|
||||
return (function (){
|
||||
return (put_cb_5727.cljs$core$IFn$_invoke$arity$1 ? put_cb_5727.cljs$core$IFn$_invoke$arity$1(true) : put_cb_5727.call(null,true));
|
||||
});})(put_cb_5727,put_handler_5725,val_5726,putter_5724,_,retval,this$__$1))
|
||||
);
|
||||
|
||||
if(cljs.core.reduced_QMARK_((self__.add_BANG_.cljs$core$IFn$_invoke$arity$2 ? self__.add_BANG_.cljs$core$IFn$_invoke$arity$2(self__.buf,val_5726) : self__.add_BANG_.call(null,self__.buf,val_5726)))){
|
||||
this$__$1.cljs$core$async$impl$channels$MMC$abort$arity$1(null);
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
} else {
|
||||
var putter = (function (){while(true){
|
||||
var putter = self__.puts.pop();
|
||||
if(cljs.core.truth_(putter)){
|
||||
if(cljs.core.async.impl.protocols.active_QMARK_(putter.handler)){
|
||||
return putter;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})();
|
||||
if(cljs.core.truth_(putter)){
|
||||
var put_cb = cljs.core.async.impl.protocols.commit(putter.handler);
|
||||
handler.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
|
||||
cljs.core.async.impl.dispatch.run((function (){
|
||||
return (put_cb.cljs$core$IFn$_invoke$arity$1 ? put_cb.cljs$core$IFn$_invoke$arity$1(true) : put_cb.call(null,true));
|
||||
}));
|
||||
|
||||
return cljs.core.async.impl.channels.box(putter.val);
|
||||
} else {
|
||||
if(cljs.core.truth_(self__.closed)){
|
||||
if(cljs.core.truth_(self__.buf)){
|
||||
(self__.add_BANG_.cljs$core$IFn$_invoke$arity$1 ? self__.add_BANG_.cljs$core$IFn$_invoke$arity$1(self__.buf) : self__.add_BANG_.call(null,self__.buf));
|
||||
} else {
|
||||
}
|
||||
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = handler.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null);
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return handler.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
var has_val = (function (){var and__5043__auto__ = self__.buf;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return (cljs.core.count(self__.buf) > (0));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})();
|
||||
var val = (cljs.core.truth_(has_val)?self__.buf.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1(null):null);
|
||||
return cljs.core.async.impl.channels.box(val);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if((self__.dirty_takes > (64))){
|
||||
(self__.dirty_takes = (0));
|
||||
|
||||
self__.takes.cleanup(cljs.core.async.impl.protocols.active_QMARK_);
|
||||
} else {
|
||||
(self__.dirty_takes = (self__.dirty_takes + (1)));
|
||||
}
|
||||
|
||||
if((self__.takes.length < (1024))){
|
||||
} else {
|
||||
throw (new Error(["Assert failed: ",["No more than ",cljs.core.str.cljs$core$IFn$_invoke$arity$1((1024))," pending takes are allowed on a single channel."].join(''),"\n","(< (.-length takes) impl/MAX-QUEUE-SIZE)"].join('')));
|
||||
}
|
||||
|
||||
self__.takes.unbounded_unshift(handler);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$Channel$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$Channel$closed_QMARK_$arity$1 = (function (_){
|
||||
var self__ = this;
|
||||
var ___$1 = this;
|
||||
return self__.closed;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.prototype.cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1 = (function (this$){
|
||||
var self__ = this;
|
||||
var this$__$1 = this;
|
||||
if(self__.closed){
|
||||
return null;
|
||||
} else {
|
||||
(self__.closed = true);
|
||||
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = self__.buf;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return (self__.puts.length === (0));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
(self__.add_BANG_.cljs$core$IFn$_invoke$arity$1 ? self__.add_BANG_.cljs$core$IFn$_invoke$arity$1(self__.buf) : self__.add_BANG_.call(null,self__.buf));
|
||||
} else {
|
||||
}
|
||||
|
||||
while(true){
|
||||
var taker_5728 = self__.takes.pop();
|
||||
if((taker_5728 == null)){
|
||||
} else {
|
||||
if(taker_5728.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(null)){
|
||||
var take_cb_5729 = taker_5728.cljs$core$async$impl$protocols$Handler$commit$arity$1(null);
|
||||
var val_5730 = (cljs.core.truth_((function (){var and__5043__auto__ = self__.buf;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return (cljs.core.count(self__.buf) > (0));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())?self__.buf.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1(null):null);
|
||||
cljs.core.async.impl.dispatch.run(((function (take_cb_5729,val_5730,taker_5728,this$__$1){
|
||||
return (function (){
|
||||
return (take_cb_5729.cljs$core$IFn$_invoke$arity$1 ? take_cb_5729.cljs$core$IFn$_invoke$arity$1(val_5730) : take_cb_5729.call(null,val_5730));
|
||||
});})(take_cb_5729,val_5730,taker_5728,this$__$1))
|
||||
);
|
||||
} else {
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 7, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$takes,cljs.core.with_meta(cljs.core.cst$sym$dirty_DASH_takes,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.cst$sym$puts,cljs.core.with_meta(cljs.core.cst$sym$dirty_DASH_puts,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$buf,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,cljs.core.cst$sym$not_DASH_native], null)),cljs.core.with_meta(cljs.core.cst$sym$closed,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.cst$sym$add_BANG_], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.cljs$lang$ctorStr = "cljs.core.async.impl.channels/ManyToManyChannel");
|
||||
|
||||
(cljs.core.async.impl.channels.ManyToManyChannel.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.channels/ManyToManyChannel");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.channels/ManyToManyChannel.
|
||||
*/
|
||||
cljs.core.async.impl.channels.__GT_ManyToManyChannel = (function cljs$core$async$impl$channels$__GT_ManyToManyChannel(takes,dirty_takes,puts,dirty_puts,buf,closed,add_BANG_){
|
||||
return (new cljs.core.async.impl.channels.ManyToManyChannel(takes,dirty_takes,puts,dirty_puts,buf,closed,add_BANG_));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.channels.ex_handler = (function cljs$core$async$impl$channels$ex_handler(ex){
|
||||
console.log(ex);
|
||||
|
||||
return null;
|
||||
});
|
||||
cljs.core.async.impl.channels.handle = (function cljs$core$async$impl$channels$handle(buf,exh,t){
|
||||
var else$ = (function (){var fexpr__5731 = (function (){var or__5045__auto__ = exh;
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return cljs.core.async.impl.channels.ex_handler;
|
||||
}
|
||||
})();
|
||||
return (fexpr__5731.cljs$core$IFn$_invoke$arity$1 ? fexpr__5731.cljs$core$IFn$_invoke$arity$1(t) : fexpr__5731.call(null,t));
|
||||
})();
|
||||
if((else$ == null)){
|
||||
return buf;
|
||||
} else {
|
||||
return cljs.core.async.impl.protocols.add_BANG_.cljs$core$IFn$_invoke$arity$2(buf,else$);
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.channels.chan = (function cljs$core$async$impl$channels$chan(var_args){
|
||||
var G__5733 = arguments.length;
|
||||
switch (G__5733) {
|
||||
case 1:
|
||||
return cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$1 = (function (buf){
|
||||
return cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$2(buf,null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$2 = (function (buf,xform){
|
||||
return cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$3(buf,xform,null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$3 = (function (buf,xform,exh){
|
||||
return (new cljs.core.async.impl.channels.ManyToManyChannel(cljs.core.async.impl.buffers.ring_buffer((32)),(0),cljs.core.async.impl.buffers.ring_buffer((32)),(0),buf,false,(function (){var add_BANG_ = (cljs.core.truth_(xform)?(xform.cljs$core$IFn$_invoke$arity$1 ? xform.cljs$core$IFn$_invoke$arity$1(cljs.core.async.impl.protocols.add_BANG_) : xform.call(null,cljs.core.async.impl.protocols.add_BANG_)):cljs.core.async.impl.protocols.add_BANG_);
|
||||
return (function() {
|
||||
var G__5737 = null;
|
||||
var G__5737__1 = (function (buf__$1){
|
||||
try{return (add_BANG_.cljs$core$IFn$_invoke$arity$1 ? add_BANG_.cljs$core$IFn$_invoke$arity$1(buf__$1) : add_BANG_.call(null,buf__$1));
|
||||
}catch (e5734){var t = e5734;
|
||||
return cljs.core.async.impl.channels.handle(buf__$1,exh,t);
|
||||
}});
|
||||
var G__5737__2 = (function (buf__$1,val){
|
||||
try{return (add_BANG_.cljs$core$IFn$_invoke$arity$2 ? add_BANG_.cljs$core$IFn$_invoke$arity$2(buf__$1,val) : add_BANG_.call(null,buf__$1,val));
|
||||
}catch (e5735){var t = e5735;
|
||||
return cljs.core.async.impl.channels.handle(buf__$1,exh,t);
|
||||
}});
|
||||
G__5737 = function(buf__$1,val){
|
||||
switch(arguments.length){
|
||||
case 1:
|
||||
return G__5737__1.call(this,buf__$1);
|
||||
case 2:
|
||||
return G__5737__2.call(this,buf__$1,val);
|
||||
}
|
||||
throw(new Error('Invalid arity: ' + arguments.length));
|
||||
};
|
||||
G__5737.cljs$core$IFn$_invoke$arity$1 = G__5737__1;
|
||||
G__5737.cljs$core$IFn$_invoke$arity$2 = G__5737__2;
|
||||
return G__5737;
|
||||
})()
|
||||
})()));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.channels.chan.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
(ns cljs.core.async.impl.dispatch
|
||||
(:require [cljs.core.async.impl.buffers :as buffers]
|
||||
[goog.async.nextTick]))
|
||||
|
||||
(def tasks (buffers/ring-buffer 32))
|
||||
(def running? false)
|
||||
(def queued? false)
|
||||
|
||||
(def TASK_BATCH_SIZE 1024)
|
||||
|
||||
(declare queue-dispatcher)
|
||||
|
||||
(defn process-messages []
|
||||
(set! running? true)
|
||||
(set! queued? false)
|
||||
(loop [count 0]
|
||||
(let [m (.pop tasks)]
|
||||
(when-not (nil? m)
|
||||
(m)
|
||||
(when (< count TASK_BATCH_SIZE)
|
||||
(recur (inc count))))))
|
||||
(set! running? false)
|
||||
(when (> (.-length tasks) 0)
|
||||
(queue-dispatcher)))
|
||||
|
||||
(defn queue-dispatcher []
|
||||
(when-not (and queued? running?)
|
||||
(set! queued? true)
|
||||
(goog.async.nextTick process-messages)))
|
||||
|
||||
(defn run [f]
|
||||
(.unbounded-unshift tasks f)
|
||||
(queue-dispatcher))
|
||||
|
||||
(defn queue-delay [f delay]
|
||||
(js/setTimeout f delay))
|
||||
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.core.async.impl.dispatch');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.core.async.impl.buffers');
|
||||
goog.require('goog.async.nextTick');
|
||||
cljs.core.async.impl.dispatch.tasks = cljs.core.async.impl.buffers.ring_buffer((32));
|
||||
cljs.core.async.impl.dispatch.running_QMARK_ = false;
|
||||
cljs.core.async.impl.dispatch.queued_QMARK_ = false;
|
||||
cljs.core.async.impl.dispatch.TASK_BATCH_SIZE = (1024);
|
||||
cljs.core.async.impl.dispatch.process_messages = (function cljs$core$async$impl$dispatch$process_messages(){
|
||||
(cljs.core.async.impl.dispatch.running_QMARK_ = true);
|
||||
|
||||
(cljs.core.async.impl.dispatch.queued_QMARK_ = false);
|
||||
|
||||
var count_5708 = (0);
|
||||
while(true){
|
||||
var m_5709 = cljs.core.async.impl.dispatch.tasks.pop();
|
||||
if((m_5709 == null)){
|
||||
} else {
|
||||
(m_5709.cljs$core$IFn$_invoke$arity$0 ? m_5709.cljs$core$IFn$_invoke$arity$0() : m_5709.call(null));
|
||||
|
||||
if((count_5708 < cljs.core.async.impl.dispatch.TASK_BATCH_SIZE)){
|
||||
var G__5710 = (count_5708 + (1));
|
||||
count_5708 = G__5710;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
(cljs.core.async.impl.dispatch.running_QMARK_ = false);
|
||||
|
||||
if((cljs.core.async.impl.dispatch.tasks.length > (0))){
|
||||
return (cljs.core.async.impl.dispatch.queue_dispatcher.cljs$core$IFn$_invoke$arity$0 ? cljs.core.async.impl.dispatch.queue_dispatcher.cljs$core$IFn$_invoke$arity$0() : cljs.core.async.impl.dispatch.queue_dispatcher.call(null));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.dispatch.queue_dispatcher = (function cljs$core$async$impl$dispatch$queue_dispatcher(){
|
||||
if(((cljs.core.async.impl.dispatch.queued_QMARK_) && (cljs.core.async.impl.dispatch.running_QMARK_))){
|
||||
return null;
|
||||
} else {
|
||||
(cljs.core.async.impl.dispatch.queued_QMARK_ = true);
|
||||
|
||||
return goog.async.nextTick(cljs.core.async.impl.dispatch.process_messages);
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.dispatch.run = (function cljs$core$async$impl$dispatch$run(f){
|
||||
cljs.core.async.impl.dispatch.tasks.unbounded_unshift(f);
|
||||
|
||||
return cljs.core.async.impl.dispatch.queue_dispatcher();
|
||||
});
|
||||
cljs.core.async.impl.dispatch.queue_delay = (function cljs$core$async$impl$dispatch$queue_delay(f,delay){
|
||||
return setTimeout(f,delay);
|
||||
});
|
||||
Executable
+144
@@ -0,0 +1,144 @@
|
||||
(ns cljs.core.async.impl.ioc-helpers
|
||||
(:require [cljs.core.async.impl.protocols :as impl])
|
||||
(:require-macros [cljs.core.async.impl.ioc-macros :as ioc]))
|
||||
|
||||
(def ^:const FN-IDX 0)
|
||||
(def ^:const STATE-IDX 1)
|
||||
(def ^:const VALUE-IDX 2)
|
||||
(def ^:const BINDINGS-IDX 3)
|
||||
(def ^:const EXCEPTION-FRAMES 4)
|
||||
(def ^:const CURRENT-EXCEPTION 5)
|
||||
(def ^:const USER-START-IDX 6)
|
||||
|
||||
(defn aset-object [arr idx o]
|
||||
(aget arr idx o))
|
||||
|
||||
(defn aget-object [arr idx]
|
||||
(aget arr idx))
|
||||
|
||||
|
||||
(defn finished?
|
||||
"Returns true if the machine is in a finished state"
|
||||
[state-array]
|
||||
(keyword-identical? (aget state-array STATE-IDX) :finished))
|
||||
|
||||
(defn- fn-handler
|
||||
[f]
|
||||
(reify
|
||||
impl/Handler
|
||||
(active? [_] true)
|
||||
(commit [_] f)))
|
||||
|
||||
|
||||
(defn run-state-machine [state]
|
||||
((aget-object state FN-IDX) state))
|
||||
|
||||
(defn run-state-machine-wrapped [state]
|
||||
(try
|
||||
(run-state-machine state)
|
||||
(catch js/Object ex
|
||||
(impl/close! ^not-native (aget-object state USER-START-IDX))
|
||||
(throw ex))))
|
||||
|
||||
(defn take! [state blk ^not-native c]
|
||||
(if-let [cb (impl/take! c (fn-handler
|
||||
(fn [x]
|
||||
(ioc/aset-all! state VALUE-IDX x STATE-IDX blk)
|
||||
(run-state-machine-wrapped state))))]
|
||||
(do (ioc/aset-all! state VALUE-IDX @cb STATE-IDX blk)
|
||||
:recur)
|
||||
nil))
|
||||
|
||||
(defn put! [state blk ^not-native c val]
|
||||
(if-let [cb (impl/put! c val (fn-handler (fn [ret-val]
|
||||
(ioc/aset-all! state VALUE-IDX ret-val STATE-IDX blk)
|
||||
(run-state-machine-wrapped state))))]
|
||||
(do (ioc/aset-all! state VALUE-IDX @cb STATE-IDX blk)
|
||||
:recur)
|
||||
nil))
|
||||
|
||||
(defn return-chan [state value]
|
||||
(let [^not-native c (aget state USER-START-IDX)]
|
||||
(when-not (nil? value)
|
||||
(impl/put! c value (fn-handler (fn [] nil))))
|
||||
(impl/close! c)
|
||||
c))
|
||||
|
||||
(defrecord ExceptionFrame [catch-block
|
||||
^Class catch-exception
|
||||
finally-block
|
||||
continue-block
|
||||
prev])
|
||||
|
||||
(defn add-exception-frame [state catch-block catch-exception finally-block continue-block]
|
||||
(ioc/aset-all! state
|
||||
EXCEPTION-FRAMES
|
||||
(->ExceptionFrame catch-block
|
||||
catch-exception
|
||||
finally-block
|
||||
continue-block
|
||||
(aget-object state EXCEPTION-FRAMES))))
|
||||
|
||||
(defn process-exception [state]
|
||||
(let [exception-frame (aget-object state EXCEPTION-FRAMES)
|
||||
catch-block (:catch-block exception-frame)
|
||||
catch-exception (:catch-exception exception-frame)
|
||||
exception (aget-object state CURRENT-EXCEPTION)]
|
||||
(cond
|
||||
(and exception
|
||||
(not exception-frame))
|
||||
(throw exception)
|
||||
|
||||
(and exception
|
||||
catch-block
|
||||
(instance? catch-exception exception))
|
||||
(ioc/aset-all! state
|
||||
STATE-IDX
|
||||
catch-block
|
||||
VALUE-IDX
|
||||
exception
|
||||
CURRENT-EXCEPTION
|
||||
nil
|
||||
EXCEPTION-FRAMES
|
||||
(assoc exception-frame
|
||||
:catch-block nil
|
||||
:catch-exception nil))
|
||||
|
||||
|
||||
(and exception
|
||||
(not catch-block)
|
||||
(not (:finally-block exception-frame)))
|
||||
|
||||
(do (ioc/aset-all! state
|
||||
EXCEPTION-FRAMES
|
||||
(:prev exception-frame))
|
||||
(recur state))
|
||||
|
||||
(and exception
|
||||
(not catch-block)
|
||||
(:finally-block exception-frame))
|
||||
(ioc/aset-all! state
|
||||
STATE-IDX
|
||||
(:finally-block exception-frame)
|
||||
EXCEPTION-FRAMES
|
||||
(assoc exception-frame
|
||||
:finally-block nil))
|
||||
|
||||
(and (not exception)
|
||||
(:finally-block exception-frame))
|
||||
(do (ioc/aset-all! state
|
||||
STATE-IDX
|
||||
(:finally-block exception-frame)
|
||||
EXCEPTION-FRAMES
|
||||
(assoc exception-frame
|
||||
:finally-block nil)))
|
||||
|
||||
(and (not exception)
|
||||
(not (:finally-block exception-frame)))
|
||||
(do (ioc/aset-all! state
|
||||
STATE-IDX
|
||||
(:continue-block exception-frame)
|
||||
EXCEPTION-FRAMES
|
||||
(:prev exception-frame)))
|
||||
|
||||
:else (throw (js/Error. "No matching clause")))))
|
||||
Executable
+542
@@ -0,0 +1,542 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.core.async.impl.ioc_helpers');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.core.async.impl.protocols');
|
||||
cljs.core.async.impl.ioc_helpers.FN_IDX = (0);
|
||||
cljs.core.async.impl.ioc_helpers.STATE_IDX = (1);
|
||||
cljs.core.async.impl.ioc_helpers.VALUE_IDX = (2);
|
||||
cljs.core.async.impl.ioc_helpers.BINDINGS_IDX = (3);
|
||||
cljs.core.async.impl.ioc_helpers.EXCEPTION_FRAMES = (4);
|
||||
cljs.core.async.impl.ioc_helpers.CURRENT_EXCEPTION = (5);
|
||||
cljs.core.async.impl.ioc_helpers.USER_START_IDX = (6);
|
||||
cljs.core.async.impl.ioc_helpers.aset_object = (function cljs$core$async$impl$ioc_helpers$aset_object(arr,idx,o){
|
||||
return (arr[idx][o]);
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.aget_object = (function cljs$core$async$impl$ioc_helpers$aget_object(arr,idx){
|
||||
return (arr[idx]);
|
||||
});
|
||||
/**
|
||||
* Returns true if the machine is in a finished state
|
||||
*/
|
||||
cljs.core.async.impl.ioc_helpers.finished_QMARK_ = (function cljs$core$async$impl$ioc_helpers$finished_QMARK_(state_array){
|
||||
return cljs.core.keyword_identical_QMARK_((state_array[(1)]),cljs.core.cst$kw$finished);
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.fn_handler = (function cljs$core$async$impl$ioc_helpers$fn_handler(f){
|
||||
if((typeof cljs !== 'undefined') && (typeof cljs.core !== 'undefined') && (typeof cljs.core.async !== 'undefined') && (typeof cljs.core.async.impl !== 'undefined') && (typeof cljs.core.async.impl.ioc_helpers !== 'undefined') && (typeof cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784 !== 'undefined')){
|
||||
} else {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.async.impl.protocols.Handler}
|
||||
* @implements {cljs.core.IMeta}
|
||||
* @implements {cljs.core.IWithMeta}
|
||||
*/
|
||||
cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784 = (function (f,meta8785){
|
||||
this.f = f;
|
||||
this.meta8785 = meta8785;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 393216;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.prototype.cljs$core$IWithMeta$_with_meta$arity$2 = (function (_8786,meta8785__$1){
|
||||
var self__ = this;
|
||||
var _8786__$1 = this;
|
||||
return (new cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784(self__.f,meta8785__$1));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.prototype.cljs$core$IMeta$_meta$arity$1 = (function (_8786){
|
||||
var self__ = this;
|
||||
var _8786__$1 = this;
|
||||
return self__.meta8785;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.prototype.cljs$core$async$impl$protocols$Handler$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.prototype.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1 = (function (_){
|
||||
var self__ = this;
|
||||
var ___$1 = this;
|
||||
return true;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.prototype.cljs$core$async$impl$protocols$Handler$commit$arity$1 = (function (_){
|
||||
var self__ = this;
|
||||
var ___$1 = this;
|
||||
return self__.f;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$f,cljs.core.cst$sym$meta8785], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.cljs$lang$ctorStr = "cljs.core.async.impl.ioc-helpers/t_cljs$core$async$impl$ioc_helpers8784");
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.ioc-helpers/t_cljs$core$async$impl$ioc_helpers8784");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.ioc-helpers/t_cljs$core$async$impl$ioc_helpers8784.
|
||||
*/
|
||||
cljs.core.async.impl.ioc_helpers.__GT_t_cljs$core$async$impl$ioc_helpers8784 = (function cljs$core$async$impl$ioc_helpers$fn_handler_$___GT_t_cljs$core$async$impl$ioc_helpers8784(f__$1,meta8785){
|
||||
return (new cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784(f__$1,meta8785));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return (new cljs.core.async.impl.ioc_helpers.t_cljs$core$async$impl$ioc_helpers8784(f,cljs.core.PersistentArrayMap.EMPTY));
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.run_state_machine = (function cljs$core$async$impl$ioc_helpers$run_state_machine(state){
|
||||
var fexpr__8787 = cljs.core.async.impl.ioc_helpers.aget_object(state,(0));
|
||||
return (fexpr__8787.cljs$core$IFn$_invoke$arity$1 ? fexpr__8787.cljs$core$IFn$_invoke$arity$1(state) : fexpr__8787.call(null,state));
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped = (function cljs$core$async$impl$ioc_helpers$run_state_machine_wrapped(state){
|
||||
try{return cljs.core.async.impl.ioc_helpers.run_state_machine(state);
|
||||
}catch (e8788){if((e8788 instanceof Object)){
|
||||
var ex = e8788;
|
||||
cljs.core.async.impl.ioc_helpers.aget_object(state,(6)).cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1(null);
|
||||
|
||||
throw ex;
|
||||
} else {
|
||||
throw e8788;
|
||||
|
||||
}
|
||||
}});
|
||||
cljs.core.async.impl.ioc_helpers.take_BANG_ = (function cljs$core$async$impl$ioc_helpers$take_BANG_(state,blk,c){
|
||||
var temp__4655__auto__ = c.cljs$core$async$impl$protocols$ReadPort$take_BANG_$arity$2(null,cljs.core.async.impl.ioc_helpers.fn_handler((function (x){
|
||||
var statearr_8789_8791 = state;
|
||||
(statearr_8789_8791[(2)] = x);
|
||||
|
||||
(statearr_8789_8791[(1)] = blk);
|
||||
|
||||
|
||||
return cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped(state);
|
||||
})));
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var cb = temp__4655__auto__;
|
||||
var statearr_8790_8792 = state;
|
||||
(statearr_8790_8792[(2)] = cljs.core.deref(cb));
|
||||
|
||||
(statearr_8790_8792[(1)] = blk);
|
||||
|
||||
|
||||
return cljs.core.cst$kw$recur;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.put_BANG_ = (function cljs$core$async$impl$ioc_helpers$put_BANG_(state,blk,c,val){
|
||||
var temp__4655__auto__ = c.cljs$core$async$impl$protocols$WritePort$put_BANG_$arity$3(null,val,cljs.core.async.impl.ioc_helpers.fn_handler((function (ret_val){
|
||||
var statearr_8793_8795 = state;
|
||||
(statearr_8793_8795[(2)] = ret_val);
|
||||
|
||||
(statearr_8793_8795[(1)] = blk);
|
||||
|
||||
|
||||
return cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped(state);
|
||||
})));
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var cb = temp__4655__auto__;
|
||||
var statearr_8794_8796 = state;
|
||||
(statearr_8794_8796[(2)] = cljs.core.deref(cb));
|
||||
|
||||
(statearr_8794_8796[(1)] = blk);
|
||||
|
||||
|
||||
return cljs.core.cst$kw$recur;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.return_chan = (function cljs$core$async$impl$ioc_helpers$return_chan(state,value){
|
||||
var c = (state[(6)]);
|
||||
if((value == null)){
|
||||
} else {
|
||||
c.cljs$core$async$impl$protocols$WritePort$put_BANG_$arity$3(null,value,cljs.core.async.impl.ioc_helpers.fn_handler((function (){
|
||||
return null;
|
||||
})));
|
||||
}
|
||||
|
||||
c.cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1(null);
|
||||
|
||||
return c;
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.IRecord}
|
||||
* @implements {cljs.core.IKVReduce}
|
||||
* @implements {cljs.core.IEquiv}
|
||||
* @implements {cljs.core.IHash}
|
||||
* @implements {cljs.core.ICollection}
|
||||
* @implements {cljs.core.ICounted}
|
||||
* @implements {cljs.core.ISeqable}
|
||||
* @implements {cljs.core.IMeta}
|
||||
* @implements {cljs.core.ICloneable}
|
||||
* @implements {cljs.core.IPrintWithWriter}
|
||||
* @implements {cljs.core.IIterable}
|
||||
* @implements {cljs.core.IWithMeta}
|
||||
* @implements {cljs.core.IAssociative}
|
||||
* @implements {cljs.core.IMap}
|
||||
* @implements {cljs.core.ILookup}
|
||||
*/
|
||||
cljs.core.async.impl.ioc_helpers.ExceptionFrame = (function (catch_block,catch_exception,finally_block,continue_block,prev,__meta,__extmap,__hash){
|
||||
this.catch_block = catch_block;
|
||||
this.catch_exception = catch_exception;
|
||||
this.finally_block = finally_block;
|
||||
this.continue_block = continue_block;
|
||||
this.prev = prev;
|
||||
this.__meta = __meta;
|
||||
this.__extmap = __extmap;
|
||||
this.__hash = __hash;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2230716170;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 139264;
|
||||
});
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$ILookup$_lookup$arity$2 = (function (this__5343__auto__,k__5344__auto__){
|
||||
var self__ = this;
|
||||
var this__5343__auto____$1 = this;
|
||||
return this__5343__auto____$1.cljs$core$ILookup$_lookup$arity$3(null,k__5344__auto__,null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$ILookup$_lookup$arity$3 = (function (this__5345__auto__,k8798,else__5346__auto__){
|
||||
var self__ = this;
|
||||
var this__5345__auto____$1 = this;
|
||||
var G__8802 = k8798;
|
||||
var G__8802__$1 = (((G__8802 instanceof cljs.core.Keyword))?G__8802.fqn:null);
|
||||
switch (G__8802__$1) {
|
||||
case "catch-block":
|
||||
return self__.catch_block;
|
||||
|
||||
break;
|
||||
case "catch-exception":
|
||||
return self__.catch_exception;
|
||||
|
||||
break;
|
||||
case "finally-block":
|
||||
return self__.finally_block;
|
||||
|
||||
break;
|
||||
case "continue-block":
|
||||
return self__.continue_block;
|
||||
|
||||
break;
|
||||
case "prev":
|
||||
return self__.prev;
|
||||
|
||||
break;
|
||||
default:
|
||||
return cljs.core.get.cljs$core$IFn$_invoke$arity$3(self__.__extmap,k8798,else__5346__auto__);
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IKVReduce$_kv_reduce$arity$3 = (function (this__5363__auto__,f__5364__auto__,init__5365__auto__){
|
||||
var self__ = this;
|
||||
var this__5363__auto____$1 = this;
|
||||
return cljs.core.reduce.cljs$core$IFn$_invoke$arity$3((function (ret__5366__auto__,p__8803){
|
||||
var vec__8804 = p__8803;
|
||||
var k__5367__auto__ = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__8804,(0),null);
|
||||
var v__5368__auto__ = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__8804,(1),null);
|
||||
return (f__5364__auto__.cljs$core$IFn$_invoke$arity$3 ? f__5364__auto__.cljs$core$IFn$_invoke$arity$3(ret__5366__auto__,k__5367__auto__,v__5368__auto__) : f__5364__auto__.call(null,ret__5366__auto__,k__5367__auto__,v__5368__auto__));
|
||||
}),init__5365__auto__,this__5363__auto____$1);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IPrintWithWriter$_pr_writer$arity$3 = (function (this__5358__auto__,writer__5359__auto__,opts__5360__auto__){
|
||||
var self__ = this;
|
||||
var this__5358__auto____$1 = this;
|
||||
var pr_pair__5361__auto__ = (function (keyval__5362__auto__){
|
||||
return cljs.core.pr_sequential_writer(writer__5359__auto__,cljs.core.pr_writer,""," ","",opts__5360__auto__,keyval__5362__auto__);
|
||||
});
|
||||
return cljs.core.pr_sequential_writer(writer__5359__auto__,pr_pair__5361__auto__,"#cljs.core.async.impl.ioc-helpers.ExceptionFrame{",", ","}",opts__5360__auto__,cljs.core.concat.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentVector(null, 5, 5, cljs.core.PersistentVector.EMPTY_NODE, [(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$catch_DASH_block,self__.catch_block],null)),(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$catch_DASH_exception,self__.catch_exception],null)),(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$finally_DASH_block,self__.finally_block],null)),(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$continue_DASH_block,self__.continue_block],null)),(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$prev,self__.prev],null))], null),self__.__extmap));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IIterable$_iterator$arity$1 = (function (G__8797){
|
||||
var self__ = this;
|
||||
var G__8797__$1 = this;
|
||||
return (new cljs.core.RecordIter((0),G__8797__$1,5,new cljs.core.PersistentVector(null, 5, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$kw$catch_DASH_block,cljs.core.cst$kw$catch_DASH_exception,cljs.core.cst$kw$finally_DASH_block,cljs.core.cst$kw$continue_DASH_block,cljs.core.cst$kw$prev], null),(cljs.core.truth_(self__.__extmap)?cljs.core._iterator(self__.__extmap):cljs.core.nil_iter())));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IMeta$_meta$arity$1 = (function (this__5341__auto__){
|
||||
var self__ = this;
|
||||
var this__5341__auto____$1 = this;
|
||||
return self__.__meta;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$ICloneable$_clone$arity$1 = (function (this__5338__auto__){
|
||||
var self__ = this;
|
||||
var this__5338__auto____$1 = this;
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,self__.finally_block,self__.continue_block,self__.prev,self__.__meta,self__.__extmap,self__.__hash));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$ICounted$_count$arity$1 = (function (this__5347__auto__){
|
||||
var self__ = this;
|
||||
var this__5347__auto____$1 = this;
|
||||
return (5 + cljs.core.count(self__.__extmap));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IHash$_hash$arity$1 = (function (this__5339__auto__){
|
||||
var self__ = this;
|
||||
var this__5339__auto____$1 = this;
|
||||
var h__5154__auto__ = self__.__hash;
|
||||
if((!((h__5154__auto__ == null)))){
|
||||
return h__5154__auto__;
|
||||
} else {
|
||||
var h__5154__auto____$1 = (function (){var fexpr__8807 = (function (coll__5340__auto__){
|
||||
return (846900531 ^ cljs.core.hash_unordered_coll(coll__5340__auto__));
|
||||
});
|
||||
return fexpr__8807(this__5339__auto____$1);
|
||||
})();
|
||||
(self__.__hash = h__5154__auto____$1);
|
||||
|
||||
return h__5154__auto____$1;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IEquiv$_equiv$arity$2 = (function (this8799,other8800){
|
||||
var self__ = this;
|
||||
var this8799__$1 = this;
|
||||
return (((!((other8800 == null)))) && ((((this8799__$1.constructor === other8800.constructor)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this8799__$1.catch_block,other8800.catch_block)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this8799__$1.catch_exception,other8800.catch_exception)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this8799__$1.finally_block,other8800.finally_block)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this8799__$1.continue_block,other8800.continue_block)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this8799__$1.prev,other8800.prev)) && (cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this8799__$1.__extmap,other8800.__extmap)))))))))))))));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IMap$_dissoc$arity$2 = (function (this__5353__auto__,k__5354__auto__){
|
||||
var self__ = this;
|
||||
var this__5353__auto____$1 = this;
|
||||
if(cljs.core.contains_QMARK_(new cljs.core.PersistentHashSet(null, new cljs.core.PersistentArrayMap(null, 5, [cljs.core.cst$kw$finally_DASH_block,null,cljs.core.cst$kw$catch_DASH_block,null,cljs.core.cst$kw$catch_DASH_exception,null,cljs.core.cst$kw$prev,null,cljs.core.cst$kw$continue_DASH_block,null], null), null),k__5354__auto__)){
|
||||
return cljs.core.dissoc.cljs$core$IFn$_invoke$arity$2(cljs.core._with_meta(cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,this__5353__auto____$1),self__.__meta),k__5354__auto__);
|
||||
} else {
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,self__.finally_block,self__.continue_block,self__.prev,self__.__meta,cljs.core.not_empty(cljs.core.dissoc.cljs$core$IFn$_invoke$arity$2(self__.__extmap,k__5354__auto__)),null));
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IAssociative$_contains_key_QMARK_$arity$2 = (function (this__5350__auto__,k8798){
|
||||
var self__ = this;
|
||||
var this__5350__auto____$1 = this;
|
||||
var G__8808 = k8798;
|
||||
var G__8808__$1 = (((G__8808 instanceof cljs.core.Keyword))?G__8808.fqn:null);
|
||||
switch (G__8808__$1) {
|
||||
case "catch-block":
|
||||
case "catch-exception":
|
||||
case "finally-block":
|
||||
case "continue-block":
|
||||
case "prev":
|
||||
return true;
|
||||
|
||||
break;
|
||||
default:
|
||||
return cljs.core.contains_QMARK_(self__.__extmap,k8798);
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IAssociative$_assoc$arity$3 = (function (this__5351__auto__,k__5352__auto__,G__8797){
|
||||
var self__ = this;
|
||||
var this__5351__auto____$1 = this;
|
||||
var pred__8809 = cljs.core.keyword_identical_QMARK_;
|
||||
var expr__8810 = k__5352__auto__;
|
||||
if(cljs.core.truth_((function (){var G__8812 = cljs.core.cst$kw$catch_DASH_block;
|
||||
var G__8813 = expr__8810;
|
||||
return (pred__8809.cljs$core$IFn$_invoke$arity$2 ? pred__8809.cljs$core$IFn$_invoke$arity$2(G__8812,G__8813) : pred__8809.call(null,G__8812,G__8813));
|
||||
})())){
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(G__8797,self__.catch_exception,self__.finally_block,self__.continue_block,self__.prev,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var G__8814 = cljs.core.cst$kw$catch_DASH_exception;
|
||||
var G__8815 = expr__8810;
|
||||
return (pred__8809.cljs$core$IFn$_invoke$arity$2 ? pred__8809.cljs$core$IFn$_invoke$arity$2(G__8814,G__8815) : pred__8809.call(null,G__8814,G__8815));
|
||||
})())){
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,G__8797,self__.finally_block,self__.continue_block,self__.prev,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var G__8816 = cljs.core.cst$kw$finally_DASH_block;
|
||||
var G__8817 = expr__8810;
|
||||
return (pred__8809.cljs$core$IFn$_invoke$arity$2 ? pred__8809.cljs$core$IFn$_invoke$arity$2(G__8816,G__8817) : pred__8809.call(null,G__8816,G__8817));
|
||||
})())){
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,G__8797,self__.continue_block,self__.prev,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var G__8818 = cljs.core.cst$kw$continue_DASH_block;
|
||||
var G__8819 = expr__8810;
|
||||
return (pred__8809.cljs$core$IFn$_invoke$arity$2 ? pred__8809.cljs$core$IFn$_invoke$arity$2(G__8818,G__8819) : pred__8809.call(null,G__8818,G__8819));
|
||||
})())){
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,self__.finally_block,G__8797,self__.prev,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var G__8820 = cljs.core.cst$kw$prev;
|
||||
var G__8821 = expr__8810;
|
||||
return (pred__8809.cljs$core$IFn$_invoke$arity$2 ? pred__8809.cljs$core$IFn$_invoke$arity$2(G__8820,G__8821) : pred__8809.call(null,G__8820,G__8821));
|
||||
})())){
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,self__.finally_block,self__.continue_block,G__8797,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,self__.finally_block,self__.continue_block,self__.prev,self__.__meta,cljs.core.assoc.cljs$core$IFn$_invoke$arity$3(self__.__extmap,k__5352__auto__,G__8797),null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$ISeqable$_seq$arity$1 = (function (this__5356__auto__){
|
||||
var self__ = this;
|
||||
var this__5356__auto____$1 = this;
|
||||
return cljs.core.seq(cljs.core.concat.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentVector(null, 5, 5, cljs.core.PersistentVector.EMPTY_NODE, [(new cljs.core.MapEntry(cljs.core.cst$kw$catch_DASH_block,self__.catch_block,null)),(new cljs.core.MapEntry(cljs.core.cst$kw$catch_DASH_exception,self__.catch_exception,null)),(new cljs.core.MapEntry(cljs.core.cst$kw$finally_DASH_block,self__.finally_block,null)),(new cljs.core.MapEntry(cljs.core.cst$kw$continue_DASH_block,self__.continue_block,null)),(new cljs.core.MapEntry(cljs.core.cst$kw$prev,self__.prev,null))], null),self__.__extmap));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$IWithMeta$_with_meta$arity$2 = (function (this__5342__auto__,G__8797){
|
||||
var self__ = this;
|
||||
var this__5342__auto____$1 = this;
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(self__.catch_block,self__.catch_exception,self__.finally_block,self__.continue_block,self__.prev,G__8797,self__.__extmap,self__.__hash));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.prototype.cljs$core$ICollection$_conj$arity$2 = (function (this__5348__auto__,entry__5349__auto__){
|
||||
var self__ = this;
|
||||
var this__5348__auto____$1 = this;
|
||||
if(cljs.core.vector_QMARK_(entry__5349__auto__)){
|
||||
return this__5348__auto____$1.cljs$core$IAssociative$_assoc$arity$3(null,cljs.core._nth.cljs$core$IFn$_invoke$arity$2(entry__5349__auto__,(0)),cljs.core._nth.cljs$core$IFn$_invoke$arity$2(entry__5349__auto__,(1)));
|
||||
} else {
|
||||
return cljs.core.reduce.cljs$core$IFn$_invoke$arity$3(cljs.core._conj,this__5348__auto____$1,entry__5349__auto__);
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 5, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$catch_DASH_block,cljs.core.with_meta(cljs.core.cst$sym$catch_DASH_exception,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,cljs.core.cst$sym$Class], null)),cljs.core.cst$sym$finally_DASH_block,cljs.core.cst$sym$continue_DASH_block,cljs.core.cst$sym$prev], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.cljs$lang$ctorPrSeq = (function (this__5389__auto__){
|
||||
return (new cljs.core.List(null,"cljs.core.async.impl.ioc-helpers/ExceptionFrame",null,(1),null));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.ioc_helpers.ExceptionFrame.cljs$lang$ctorPrWriter = (function (this__5389__auto__,writer__5390__auto__){
|
||||
return cljs.core._write(writer__5390__auto__,"cljs.core.async.impl.ioc-helpers/ExceptionFrame");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.ioc-helpers/ExceptionFrame.
|
||||
*/
|
||||
cljs.core.async.impl.ioc_helpers.__GT_ExceptionFrame = (function cljs$core$async$impl$ioc_helpers$__GT_ExceptionFrame(catch_block,catch_exception,finally_block,continue_block,prev){
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(catch_block,catch_exception,finally_block,continue_block,prev,null,null,null));
|
||||
});
|
||||
|
||||
/**
|
||||
* Factory function for cljs.core.async.impl.ioc-helpers/ExceptionFrame, taking a map of keywords to field values.
|
||||
*/
|
||||
cljs.core.async.impl.ioc_helpers.map__GT_ExceptionFrame = (function cljs$core$async$impl$ioc_helpers$map__GT_ExceptionFrame(G__8801){
|
||||
var extmap__5385__auto__ = (function (){var G__8822 = cljs.core.dissoc.cljs$core$IFn$_invoke$arity$variadic(G__8801,cljs.core.cst$kw$catch_DASH_block,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.cst$kw$catch_DASH_exception,cljs.core.cst$kw$finally_DASH_block,cljs.core.cst$kw$continue_DASH_block,cljs.core.cst$kw$prev], 0));
|
||||
if(cljs.core.record_QMARK_(G__8801)){
|
||||
return cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,G__8822);
|
||||
} else {
|
||||
return G__8822;
|
||||
}
|
||||
})();
|
||||
return (new cljs.core.async.impl.ioc_helpers.ExceptionFrame(cljs.core.cst$kw$catch_DASH_block.cljs$core$IFn$_invoke$arity$1(G__8801),cljs.core.cst$kw$catch_DASH_exception.cljs$core$IFn$_invoke$arity$1(G__8801),cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(G__8801),cljs.core.cst$kw$continue_DASH_block.cljs$core$IFn$_invoke$arity$1(G__8801),cljs.core.cst$kw$prev.cljs$core$IFn$_invoke$arity$1(G__8801),null,cljs.core.not_empty(extmap__5385__auto__),null));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.ioc_helpers.add_exception_frame = (function cljs$core$async$impl$ioc_helpers$add_exception_frame(state,catch_block,catch_exception,finally_block,continue_block){
|
||||
var statearr_8825 = state;
|
||||
(statearr_8825[(4)] = cljs.core.async.impl.ioc_helpers.__GT_ExceptionFrame(catch_block,catch_exception,finally_block,continue_block,cljs.core.async.impl.ioc_helpers.aget_object(state,(4))));
|
||||
|
||||
return statearr_8825;
|
||||
});
|
||||
cljs.core.async.impl.ioc_helpers.process_exception = (function cljs$core$async$impl$ioc_helpers$process_exception(state){
|
||||
while(true){
|
||||
var exception_frame = cljs.core.async.impl.ioc_helpers.aget_object(state,(4));
|
||||
var catch_block = cljs.core.cst$kw$catch_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame);
|
||||
var catch_exception = cljs.core.cst$kw$catch_DASH_exception.cljs$core$IFn$_invoke$arity$1(exception_frame);
|
||||
var exception = cljs.core.async.impl.ioc_helpers.aget_object(state,(5));
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = exception;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return cljs.core.not(exception_frame);
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
throw exception;
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = exception;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
var and__5043__auto____$1 = catch_block;
|
||||
if(cljs.core.truth_(and__5043__auto____$1)){
|
||||
return (exception instanceof catch_exception);
|
||||
} else {
|
||||
return and__5043__auto____$1;
|
||||
}
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
var statearr_8826 = state;
|
||||
(statearr_8826[(1)] = catch_block);
|
||||
|
||||
(statearr_8826[(2)] = exception);
|
||||
|
||||
(statearr_8826[(5)] = null);
|
||||
|
||||
(statearr_8826[(4)] = cljs.core.assoc.cljs$core$IFn$_invoke$arity$variadic(exception_frame,cljs.core.cst$kw$catch_DASH_block,null,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.cst$kw$catch_DASH_exception,null], 0)));
|
||||
|
||||
return statearr_8826;
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = exception;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return ((cljs.core.not(catch_block)) && (cljs.core.not(cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame))));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
var statearr_8827_8831 = state;
|
||||
(statearr_8827_8831[(4)] = cljs.core.cst$kw$prev.cljs$core$IFn$_invoke$arity$1(exception_frame));
|
||||
|
||||
|
||||
var G__8832 = state;
|
||||
state = G__8832;
|
||||
continue;
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = exception;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
var and__5043__auto____$1 = cljs.core.not(catch_block);
|
||||
if(and__5043__auto____$1){
|
||||
return cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame);
|
||||
} else {
|
||||
return and__5043__auto____$1;
|
||||
}
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
var statearr_8828 = state;
|
||||
(statearr_8828[(1)] = cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame));
|
||||
|
||||
(statearr_8828[(4)] = cljs.core.assoc.cljs$core$IFn$_invoke$arity$3(exception_frame,cljs.core.cst$kw$finally_DASH_block,null));
|
||||
|
||||
return statearr_8828;
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = cljs.core.not(exception);
|
||||
if(and__5043__auto__){
|
||||
return cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame);
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
var statearr_8829 = state;
|
||||
(statearr_8829[(1)] = cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame));
|
||||
|
||||
(statearr_8829[(4)] = cljs.core.assoc.cljs$core$IFn$_invoke$arity$3(exception_frame,cljs.core.cst$kw$finally_DASH_block,null));
|
||||
|
||||
return statearr_8829;
|
||||
} else {
|
||||
if(((cljs.core.not(exception)) && (cljs.core.not(cljs.core.cst$kw$finally_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame))))){
|
||||
var statearr_8830 = state;
|
||||
(statearr_8830[(1)] = cljs.core.cst$kw$continue_DASH_block.cljs$core$IFn$_invoke$arity$1(exception_frame));
|
||||
|
||||
(statearr_8830[(4)] = cljs.core.cst$kw$prev.cljs$core$IFn$_invoke$arity$1(exception_frame));
|
||||
|
||||
return statearr_8830;
|
||||
} else {
|
||||
throw (new Error("No matching clause"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
;; Copyright (c) Rich Hickey and contributors. All rights reserved.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.core.async.impl.protocols)
|
||||
|
||||
(def ^:const MAX-QUEUE-SIZE 1024)
|
||||
|
||||
(defprotocol ReadPort
|
||||
(take! [port fn1-handler] "derefable val if taken, nil if take was enqueued"))
|
||||
|
||||
(defprotocol WritePort
|
||||
(put! [port val fn1-handler] "derefable boolean (false if already closed) if handled, nil if put was enqueued.
|
||||
Must throw on nil val."))
|
||||
|
||||
(defprotocol Channel
|
||||
(close! [chan])
|
||||
(closed? [chan]))
|
||||
|
||||
(defprotocol Handler
|
||||
(active? [h] "returns true if has callback. Must work w/o lock")
|
||||
#_(lock-id [h] "a unique id for lock acquisition order, 0 if no lock")
|
||||
(commit [h] "commit to fulfilling its end of the transfer, returns cb. Must be called within lock"))
|
||||
|
||||
(defprotocol Buffer
|
||||
(full? [b])
|
||||
(remove! [b])
|
||||
(add!* [b itm]))
|
||||
|
||||
(defn add!
|
||||
([b] b)
|
||||
([b itm]
|
||||
(assert (not (nil? itm)))
|
||||
(add!* b itm)))
|
||||
|
||||
;; Defines a buffer that will never block (return true to full?)
|
||||
(defprotocol UnblockingBuffer)
|
||||
Executable
+284
@@ -0,0 +1,284 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.core.async.impl.protocols');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
cljs.core.async.impl.protocols.MAX_QUEUE_SIZE = (1024);
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.protocols.ReadPort = function(){};
|
||||
|
||||
var cljs$core$async$impl$protocols$ReadPort$take_BANG_$dyn_5689 = (function (port,fn1_handler){
|
||||
var x__5393__auto__ = (((port == null))?null:port);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.take_BANG_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$2 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$2(port,fn1_handler) : m__5394__auto__.call(null,port,fn1_handler));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.take_BANG_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$2 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$2(port,fn1_handler) : m__5392__auto__.call(null,port,fn1_handler));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("ReadPort.take!",port);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* derefable val if taken, nil if take was enqueued
|
||||
*/
|
||||
cljs.core.async.impl.protocols.take_BANG_ = (function cljs$core$async$impl$protocols$take_BANG_(port,fn1_handler){
|
||||
if((((!((port == null)))) && ((!((port.cljs$core$async$impl$protocols$ReadPort$take_BANG_$arity$2 == null)))))){
|
||||
return port.cljs$core$async$impl$protocols$ReadPort$take_BANG_$arity$2(port,fn1_handler);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$ReadPort$take_BANG_$dyn_5689(port,fn1_handler);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.protocols.WritePort = function(){};
|
||||
|
||||
var cljs$core$async$impl$protocols$WritePort$put_BANG_$dyn_5690 = (function (port,val,fn1_handler){
|
||||
var x__5393__auto__ = (((port == null))?null:port);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.put_BANG_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$3 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$3(port,val,fn1_handler) : m__5394__auto__.call(null,port,val,fn1_handler));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.put_BANG_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$3 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$3(port,val,fn1_handler) : m__5392__auto__.call(null,port,val,fn1_handler));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("WritePort.put!",port);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* derefable boolean (false if already closed) if handled, nil if put was enqueued.
|
||||
* Must throw on nil val.
|
||||
*/
|
||||
cljs.core.async.impl.protocols.put_BANG_ = (function cljs$core$async$impl$protocols$put_BANG_(port,val,fn1_handler){
|
||||
if((((!((port == null)))) && ((!((port.cljs$core$async$impl$protocols$WritePort$put_BANG_$arity$3 == null)))))){
|
||||
return port.cljs$core$async$impl$protocols$WritePort$put_BANG_$arity$3(port,val,fn1_handler);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$WritePort$put_BANG_$dyn_5690(port,val,fn1_handler);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.protocols.Channel = function(){};
|
||||
|
||||
var cljs$core$async$impl$protocols$Channel$close_BANG_$dyn_5691 = (function (chan){
|
||||
var x__5393__auto__ = (((chan == null))?null:chan);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.close_BANG_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(chan) : m__5394__auto__.call(null,chan));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.close_BANG_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(chan) : m__5392__auto__.call(null,chan));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Channel.close!",chan);
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.protocols.close_BANG_ = (function cljs$core$async$impl$protocols$close_BANG_(chan){
|
||||
if((((!((chan == null)))) && ((!((chan.cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1 == null)))))){
|
||||
return chan.cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1(chan);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Channel$close_BANG_$dyn_5691(chan);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$core$async$impl$protocols$Channel$closed_QMARK_$dyn_5692 = (function (chan){
|
||||
var x__5393__auto__ = (((chan == null))?null:chan);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.closed_QMARK_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(chan) : m__5394__auto__.call(null,chan));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.closed_QMARK_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(chan) : m__5392__auto__.call(null,chan));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Channel.closed?",chan);
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.protocols.closed_QMARK_ = (function cljs$core$async$impl$protocols$closed_QMARK_(chan){
|
||||
if((((!((chan == null)))) && ((!((chan.cljs$core$async$impl$protocols$Channel$closed_QMARK_$arity$1 == null)))))){
|
||||
return chan.cljs$core$async$impl$protocols$Channel$closed_QMARK_$arity$1(chan);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Channel$closed_QMARK_$dyn_5692(chan);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.protocols.Handler = function(){};
|
||||
|
||||
var cljs$core$async$impl$protocols$Handler$active_QMARK_$dyn_5693 = (function (h){
|
||||
var x__5393__auto__ = (((h == null))?null:h);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.active_QMARK_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(h) : m__5394__auto__.call(null,h));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.active_QMARK_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(h) : m__5392__auto__.call(null,h));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Handler.active?",h);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* returns true if has callback. Must work w/o lock
|
||||
*/
|
||||
cljs.core.async.impl.protocols.active_QMARK_ = (function cljs$core$async$impl$protocols$active_QMARK_(h){
|
||||
if((((!((h == null)))) && ((!((h.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1 == null)))))){
|
||||
return h.cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1(h);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Handler$active_QMARK_$dyn_5693(h);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$core$async$impl$protocols$Handler$commit$dyn_5694 = (function (h){
|
||||
var x__5393__auto__ = (((h == null))?null:h);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.commit[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(h) : m__5394__auto__.call(null,h));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.commit["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(h) : m__5392__auto__.call(null,h));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Handler.commit",h);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* commit to fulfilling its end of the transfer, returns cb. Must be called within lock
|
||||
*/
|
||||
cljs.core.async.impl.protocols.commit = (function cljs$core$async$impl$protocols$commit(h){
|
||||
if((((!((h == null)))) && ((!((h.cljs$core$async$impl$protocols$Handler$commit$arity$1 == null)))))){
|
||||
return h.cljs$core$async$impl$protocols$Handler$commit$arity$1(h);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Handler$commit$dyn_5694(h);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.protocols.Buffer = function(){};
|
||||
|
||||
var cljs$core$async$impl$protocols$Buffer$full_QMARK_$dyn_5695 = (function (b){
|
||||
var x__5393__auto__ = (((b == null))?null:b);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.full_QMARK_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(b) : m__5394__auto__.call(null,b));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.full_QMARK_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(b) : m__5392__auto__.call(null,b));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Buffer.full?",b);
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.protocols.full_QMARK_ = (function cljs$core$async$impl$protocols$full_QMARK_(b){
|
||||
if((((!((b == null)))) && ((!((b.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1 == null)))))){
|
||||
return b.cljs$core$async$impl$protocols$Buffer$full_QMARK_$arity$1(b);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Buffer$full_QMARK_$dyn_5695(b);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$core$async$impl$protocols$Buffer$remove_BANG_$dyn_5696 = (function (b){
|
||||
var x__5393__auto__ = (((b == null))?null:b);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.remove_BANG_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(b) : m__5394__auto__.call(null,b));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.remove_BANG_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(b) : m__5392__auto__.call(null,b));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Buffer.remove!",b);
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.protocols.remove_BANG_ = (function cljs$core$async$impl$protocols$remove_BANG_(b){
|
||||
if((((!((b == null)))) && ((!((b.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1 == null)))))){
|
||||
return b.cljs$core$async$impl$protocols$Buffer$remove_BANG_$arity$1(b);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Buffer$remove_BANG_$dyn_5696(b);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$dyn_5697 = (function (b,itm){
|
||||
var x__5393__auto__ = (((b == null))?null:b);
|
||||
var m__5394__auto__ = (cljs.core.async.impl.protocols.add_BANG__STAR_[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$2 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$2(b,itm) : m__5394__auto__.call(null,b,itm));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.core.async.impl.protocols.add_BANG__STAR_["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$2 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$2(b,itm) : m__5392__auto__.call(null,b,itm));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Buffer.add!*",b);
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.core.async.impl.protocols.add_BANG__STAR_ = (function cljs$core$async$impl$protocols$add_BANG__STAR_(b,itm){
|
||||
if((((!((b == null)))) && ((!((b.cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$arity$2 == null)))))){
|
||||
return b.cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$arity$2(b,itm);
|
||||
} else {
|
||||
return cljs$core$async$impl$protocols$Buffer$add_BANG__STAR_$dyn_5697(b,itm);
|
||||
}
|
||||
});
|
||||
|
||||
cljs.core.async.impl.protocols.add_BANG_ = (function cljs$core$async$impl$protocols$add_BANG_(var_args){
|
||||
var G__5699 = arguments.length;
|
||||
switch (G__5699) {
|
||||
case 1:
|
||||
return cljs.core.async.impl.protocols.add_BANG_.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.core.async.impl.protocols.add_BANG_.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.core.async.impl.protocols.add_BANG_.cljs$core$IFn$_invoke$arity$1 = (function (b){
|
||||
return b;
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.protocols.add_BANG_.cljs$core$IFn$_invoke$arity$2 = (function (b,itm){
|
||||
if((!((itm == null)))){
|
||||
} else {
|
||||
throw (new Error("Assert failed: (not (nil? itm))"));
|
||||
}
|
||||
|
||||
return cljs.core.async.impl.protocols.add_BANG__STAR_(b,itm);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.protocols.add_BANG_.cljs$lang$maxFixedArity = 2);
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.core.async.impl.protocols.UnblockingBuffer = function(){};
|
||||
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
;; Copyright (c) Rich Hickey and contributors. All rights reserved.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.core.async.impl.timers
|
||||
(:require [cljs.core.async.impl.protocols :as impl]
|
||||
[cljs.core.async.impl.channels :as channels]
|
||||
[cljs.core.async.impl.dispatch :as dispatch]))
|
||||
|
||||
(def MAX_LEVEL 15) ;; 16 levels
|
||||
(def P (/ 1 2))
|
||||
|
||||
(defn random-level
|
||||
([] (random-level 0))
|
||||
([level]
|
||||
(if (and (< (.random js/Math) P)
|
||||
(< level MAX_LEVEL))
|
||||
(recur (inc level))
|
||||
level)))
|
||||
|
||||
(deftype SkipListNode [key ^:mutable val forward]
|
||||
ISeqable
|
||||
(-seq [coll]
|
||||
(list key val))
|
||||
|
||||
IPrintWithWriter
|
||||
(-pr-writer [coll writer opts]
|
||||
(pr-sequential-writer writer pr-writer "[" " " "]" opts coll)))
|
||||
|
||||
(defn skip-list-node
|
||||
([level] (skip-list-node nil nil level))
|
||||
([k v level]
|
||||
(let [arr (make-array (inc level))]
|
||||
(loop [i 0]
|
||||
(when (< i (alength arr))
|
||||
(aset arr i nil)
|
||||
(recur (inc i))))
|
||||
(SkipListNode. k v arr))))
|
||||
|
||||
(defn least-greater-node
|
||||
([x k level] (least-greater-node x k level nil))
|
||||
([x k level update]
|
||||
(if-not (neg? level)
|
||||
(let [x (loop [x x]
|
||||
(if-let [x' (aget (.-forward x) level)]
|
||||
(if (< (.-key x') k)
|
||||
(recur x')
|
||||
x)
|
||||
x))]
|
||||
(when-not (nil? update)
|
||||
(aset update level x))
|
||||
(recur x k (dec level) update))
|
||||
x)))
|
||||
|
||||
(deftype SkipList [header ^:mutable level]
|
||||
Object
|
||||
(put [coll k v]
|
||||
(let [update (make-array MAX_LEVEL)
|
||||
x (least-greater-node header k level update)
|
||||
x (aget (.-forward x) 0)]
|
||||
(if (and (not (nil? x)) (== (.-key x) k))
|
||||
(set! (.-val x) v)
|
||||
(let [new-level (random-level)]
|
||||
(when (> new-level level)
|
||||
(loop [i (inc level)]
|
||||
(when (<= i (inc new-level))
|
||||
(aset update i header)
|
||||
(recur (inc i))))
|
||||
(set! level new-level))
|
||||
(let [x (skip-list-node k v (make-array new-level))]
|
||||
(loop [i 0]
|
||||
(when (<= i level)
|
||||
(let [links (.-forward (aget update i))]
|
||||
(aset (.-forward x) i (aget links i))
|
||||
(aset links i x)))))))))
|
||||
|
||||
(remove [coll k]
|
||||
(let [update (make-array MAX_LEVEL)
|
||||
x (least-greater-node header k level update)
|
||||
x (aget (.-forward x) 0)]
|
||||
(when (and (not (nil? x)) (== (.-key x) k))
|
||||
(loop [i 0]
|
||||
(when (<= i level)
|
||||
(let [links (.-forward (aget update i))]
|
||||
(if (identical? (aget links i) x)
|
||||
(do
|
||||
(aset links i (aget (.-forward x) i))
|
||||
(recur (inc i)))
|
||||
(recur (inc i))))))
|
||||
(while (and (> level 0)
|
||||
(nil? (aget (.-forward header) level)))
|
||||
(set! level (dec level))))))
|
||||
|
||||
(ceilingEntry [coll k]
|
||||
(loop [x header level level]
|
||||
(if-not (neg? level)
|
||||
(let [nx (loop [x x]
|
||||
(let [x' (aget (.-forward x) level)]
|
||||
(when-not (nil? x')
|
||||
(if (>= (.-key x') k)
|
||||
x'
|
||||
(recur x')))))]
|
||||
(if-not (nil? nx)
|
||||
(recur nx (dec level))
|
||||
(recur x (dec level))))
|
||||
(when-not (identical? x header)
|
||||
x))))
|
||||
|
||||
(floorEntry [coll k]
|
||||
(loop [x header level level]
|
||||
(if-not (neg? level)
|
||||
(let [nx (loop [x x]
|
||||
(let [x' (aget (.-forward x) level)]
|
||||
(if-not (nil? x')
|
||||
(if (> (.-key x') k)
|
||||
x
|
||||
(recur x'))
|
||||
(when (zero? level)
|
||||
x))))]
|
||||
(if nx
|
||||
(recur nx (dec level))
|
||||
(recur x (dec level))))
|
||||
(when-not (identical? x header)
|
||||
x))))
|
||||
|
||||
ISeqable
|
||||
(-seq [coll]
|
||||
(letfn [(iter [node]
|
||||
(lazy-seq
|
||||
(when-not (nil? node)
|
||||
(cons [(.-key node) (.-val node)]
|
||||
(iter (aget (.-forward node) 0))))))]
|
||||
(iter (aget (.-forward header) 0))))
|
||||
|
||||
IPrintWithWriter
|
||||
(-pr-writer [coll writer opts]
|
||||
(let [pr-pair (fn [keyval]
|
||||
(pr-sequential-writer writer pr-writer "" " " "" opts keyval))]
|
||||
(pr-sequential-writer writer pr-pair "{" ", " "}" opts coll))))
|
||||
|
||||
(defn skip-list []
|
||||
(SkipList. (skip-list-node 0) 0))
|
||||
|
||||
(def timeouts-map (skip-list))
|
||||
|
||||
(def TIMEOUT_RESOLUTION_MS 10)
|
||||
|
||||
(defn timeout
|
||||
"returns a channel that will close after msecs"
|
||||
[msecs]
|
||||
(let [timeout (+ (.valueOf (js/Date.)) msecs)
|
||||
me (.ceilingEntry timeouts-map timeout)]
|
||||
(or (when (and me (< (.-key me) (+ timeout TIMEOUT_RESOLUTION_MS)))
|
||||
(.-val me))
|
||||
(let [timeout-channel (channels/chan nil)]
|
||||
(.put timeouts-map timeout timeout-channel)
|
||||
(dispatch/queue-delay
|
||||
(fn []
|
||||
(.remove timeouts-map timeout)
|
||||
(impl/close! timeout-channel))
|
||||
msecs)
|
||||
timeout-channel))))
|
||||
|
||||
Executable
+470
@@ -0,0 +1,470 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.core.async.impl.timers');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.core.async.impl.protocols');
|
||||
goog.require('cljs.core.async.impl.channels');
|
||||
goog.require('cljs.core.async.impl.dispatch');
|
||||
cljs.core.async.impl.timers.MAX_LEVEL = (15);
|
||||
cljs.core.async.impl.timers.P = ((1) / (2));
|
||||
cljs.core.async.impl.timers.random_level = (function cljs$core$async$impl$timers$random_level(var_args){
|
||||
var G__8836 = arguments.length;
|
||||
switch (G__8836) {
|
||||
case 0:
|
||||
return cljs.core.async.impl.timers.random_level.cljs$core$IFn$_invoke$arity$0();
|
||||
|
||||
break;
|
||||
case 1:
|
||||
return cljs.core.async.impl.timers.random_level.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.core.async.impl.timers.random_level.cljs$core$IFn$_invoke$arity$0 = (function (){
|
||||
return cljs.core.async.impl.timers.random_level.cljs$core$IFn$_invoke$arity$1((0));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.random_level.cljs$core$IFn$_invoke$arity$1 = (function (level){
|
||||
while(true){
|
||||
if((((Math.random() < cljs.core.async.impl.timers.P)) && ((level < cljs.core.async.impl.timers.MAX_LEVEL)))){
|
||||
var G__8838 = (level + (1));
|
||||
level = G__8838;
|
||||
continue;
|
||||
} else {
|
||||
return level;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.random_level.cljs$lang$maxFixedArity = 1);
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.ISeqable}
|
||||
* @implements {cljs.core.IPrintWithWriter}
|
||||
*/
|
||||
cljs.core.async.impl.timers.SkipListNode = (function (key,val,forward){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
this.forward = forward;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2155872256;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.timers.SkipListNode.prototype.cljs$core$ISeqable$_seq$arity$1 = (function (coll){
|
||||
var self__ = this;
|
||||
var coll__$1 = this;
|
||||
return (new cljs.core.List(null,self__.key,(new cljs.core.List(null,self__.val,null,(1),null)),(2),null));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipListNode.prototype.cljs$core$IPrintWithWriter$_pr_writer$arity$3 = (function (coll,writer,opts){
|
||||
var self__ = this;
|
||||
var coll__$1 = this;
|
||||
return cljs.core.pr_sequential_writer(writer,cljs.core.pr_writer,"["," ","]",opts,coll__$1);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipListNode.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 3, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$key,cljs.core.with_meta(cljs.core.cst$sym$val,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.cst$sym$forward], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipListNode.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.timers.SkipListNode.cljs$lang$ctorStr = "cljs.core.async.impl.timers/SkipListNode");
|
||||
|
||||
(cljs.core.async.impl.timers.SkipListNode.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.timers/SkipListNode");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.timers/SkipListNode.
|
||||
*/
|
||||
cljs.core.async.impl.timers.__GT_SkipListNode = (function cljs$core$async$impl$timers$__GT_SkipListNode(key,val,forward){
|
||||
return (new cljs.core.async.impl.timers.SkipListNode(key,val,forward));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.timers.skip_list_node = (function cljs$core$async$impl$timers$skip_list_node(var_args){
|
||||
var G__8840 = arguments.length;
|
||||
switch (G__8840) {
|
||||
case 1:
|
||||
return cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$1 = (function (level){
|
||||
return cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$3(null,null,level);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$3 = (function (k,v,level){
|
||||
var arr = (new Array((level + (1))));
|
||||
var i_8842 = (0);
|
||||
while(true){
|
||||
if((i_8842 < arr.length)){
|
||||
(arr[i_8842] = null);
|
||||
|
||||
var G__8843 = (i_8842 + (1));
|
||||
i_8842 = G__8843;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (new cljs.core.async.impl.timers.SkipListNode(k,v,arr));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.skip_list_node.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
cljs.core.async.impl.timers.least_greater_node = (function cljs$core$async$impl$timers$least_greater_node(var_args){
|
||||
var G__8845 = arguments.length;
|
||||
switch (G__8845) {
|
||||
case 3:
|
||||
return cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
case 4:
|
||||
return cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$4((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$3 = (function (x,k,level){
|
||||
return cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$4(x,k,level,null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$4 = (function (x,k,level,update){
|
||||
while(true){
|
||||
if((!((level < (0))))){
|
||||
var x__$1 = (function (){var x__$1 = x;
|
||||
while(true){
|
||||
var temp__4655__auto__ = (x__$1.forward[level]);
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var x_SINGLEQUOTE_ = temp__4655__auto__;
|
||||
if((x_SINGLEQUOTE_.key < k)){
|
||||
var G__8847 = x_SINGLEQUOTE_;
|
||||
x__$1 = G__8847;
|
||||
continue;
|
||||
} else {
|
||||
return x__$1;
|
||||
}
|
||||
} else {
|
||||
return x__$1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})();
|
||||
if((update == null)){
|
||||
} else {
|
||||
(update[level] = x__$1);
|
||||
}
|
||||
|
||||
var G__8848 = x__$1;
|
||||
var G__8849 = k;
|
||||
var G__8850 = (level - (1));
|
||||
var G__8851 = update;
|
||||
x = G__8848;
|
||||
k = G__8849;
|
||||
level = G__8850;
|
||||
update = G__8851;
|
||||
continue;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.least_greater_node.cljs$lang$maxFixedArity = 4);
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.async.impl.timers.Object}
|
||||
* @implements {cljs.core.ISeqable}
|
||||
* @implements {cljs.core.IPrintWithWriter}
|
||||
*/
|
||||
cljs.core.async.impl.timers.SkipList = (function (header,level){
|
||||
this.header = header;
|
||||
this.level = level;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2155872256;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 0;
|
||||
});
|
||||
(cljs.core.async.impl.timers.SkipList.prototype.put = (function (k,v){
|
||||
var self__ = this;
|
||||
var coll = this;
|
||||
var update = (new Array(cljs.core.async.impl.timers.MAX_LEVEL));
|
||||
var x = cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$4(self__.header,k,self__.level,update);
|
||||
var x__$1 = (x.forward[(0)]);
|
||||
if((((!((x__$1 == null)))) && ((x__$1.key === k)))){
|
||||
return (x__$1.val = v);
|
||||
} else {
|
||||
var new_level = cljs.core.async.impl.timers.random_level.cljs$core$IFn$_invoke$arity$0();
|
||||
if((new_level > self__.level)){
|
||||
var i_8852 = (self__.level + (1));
|
||||
while(true){
|
||||
if((i_8852 <= (new_level + (1)))){
|
||||
(update[i_8852] = self__.header);
|
||||
|
||||
var G__8853 = (i_8852 + (1));
|
||||
i_8852 = G__8853;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
(self__.level = new_level);
|
||||
} else {
|
||||
}
|
||||
|
||||
var x__$2 = cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$3(k,v,(new Array(new_level)));
|
||||
var i = (0);
|
||||
while(true){
|
||||
if((i <= self__.level)){
|
||||
var links = (update[i]).forward;
|
||||
(x__$2.forward[i] = (links[i]));
|
||||
|
||||
return (links[i] = x__$2);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.prototype.remove = (function (k){
|
||||
var self__ = this;
|
||||
var coll = this;
|
||||
var update = (new Array(cljs.core.async.impl.timers.MAX_LEVEL));
|
||||
var x = cljs.core.async.impl.timers.least_greater_node.cljs$core$IFn$_invoke$arity$4(self__.header,k,self__.level,update);
|
||||
var x__$1 = (x.forward[(0)]);
|
||||
if((((!((x__$1 == null)))) && ((x__$1.key === k)))){
|
||||
var i_8854 = (0);
|
||||
while(true){
|
||||
if((i_8854 <= self__.level)){
|
||||
var links_8855 = (update[i_8854]).forward;
|
||||
if(((links_8855[i_8854]) === x__$1)){
|
||||
(links_8855[i_8854] = (x__$1.forward[i_8854]));
|
||||
|
||||
var G__8856 = (i_8854 + (1));
|
||||
i_8854 = G__8856;
|
||||
continue;
|
||||
} else {
|
||||
var G__8857 = (i_8854 + (1));
|
||||
i_8854 = G__8857;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
while(true){
|
||||
if((((self__.level > (0))) && (((self__.header.forward[self__.level]) == null)))){
|
||||
(self__.level = (self__.level - (1)));
|
||||
|
||||
continue;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.prototype.ceilingEntry = (function (k){
|
||||
var self__ = this;
|
||||
var coll = this;
|
||||
var x = self__.header;
|
||||
var level__$1 = self__.level;
|
||||
while(true){
|
||||
if((!((level__$1 < (0))))){
|
||||
var nx = (function (){var x__$1 = x;
|
||||
while(true){
|
||||
var x_SINGLEQUOTE_ = (x__$1.forward[level__$1]);
|
||||
if((x_SINGLEQUOTE_ == null)){
|
||||
return null;
|
||||
} else {
|
||||
if((x_SINGLEQUOTE_.key >= k)){
|
||||
return x_SINGLEQUOTE_;
|
||||
} else {
|
||||
var G__8858 = x_SINGLEQUOTE_;
|
||||
x__$1 = G__8858;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
})();
|
||||
if((!((nx == null)))){
|
||||
var G__8859 = nx;
|
||||
var G__8860 = (level__$1 - (1));
|
||||
x = G__8859;
|
||||
level__$1 = G__8860;
|
||||
continue;
|
||||
} else {
|
||||
var G__8861 = x;
|
||||
var G__8862 = (level__$1 - (1));
|
||||
x = G__8861;
|
||||
level__$1 = G__8862;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if((x === self__.header)){
|
||||
return null;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.prototype.floorEntry = (function (k){
|
||||
var self__ = this;
|
||||
var coll = this;
|
||||
var x = self__.header;
|
||||
var level__$1 = self__.level;
|
||||
while(true){
|
||||
if((!((level__$1 < (0))))){
|
||||
var nx = (function (){var x__$1 = x;
|
||||
while(true){
|
||||
var x_SINGLEQUOTE_ = (x__$1.forward[level__$1]);
|
||||
if((!((x_SINGLEQUOTE_ == null)))){
|
||||
if((x_SINGLEQUOTE_.key > k)){
|
||||
return x__$1;
|
||||
} else {
|
||||
var G__8863 = x_SINGLEQUOTE_;
|
||||
x__$1 = G__8863;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if((level__$1 === (0))){
|
||||
return x__$1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
})();
|
||||
if(cljs.core.truth_(nx)){
|
||||
var G__8864 = nx;
|
||||
var G__8865 = (level__$1 - (1));
|
||||
x = G__8864;
|
||||
level__$1 = G__8865;
|
||||
continue;
|
||||
} else {
|
||||
var G__8866 = x;
|
||||
var G__8867 = (level__$1 - (1));
|
||||
x = G__8866;
|
||||
level__$1 = G__8867;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if((x === self__.header)){
|
||||
return null;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.prototype.cljs$core$ISeqable$_seq$arity$1 = (function (coll){
|
||||
var self__ = this;
|
||||
var coll__$1 = this;
|
||||
var iter = (function cljs$core$async$impl$timers$iter(node){
|
||||
return (new cljs.core.LazySeq(null,(function (){
|
||||
if((node == null)){
|
||||
return null;
|
||||
} else {
|
||||
return cljs.core.cons(new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [node.key,node.val], null),cljs$core$async$impl$timers$iter((node.forward[(0)])));
|
||||
}
|
||||
}),null,null));
|
||||
});
|
||||
return iter((self__.header.forward[(0)]));
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.prototype.cljs$core$IPrintWithWriter$_pr_writer$arity$3 = (function (coll,writer,opts){
|
||||
var self__ = this;
|
||||
var coll__$1 = this;
|
||||
var pr_pair = (function (keyval){
|
||||
return cljs.core.pr_sequential_writer(writer,cljs.core.pr_writer,""," ","",opts,keyval);
|
||||
});
|
||||
return cljs.core.pr_sequential_writer(writer,pr_pair,"{",", ","}",opts,coll__$1);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$header,cljs.core.with_meta(cljs.core.cst$sym$level,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null))], null);
|
||||
}));
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.cljs$lang$type = true);
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.cljs$lang$ctorStr = "cljs.core.async.impl.timers/SkipList");
|
||||
|
||||
(cljs.core.async.impl.timers.SkipList.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.core.async.impl.timers/SkipList");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.core.async.impl.timers/SkipList.
|
||||
*/
|
||||
cljs.core.async.impl.timers.__GT_SkipList = (function cljs$core$async$impl$timers$__GT_SkipList(header,level){
|
||||
return (new cljs.core.async.impl.timers.SkipList(header,level));
|
||||
});
|
||||
|
||||
cljs.core.async.impl.timers.skip_list = (function cljs$core$async$impl$timers$skip_list(){
|
||||
return (new cljs.core.async.impl.timers.SkipList(cljs.core.async.impl.timers.skip_list_node.cljs$core$IFn$_invoke$arity$1((0)),(0)));
|
||||
});
|
||||
cljs.core.async.impl.timers.timeouts_map = cljs.core.async.impl.timers.skip_list();
|
||||
cljs.core.async.impl.timers.TIMEOUT_RESOLUTION_MS = (10);
|
||||
/**
|
||||
* returns a channel that will close after msecs
|
||||
*/
|
||||
cljs.core.async.impl.timers.timeout = (function cljs$core$async$impl$timers$timeout(msecs){
|
||||
var timeout = ((new Date()).valueOf() + msecs);
|
||||
var me = cljs.core.async.impl.timers.timeouts_map.ceilingEntry(timeout);
|
||||
var or__5045__auto__ = (cljs.core.truth_((function (){var and__5043__auto__ = me;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return (me.key < (timeout + cljs.core.async.impl.timers.TIMEOUT_RESOLUTION_MS));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())?me.val:null);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
var timeout_channel = cljs.core.async.impl.channels.chan.cljs$core$IFn$_invoke$arity$1(null);
|
||||
cljs.core.async.impl.timers.timeouts_map.put(timeout,timeout_channel);
|
||||
|
||||
cljs.core.async.impl.dispatch.queue_delay((function (){
|
||||
cljs.core.async.impl.timers.timeouts_map.remove(timeout);
|
||||
|
||||
return cljs.core.async.impl.protocols.close_BANG_(timeout_channel);
|
||||
}),msecs);
|
||||
|
||||
return timeout_channel;
|
||||
}
|
||||
});
|
||||
Executable
+477
@@ -0,0 +1,477 @@
|
||||
goog.provide('cljs.core.constants');
|
||||
goog.require('cljs.core');
|
||||
cljs.core.cst$kw$response = new cljs.core.Keyword(null,"response","response",-1068424192);
|
||||
cljs.core.cst$sym$form = new cljs.core.Symbol(null,"form","form",16469056,null);
|
||||
cljs.core.cst$sym$tag = new cljs.core.Symbol(null,"tag","tag",350170304,null);
|
||||
cljs.core.cst$kw$description = new cljs.core.Keyword(null,"description","description",-1428560544);
|
||||
cljs.core.cst$sym$_AMPERSAND_ = new cljs.core.Symbol(null,"&","&",-2144855648,null);
|
||||
cljs.core.cst$sym$uuid = new cljs.core.Symbol(null,"uuid","uuid",-504564192,null);
|
||||
cljs.core.cst$kw$div$todo_DASH_page = new cljs.core.Keyword(null,"div.todo-page","div.todo-page",-241729984);
|
||||
cljs.core.cst$kw$features = new cljs.core.Keyword(null,"features","features",-1146962336);
|
||||
cljs.core.cst$sym$case_STAR_ = new cljs.core.Symbol(null,"case*","case*",-1938255072,null);
|
||||
cljs.core.cst$sym$after_DASH_render = new cljs.core.Symbol(null,"after-render","after-render",-656902336,null);
|
||||
cljs.core.cst$kw$ex_DASH_kind = new cljs.core.Keyword(null,"ex-kind","ex-kind",1581199296);
|
||||
cljs.core.cst$sym$clauses = new cljs.core.Symbol(null,"clauses","clauses",-1199594528,null);
|
||||
cljs.core.cst$kw$async = new cljs.core.Keyword(null,"async","async",1050769601);
|
||||
cljs.core.cst$sym$end = new cljs.core.Symbol(null,"end","end",1372345569,null);
|
||||
cljs.core.cst$sym$defrecord_STAR_ = new cljs.core.Symbol(null,"defrecord*","defrecord*",-1936366207,null);
|
||||
cljs.core.cst$sym$meta8942 = new cljs.core.Symbol(null,"meta8942","meta8942",1074984321,null);
|
||||
cljs.core.cst$sym$base = new cljs.core.Symbol(null,"base","base",1825810849,null);
|
||||
cljs.core.cst$sym$obj = new cljs.core.Symbol(null,"obj","obj",-1672671807,null);
|
||||
cljs.core.cst$kw$finally = new cljs.core.Keyword(null,"finally","finally",1589088705);
|
||||
cljs.core.cst$kw$data_DASH_index = new cljs.core.Keyword(null,"data-index","data-index",1161508385);
|
||||
cljs.core.cst$sym$fqn = new cljs.core.Symbol(null,"fqn","fqn",-1749334463,null);
|
||||
cljs.core.cst$sym$Class = new cljs.core.Symbol(null,"Class","Class",2064526977,null);
|
||||
cljs.core.cst$sym$first = new cljs.core.Symbol(null,"first","first",996428481,null);
|
||||
cljs.core.cst$kw$reader_DASH_error = new cljs.core.Keyword(null,"reader-error","reader-error",1610253121);
|
||||
cljs.core.cst$sym$try = new cljs.core.Symbol(null,"try","try",-1273693247,null);
|
||||
cljs.core.cst$sym$change = new cljs.core.Symbol(null,"change","change",477485025,null);
|
||||
cljs.core.cst$sym$has_DASH_nil_QMARK_ = new cljs.core.Symbol(null,"has-nil?","has-nil?",825886722,null);
|
||||
cljs.core.cst$kw$on_DASH_set = new cljs.core.Keyword(null,"on-set","on-set",-140953470);
|
||||
cljs.core.cst$kw$live_for = new cljs.core.Keyword(null,"live_for","live_for",663254210);
|
||||
cljs.core.cst$kw$format = new cljs.core.Keyword(null,"format","format",-1306924766);
|
||||
cljs.core.cst$sym$puts = new cljs.core.Symbol(null,"puts","puts",-1883877054,null);
|
||||
cljs.core.cst$sym$meta10272 = new cljs.core.Symbol(null,"meta10272","meta10272",1295395426,null);
|
||||
cljs.core.cst$sym$vf = new cljs.core.Symbol(null,"vf","vf",1319108258,null);
|
||||
cljs.core.cst$sym$rear = new cljs.core.Symbol(null,"rear","rear",-900164830,null);
|
||||
cljs.core.cst$sym$hierarchy = new cljs.core.Symbol(null,"hierarchy","hierarchy",587061186,null);
|
||||
cljs.core.cst$sym$iter = new cljs.core.Symbol(null,"iter","iter",-1346195486,null);
|
||||
cljs.core.cst$kw$_STAR_ = new cljs.core.Keyword(null,"*","*",-1294732318);
|
||||
cljs.core.cst$sym$clojure$core_SLASH_list = new cljs.core.Symbol("clojure.core","list","clojure.core/list",-1119203325,null);
|
||||
cljs.core.cst$kw$get = new cljs.core.Keyword(null,"get","get",1683182755);
|
||||
cljs.core.cst$sym$watching = new cljs.core.Symbol(null,"watching","watching",1947648227,null);
|
||||
cljs.core.cst$sym$handler = new cljs.core.Symbol(null,"handler","handler",1444934915,null);
|
||||
cljs.core.cst$sym$step = new cljs.core.Symbol(null,"step","step",-1365547645,null);
|
||||
cljs.core.cst$kw$fname = new cljs.core.Keyword(null,"fname","fname",1500291491);
|
||||
cljs.core.cst$sym$boolean = new cljs.core.Symbol(null,"boolean","boolean",-278886877,null);
|
||||
cljs.core.cst$sym$update_DASH_count = new cljs.core.Symbol(null,"update-count","update-count",-411982269,null);
|
||||
cljs.core.cst$kw$somef = new cljs.core.Keyword(null,"somef","somef",-622590365);
|
||||
cljs.core.cst$sym$reaction = new cljs.core.Symbol(null,"reaction","reaction",2131401315,null);
|
||||
cljs.core.cst$sym$method_DASH_table = new cljs.core.Symbol(null,"method-table","method-table",-1878263165,null);
|
||||
cljs.core.cst$kw$ready = new cljs.core.Keyword(null,"ready","ready",1086465795);
|
||||
cljs.core.cst$sym$chunk = new cljs.core.Symbol(null,"chunk","chunk",449371907,null);
|
||||
cljs.core.cst$sym$callback = new cljs.core.Symbol(null,"callback","callback",935395299,null);
|
||||
cljs.core.cst$kw$matched = new cljs.core.Keyword(null,"matched","matched",-975207164);
|
||||
cljs.core.cst$sym$i = new cljs.core.Symbol(null,"i","i",253690212,null);
|
||||
cljs.core.cst$kw$api = new cljs.core.Keyword(null,"api","api",-899839580);
|
||||
cljs.core.cst$sym$rest = new cljs.core.Symbol(null,"rest","rest",398835108,null);
|
||||
cljs.core.cst$kw$original_DASH_text = new cljs.core.Keyword(null,"original-text","original-text",744448452);
|
||||
cljs.core.cst$kw$namespaced_DASH_map = new cljs.core.Keyword(null,"namespaced-map","namespaced-map",1235665380);
|
||||
cljs.core.cst$kw$meta = new cljs.core.Keyword(null,"meta","meta",1499536964);
|
||||
cljs.core.cst$sym$p = new cljs.core.Symbol(null,"p","p",1791580836,null);
|
||||
cljs.core.cst$sym$s_DASH_pos = new cljs.core.Symbol(null,"s-pos","s-pos",-540562492,null);
|
||||
cljs.core.cst$kw$ul = new cljs.core.Keyword(null,"ul","ul",-1349521403);
|
||||
cljs.core.cst$kw$kf = new cljs.core.Keyword(null,"kf","kf",1608087589);
|
||||
cljs.core.cst$sym$rep_DASH_fn = new cljs.core.Symbol(null,"rep-fn","rep-fn",-1724891035,null);
|
||||
cljs.core.cst$kw$mutes = new cljs.core.Keyword(null,"mutes","mutes",1068806309);
|
||||
cljs.core.cst$kw$keywords_QMARK_ = new cljs.core.Keyword(null,"keywords?","keywords?",764949733);
|
||||
cljs.core.cst$kw$dup = new cljs.core.Keyword(null,"dup","dup",556298533);
|
||||
cljs.core.cst$sym$meta2240 = new cljs.core.Symbol(null,"meta2240","meta2240",-230975163,null);
|
||||
cljs.core.cst$kw$solo = new cljs.core.Keyword(null,"solo","solo",-316350075);
|
||||
cljs.core.cst$kw$li$message = new cljs.core.Keyword(null,"li.message","li.message",-992924155);
|
||||
cljs.core.cst$kw$read = new cljs.core.Keyword(null,"read","read",1140058661);
|
||||
cljs.core.cst$kw$key = new cljs.core.Keyword(null,"key","key",-1516042587);
|
||||
cljs.core.cst$sym$comp = new cljs.core.Symbol(null,"comp","comp",-1462482139,null);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_array_DASH_map = new cljs.core.Symbol("cljs.core","array-map","cljs.core/array-map",-1519210683,null);
|
||||
cljs.core.cst$sym$dispatch_DASH_fn = new cljs.core.Symbol(null,"dispatch-fn","dispatch-fn",-1401088155,null);
|
||||
cljs.core.cst$kw$placeholder = new cljs.core.Keyword(null,"placeholder","placeholder",-104873083);
|
||||
cljs.core.cst$sym$buffer = new cljs.core.Symbol(null,"buffer","buffer",-2037140571,null);
|
||||
cljs.core.cst$kw$cljs$core$async_SLASH_nothing = new cljs.core.Keyword("cljs.core.async","nothing","cljs.core.async/nothing",-69252123);
|
||||
cljs.core.cst$kw$index = new cljs.core.Keyword(null,"index","index",-1531685915);
|
||||
cljs.core.cst$kw$i_SHARP_back$btn = new cljs.core.Keyword(null,"i#back.btn","i#back.btn",-1215314874);
|
||||
cljs.core.cst$sym$prev_DASH_column = new cljs.core.Symbol(null,"prev-column","prev-column",324083974,null);
|
||||
cljs.core.cst$kw$reader_DASH_exception = new cljs.core.Keyword(null,"reader-exception","reader-exception",-1938323098);
|
||||
cljs.core.cst$kw$not_DASH_initialized = new cljs.core.Keyword(null,"not-initialized","not-initialized",-1937378906);
|
||||
cljs.core.cst$kw$else = new cljs.core.Keyword(null,"else","else",-1508377146);
|
||||
cljs.core.cst$sym$left = new cljs.core.Symbol(null,"left","left",1241415590,null);
|
||||
cljs.core.cst$kw$li$todo_DASH_line = new cljs.core.Keyword(null,"li.todo-line","li.todo-line",-120685561);
|
||||
cljs.core.cst$sym$ns_STAR_ = new cljs.core.Symbol(null,"ns*","ns*",1840949383,null);
|
||||
cljs.core.cst$kw$failure = new cljs.core.Keyword(null,"failure","failure",720415879);
|
||||
cljs.core.cst$kw$offset = new cljs.core.Keyword(null,"offset","offset",296498311);
|
||||
cljs.core.cst$sym$path = new cljs.core.Symbol(null,"path","path",1452340359,null);
|
||||
cljs.core.cst$kw$cljs$core_SLASH_none = new cljs.core.Keyword("cljs.core","none","cljs.core/none",926646439);
|
||||
cljs.core.cst$sym$shift = new cljs.core.Symbol(null,"shift","shift",-1657295705,null);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_hash_DASH_map = new cljs.core.Symbol("cljs.core","hash-map","cljs.core/hash-map",303385767,null);
|
||||
cljs.core.cst$sym$iters = new cljs.core.Symbol(null,"iters","iters",719353031,null);
|
||||
cljs.core.cst$kw$derefed = new cljs.core.Keyword(null,"derefed","derefed",590684583);
|
||||
cljs.core.cst$sym$meta10264 = new cljs.core.Symbol(null,"meta10264","meta10264",-212104601,null);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_apply = new cljs.core.Symbol("cljs.core","apply","cljs.core/apply",1757277831,null);
|
||||
cljs.core.cst$kw$displayName = new cljs.core.Keyword(null,"displayName","displayName",-809144601);
|
||||
cljs.core.cst$sym$args = new cljs.core.Symbol(null,"args","args",-1338879193,null);
|
||||
cljs.core.cst$sym$active_QMARK_ = new cljs.core.Symbol(null,"active?","active?",2100031303,null);
|
||||
cljs.core.cst$kw$span_SHARP_add_DASH_item$btn = new cljs.core.Keyword(null,"span#add-item.btn","span#add-item.btn",-776494201);
|
||||
cljs.core.cst$sym$xform = new cljs.core.Symbol(null,"xform","xform",-85179481,null);
|
||||
cljs.core.cst$kw$validator = new cljs.core.Keyword(null,"validator","validator",-1966190681);
|
||||
cljs.core.cst$sym$finally = new cljs.core.Symbol(null,"finally","finally",-1065347064,null);
|
||||
cljs.core.cst$kw$method = new cljs.core.Keyword(null,"method","method",55703592);
|
||||
cljs.core.cst$sym$closed = new cljs.core.Symbol(null,"closed","closed",720856168,null);
|
||||
cljs.core.cst$kw$content = new cljs.core.Keyword(null,"content","content",15833224);
|
||||
cljs.core.cst$kw$raw = new cljs.core.Keyword(null,"raw","raw",1604651272);
|
||||
cljs.core.cst$kw$default = new cljs.core.Keyword(null,"default","default",-1987822328);
|
||||
cljs.core.cst$kw$cljsRender = new cljs.core.Keyword(null,"cljsRender","cljsRender",247449928);
|
||||
cljs.core.cst$kw$finally_DASH_block = new cljs.core.Keyword(null,"finally-block","finally-block",832982472);
|
||||
cljs.core.cst$sym$lists_DASH_page = new cljs.core.Symbol(null,"lists-page","lists-page",1789205992,null);
|
||||
cljs.core.cst$sym$prefer_DASH_table = new cljs.core.Symbol(null,"prefer-table","prefer-table",462168584,null);
|
||||
cljs.core.cst$sym$cb = new cljs.core.Symbol(null,"cb","cb",-2064487928,null);
|
||||
cljs.core.cst$sym$cljs$core$async_SLASH_t_cljs$core$async10263 = new cljs.core.Symbol("cljs.core.async","t_cljs$core$async10263","cljs.core.async/t_cljs$core$async10263",-798337432,null);
|
||||
cljs.core.cst$sym$loop_STAR_ = new cljs.core.Symbol(null,"loop*","loop*",615029416,null);
|
||||
cljs.core.cst$sym$watches = new cljs.core.Symbol(null,"watches","watches",1367433992,null);
|
||||
cljs.core.cst$kw$ns = new cljs.core.Keyword(null,"ns","ns",441598760);
|
||||
cljs.core.cst$kw$symbol = new cljs.core.Keyword(null,"symbol","symbol",-1038572696);
|
||||
cljs.core.cst$sym$buf_DASH_fn = new cljs.core.Symbol(null,"buf-fn","buf-fn",-1200281591,null);
|
||||
cljs.core.cst$kw$name = new cljs.core.Keyword(null,"name","name",1843675177);
|
||||
cljs.core.cst$sym$NaN = new cljs.core.Symbol(null,"NaN","NaN",666918153,null);
|
||||
cljs.core.cst$kw$pending = new cljs.core.Keyword(null,"pending","pending",-220036727);
|
||||
cljs.core.cst$sym$rdr = new cljs.core.Symbol(null,"rdr","rdr",190007785,null);
|
||||
cljs.core.cst$sym$bitmap = new cljs.core.Symbol(null,"bitmap","bitmap",501334601,null);
|
||||
cljs.core.cst$sym$_seq = new cljs.core.Symbol(null,"_seq","_seq",-449557847,null);
|
||||
cljs.core.cst$sym$on_DASH_set = new cljs.core.Symbol(null,"on-set","on-set",1499578057,null);
|
||||
cljs.core.cst$sym$nil_DASH_val = new cljs.core.Symbol(null,"nil-val","nil-val",-513933559,null);
|
||||
cljs.core.cst$kw$value = new cljs.core.Keyword(null,"value","value",305978217);
|
||||
cljs.core.cst$sym$solo_DASH_mode = new cljs.core.Symbol(null,"solo-mode","solo-mode",2031788074,null);
|
||||
cljs.core.cst$sym$somef = new cljs.core.Symbol(null,"somef","somef",1017941162,null);
|
||||
cljs.core.cst$sym$meta10267 = new cljs.core.Symbol(null,"meta10267","meta10267",90644714,null);
|
||||
cljs.core.cst$kw$response_DASH_format = new cljs.core.Keyword(null,"response-format","response-format",1664465322);
|
||||
cljs.core.cst$kw$status_DASH_text = new cljs.core.Keyword(null,"status-text","status-text",-1834235478);
|
||||
cljs.core.cst$kw$component_DASH_did_DASH_mount = new cljs.core.Keyword(null,"component-did-mount","component-did-mount",-1126910518);
|
||||
cljs.core.cst$kw$file = new cljs.core.Keyword(null,"file","file",-1269645878);
|
||||
cljs.core.cst$kw$textarea$edit_DASH_item_DASH_text = new cljs.core.Keyword(null,"textarea.edit-item-text","textarea.edit-item-text",-615742998);
|
||||
cljs.core.cst$kw$i_SHARP_add_DASH_item_DASH_done$btn = new cljs.core.Keyword(null,"i#add-item-done.btn","i#add-item-done.btn",-1088566806);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_concat = new cljs.core.Symbol("cljs.core","concat","cljs.core/concat",-1133584918,null);
|
||||
cljs.core.cst$sym$v = new cljs.core.Symbol(null,"v","v",1661996586,null);
|
||||
cljs.core.cst$kw$compute = new cljs.core.Keyword(null,"compute","compute",1555393130);
|
||||
cljs.core.cst$sym$js = new cljs.core.Symbol(null,"js","js",-886355190,null);
|
||||
cljs.core.cst$kw$readers = new cljs.core.Keyword(null,"readers","readers",-2118263030);
|
||||
cljs.core.cst$kw$secretary$core_SLASH_map = new cljs.core.Keyword("secretary.core","map","secretary.core/map",-31086646);
|
||||
cljs.core.cst$kw$end_DASH_column = new cljs.core.Keyword(null,"end-column","end-column",1425389514);
|
||||
cljs.core.cst$sym$riter = new cljs.core.Symbol(null,"riter","riter",-237834262,null);
|
||||
cljs.core.cst$sym$__hash = new cljs.core.Symbol(null,"__hash","__hash",-1328796629,null);
|
||||
cljs.core.cst$sym$meta = new cljs.core.Symbol(null,"meta","meta",-1154898805,null);
|
||||
cljs.core.cst$sym$_meta = new cljs.core.Symbol(null,"_meta","_meta",-1716892533,null);
|
||||
cljs.core.cst$kw$aborted = new cljs.core.Keyword(null,"aborted","aborted",1775972619);
|
||||
cljs.core.cst$kw$span$unchecked_DASH_count = new cljs.core.Keyword(null,"span.unchecked-count","span.unchecked-count",-408283861);
|
||||
cljs.core.cst$sym$afn = new cljs.core.Symbol(null,"afn","afn",216963467,null);
|
||||
cljs.core.cst$kw$processing_DASH_request = new cljs.core.Keyword(null,"processing-request","processing-request",-264947221);
|
||||
cljs.core.cst$kw$params = new cljs.core.Keyword(null,"params","params",710516235);
|
||||
cljs.core.cst$kw$p$warn = new cljs.core.Keyword(null,"p.warn","p.warn",-621694453);
|
||||
cljs.core.cst$kw$on_DASH_blur = new cljs.core.Keyword(null,"on-blur","on-blur",814300747);
|
||||
cljs.core.cst$sym$todos = new cljs.core.Symbol(null,"todos","todos",-2024126901,null);
|
||||
cljs.core.cst$sym$tree = new cljs.core.Symbol(null,"tree","tree",1444219499,null);
|
||||
cljs.core.cst$sym$fn = new cljs.core.Symbol(null,"fn","fn",465265323,null);
|
||||
cljs.core.cst$kw$div_SHARP_loader = new cljs.core.Keyword(null,"div#loader","div#loader",418409131);
|
||||
cljs.core.cst$sym$front = new cljs.core.Symbol(null,"front","front",117022539,null);
|
||||
cljs.core.cst$sym$buf = new cljs.core.Symbol(null,"buf","buf",1426618187,null);
|
||||
cljs.core.cst$sym$mults = new cljs.core.Symbol(null,"mults","mults",-461114485,null);
|
||||
cljs.core.cst$kw$component_DASH_did_DASH_update = new cljs.core.Keyword(null,"component-did-update","component-did-update",-1468549173);
|
||||
cljs.core.cst$sym$next_DASH_entry = new cljs.core.Symbol(null,"next-entry","next-entry",1091342476,null);
|
||||
cljs.core.cst$kw$read_DASH_cond = new cljs.core.Keyword(null,"read-cond","read-cond",1056899244);
|
||||
cljs.core.cst$kw$val = new cljs.core.Keyword(null,"val","val",128701612);
|
||||
cljs.core.cst$sym$key = new cljs.core.Symbol(null,"key","key",124488940,null);
|
||||
cljs.core.cst$sym$meta4886 = new cljs.core.Symbol(null,"meta4886","meta4886",-297171700,null);
|
||||
cljs.core.cst$sym$_next = new cljs.core.Symbol(null,"_next","_next",101877036,null);
|
||||
cljs.core.cst$sym$inst = new cljs.core.Symbol(null,"inst","inst",-2008473268,null);
|
||||
cljs.core.cst$sym$fn1 = new cljs.core.Symbol(null,"fn1","fn1",895834444,null);
|
||||
cljs.core.cst$kw$recur = new cljs.core.Keyword(null,"recur","recur",-437573268);
|
||||
cljs.core.cst$kw$li$todo_DASH_link = new cljs.core.Keyword(null,"li.todo-link","li.todo-link",1015736716);
|
||||
cljs.core.cst$kw$type = new cljs.core.Keyword(null,"type","type",1174270348);
|
||||
cljs.core.cst$kw$request_DASH_received = new cljs.core.Keyword(null,"request-received","request-received",2110590540);
|
||||
cljs.core.cst$sym$kf = new cljs.core.Symbol(null,"kf","kf",-1046348180,null);
|
||||
cljs.core.cst$sym$omgnata$core_SLASH_lists_DASH_page = new cljs.core.Symbol("omgnata.core","lists-page","omgnata.core/lists-page",593904300,null);
|
||||
cljs.core.cst$kw$catch_DASH_block = new cljs.core.Keyword(null,"catch-block","catch-block",1175212748);
|
||||
cljs.core.cst$sym$root_DASH_iter = new cljs.core.Symbol(null,"root-iter","root-iter",1974672108,null);
|
||||
cljs.core.cst$kw$delete = new cljs.core.Keyword(null,"delete","delete",-1768633620);
|
||||
cljs.core.cst$kw$div_SHARP_list_DASH_edit_DASH_container = new cljs.core.Keyword(null,"div#list-edit-container","div#list-edit-container",500002636);
|
||||
cljs.core.cst$sym$do = new cljs.core.Symbol(null,"do","do",1686842252,null);
|
||||
cljs.core.cst$sym$vec = new cljs.core.Symbol(null,"vec","vec",982683596,null);
|
||||
cljs.core.cst$sym$p__4883 = new cljs.core.Symbol(null,"p__4883","p__4883",2053661997,null);
|
||||
cljs.core.cst$sym$add_BANG_ = new cljs.core.Symbol(null,"add!","add!",2046056845,null);
|
||||
cljs.core.cst$kw$preserve = new cljs.core.Keyword(null,"preserve","preserve",1276846509);
|
||||
cljs.core.cst$kw$fallback_DASH_impl = new cljs.core.Keyword(null,"fallback-impl","fallback-impl",-1501286995);
|
||||
cljs.core.cst$kw$route = new cljs.core.Keyword(null,"route","route",329891309);
|
||||
cljs.core.cst$kw$keyword_DASH_fn = new cljs.core.Keyword(null,"keyword-fn","keyword-fn",-64566675);
|
||||
cljs.core.cst$sym$Inf = new cljs.core.Symbol(null,"Inf","Inf",647172781,null);
|
||||
cljs.core.cst$kw$source = new cljs.core.Keyword(null,"source","source",-433931539);
|
||||
cljs.core.cst$kw$handlers = new cljs.core.Keyword(null,"handlers","handlers",79528781);
|
||||
cljs.core.cst$kw$flush_DASH_on_DASH_newline = new cljs.core.Keyword(null,"flush-on-newline","flush-on-newline",-151457939);
|
||||
cljs.core.cst$kw$finished = new cljs.core.Keyword(null,"finished","finished",-1018867731);
|
||||
cljs.core.cst$sym$default_DASH_dispatch_DASH_val = new cljs.core.Symbol(null,"default-dispatch-val","default-dispatch-val",-1231201266,null);
|
||||
cljs.core.cst$kw$componentWillUnmount = new cljs.core.Keyword(null,"componentWillUnmount","componentWillUnmount",1573788814);
|
||||
cljs.core.cst$kw$no_DASH_test = new cljs.core.Keyword(null,"no-test","no-test",-1679482642);
|
||||
cljs.core.cst$kw$string = new cljs.core.Keyword(null,"string","string",-1989541586);
|
||||
cljs.core.cst$sym$queue = new cljs.core.Symbol(null,"queue","queue",-1198599890,null);
|
||||
cljs.core.cst$sym$_ = new cljs.core.Symbol(null,"_","_",-1201019570,null);
|
||||
cljs.core.cst$kw$vector = new cljs.core.Keyword(null,"vector","vector",1902966158);
|
||||
cljs.core.cst$sym$validator = new cljs.core.Symbol(null,"validator","validator",-325659154,null);
|
||||
cljs.core.cst$kw$illegal_DASH_argument = new cljs.core.Keyword(null,"illegal-argument","illegal-argument",-1845493170);
|
||||
cljs.core.cst$sym$letfn_STAR_ = new cljs.core.Symbol(null,"letfn*","letfn*",-110097810,null);
|
||||
cljs.core.cst$kw$cljs$analyzer_SLASH_analyzed = new cljs.core.Keyword("cljs.analyzer","analyzed","cljs.analyzer/analyzed",-735094162);
|
||||
cljs.core.cst$sym$meta8924 = new cljs.core.Symbol(null,"meta8924","meta8924",1531656878,null);
|
||||
cljs.core.cst$sym$if = new cljs.core.Symbol(null,"if","if",1181717262,null);
|
||||
cljs.core.cst$sym$readable = new cljs.core.Symbol(null,"readable","readable",2113054478,null);
|
||||
cljs.core.cst$kw$parse_DASH_error = new cljs.core.Keyword(null,"parse-error","parse-error",255902478);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_with_DASH_meta = new cljs.core.Symbol("cljs.core","with-meta","cljs.core/with-meta",749126446,null);
|
||||
cljs.core.cst$sym$finally_DASH_block = new cljs.core.Symbol(null,"finally-block","finally-block",-1821453297,null);
|
||||
cljs.core.cst$sym$arr = new cljs.core.Symbol(null,"arr","arr",2115492975,null);
|
||||
cljs.core.cst$sym$new = new cljs.core.Symbol(null,"new","new",-444906321,null);
|
||||
cljs.core.cst$kw$on_DASH_click = new cljs.core.Keyword(null,"on-click","on-click",1632826543);
|
||||
cljs.core.cst$kw$strable = new cljs.core.Keyword(null,"strable","strable",1877668047);
|
||||
cljs.core.cst$kw$descendants = new cljs.core.Keyword(null,"descendants","descendants",1824886031);
|
||||
cljs.core.cst$kw$allow = new cljs.core.Keyword(null,"allow","allow",-1857325745);
|
||||
cljs.core.cst$sym$ns = new cljs.core.Symbol(null,"ns","ns",2082130287,null);
|
||||
cljs.core.cst$kw$title = new cljs.core.Keyword(null,"title","title",636505583);
|
||||
cljs.core.cst$kw$sym = new cljs.core.Keyword(null,"sym","sym",-1444860305);
|
||||
cljs.core.cst$kw$prefix = new cljs.core.Keyword(null,"prefix","prefix",-265908465);
|
||||
cljs.core.cst$kw$column = new cljs.core.Keyword(null,"column","column",2078222095);
|
||||
cljs.core.cst$sym$pick = new cljs.core.Symbol(null,"pick","pick",1300068175,null);
|
||||
cljs.core.cst$kw$headers = new cljs.core.Keyword(null,"headers","headers",-835030129);
|
||||
cljs.core.cst$kw$i$checkbox$btn = new cljs.core.Keyword(null,"i.checkbox.btn","i.checkbox.btn",15892367);
|
||||
cljs.core.cst$sym$completed = new cljs.core.Symbol(null,"completed","completed",1154475024,null);
|
||||
cljs.core.cst$sym$forward = new cljs.core.Symbol(null,"forward","forward",1083186224,null);
|
||||
cljs.core.cst$kw$div$message = new cljs.core.Keyword(null,"div.message","div.message",197515312);
|
||||
cljs.core.cst$kw$shouldComponentUpdate = new cljs.core.Keyword(null,"shouldComponentUpdate","shouldComponentUpdate",1795750960);
|
||||
cljs.core.cst$kw$error_DASH_handler = new cljs.core.Keyword(null,"error-handler","error-handler",-484945776);
|
||||
cljs.core.cst$kw$ancestors = new cljs.core.Keyword(null,"ancestors","ancestors",-776045424);
|
||||
cljs.core.cst$sym$flag = new cljs.core.Symbol(null,"flag","flag",-1565787888,null);
|
||||
cljs.core.cst$kw$style = new cljs.core.Keyword(null,"style","style",-496642736);
|
||||
cljs.core.cst$sym$ensure_DASH_mult = new cljs.core.Symbol(null,"ensure-mult","ensure-mult",1796584816,null);
|
||||
cljs.core.cst$sym$value = new cljs.core.Symbol(null,"value","value",1946509744,null);
|
||||
cljs.core.cst$kw$write = new cljs.core.Keyword(null,"write","write",-1857649168);
|
||||
cljs.core.cst$sym$name = new cljs.core.Symbol(null,"name","name",-810760592,null);
|
||||
cljs.core.cst$sym$meta9735 = new cljs.core.Symbol(null,"meta9735","meta9735",-1978445200,null);
|
||||
cljs.core.cst$sym$map__4884 = new cljs.core.Symbol(null,"map__4884","map__4884",-1688549712,null);
|
||||
cljs.core.cst$sym$n = new cljs.core.Symbol(null,"n","n",-2092305744,null);
|
||||
cljs.core.cst$kw$div = new cljs.core.Keyword(null,"div","div",1057191632);
|
||||
cljs.core.cst$sym$frames = new cljs.core.Symbol(null,"frames","frames",-888748272,null);
|
||||
cljs.core.cst$kw$readably = new cljs.core.Keyword(null,"readably","readably",1129599760);
|
||||
cljs.core.cst$kw$more_DASH_marker = new cljs.core.Keyword(null,"more-marker","more-marker",-14717935);
|
||||
cljs.core.cst$kw$span$btn$handle$fa_DASH_stack = new cljs.core.Keyword(null,"span.btn.handle.fa-stack","span.btn.handle.fa-stack",-1487675343);
|
||||
cljs.core.cst$sym$fields = new cljs.core.Symbol(null,"fields","fields",-291534703,null);
|
||||
cljs.core.cst$sym$re = new cljs.core.Symbol(null,"re","re",1869207729,null);
|
||||
cljs.core.cst$sym$scheduled_QMARK_ = new cljs.core.Symbol(null,"scheduled?","scheduled?",579986609,null);
|
||||
cljs.core.cst$kw$i$btn$delete_DASH_item = new cljs.core.Keyword(null,"i.btn.delete-item","i.btn.delete-item",982327537);
|
||||
cljs.core.cst$sym$method_DASH_cache = new cljs.core.Symbol(null,"method-cache","method-cache",1230193905,null);
|
||||
cljs.core.cst$sym$cs = new cljs.core.Symbol(null,"cs","cs",-117024463,null);
|
||||
cljs.core.cst$kw$div_SHARP_add_DASH_item_DASH_container = new cljs.core.Keyword(null,"div#add-item-container","div#add-item-container",1139529041);
|
||||
cljs.core.cst$sym$dirty_QMARK_ = new cljs.core.Symbol(null,"dirty?","dirty?",-419314319,null);
|
||||
cljs.core.cst$sym$orig_DASH_route = new cljs.core.Symbol(null,"orig-route","orig-route",899103121,null);
|
||||
cljs.core.cst$kw$reagentRender = new cljs.core.Keyword(null,"reagentRender","reagentRender",-358306383);
|
||||
cljs.core.cst$kw$filename = new cljs.core.Keyword(null,"filename","filename",-1428840783);
|
||||
cljs.core.cst$sym$meta10275 = new cljs.core.Symbol(null,"meta10275","meta10275",1969594161,null);
|
||||
cljs.core.cst$sym$edit = new cljs.core.Symbol(null,"edit","edit",-1302639,null);
|
||||
cljs.core.cst$sym$meta3381 = new cljs.core.Symbol(null,"meta3381","meta3381",999308338,null);
|
||||
cljs.core.cst$sym$params = new cljs.core.Symbol(null,"params","params",-1943919534,null);
|
||||
cljs.core.cst$sym$editable_QMARK_ = new cljs.core.Symbol(null,"editable?","editable?",-164945806,null);
|
||||
cljs.core.cst$sym$base_DASH_count = new cljs.core.Symbol(null,"base-count","base-count",-1180647182,null);
|
||||
cljs.core.cst$sym$verbose_DASH_handler_DASH_fn = new cljs.core.Symbol(null,"verbose-handler-fn","verbose-handler-fn",547340594,null);
|
||||
cljs.core.cst$kw$render = new cljs.core.Keyword(null,"render","render",-1408033454);
|
||||
cljs.core.cst$kw$illegal_DASH_state = new cljs.core.Keyword(null,"illegal-state","illegal-state",-1519851182);
|
||||
cljs.core.cst$sym$clojure$core_SLASH_unquote_DASH_splicing = new cljs.core.Symbol("clojure.core","unquote-splicing","clojure.core/unquote-splicing",-552003150,null);
|
||||
cljs.core.cst$sym$collision_DASH_hash = new cljs.core.Symbol(null,"collision-hash","collision-hash",-35831342,null);
|
||||
cljs.core.cst$sym$deftype_STAR_ = new cljs.core.Symbol(null,"deftype*","deftype*",962659890,null);
|
||||
cljs.core.cst$sym$let_STAR_ = new cljs.core.Symbol(null,"let*","let*",1920721458,null);
|
||||
cljs.core.cst$sym$meta8945 = new cljs.core.Symbol(null,"meta8945","meta8945",1831858866,null);
|
||||
cljs.core.cst$sym$start = new cljs.core.Symbol(null,"start","start",1285322546,null);
|
||||
cljs.core.cst$kw$splicing_QMARK_ = new cljs.core.Keyword(null,"splicing?","splicing?",-428596366);
|
||||
cljs.core.cst$sym$sourceIter = new cljs.core.Symbol(null,"sourceIter","sourceIter",1068220306,null);
|
||||
cljs.core.cst$sym$coll = new cljs.core.Symbol(null,"coll","coll",-1006698606,null);
|
||||
cljs.core.cst$sym$not_DASH_native = new cljs.core.Symbol(null,"not-native","not-native",-236392494,null);
|
||||
cljs.core.cst$sym$js_STAR_ = new cljs.core.Symbol(null,"js*","js*",-1134233646,null);
|
||||
cljs.core.cst$kw$details = new cljs.core.Keyword(null,"details","details",1956795411);
|
||||
cljs.core.cst$kw$reagent_DASH_render = new cljs.core.Keyword(null,"reagent-render","reagent-render",-985383853);
|
||||
cljs.core.cst$sym$strobj = new cljs.core.Symbol(null,"strobj","strobj",1088091283,null);
|
||||
cljs.core.cst$sym$todo_DASH_page = new cljs.core.Symbol(null,"todo-page","todo-page",1011891,null);
|
||||
cljs.core.cst$sym$catch_DASH_block = new cljs.core.Symbol(null,"catch-block","catch-block",-1479223021,null);
|
||||
cljs.core.cst$sym$omgnata$core = new cljs.core.Symbol(null,"omgnata.core","omgnata.core",-1309113965,null);
|
||||
cljs.core.cst$kw$line = new cljs.core.Keyword(null,"line","line",212345235);
|
||||
cljs.core.cst$kw$priority = new cljs.core.Keyword(null,"priority","priority",1431093715);
|
||||
cljs.core.cst$kw$solos = new cljs.core.Keyword(null,"solos","solos",1441458643);
|
||||
cljs.core.cst$sym$_rest = new cljs.core.Symbol(null,"_rest","_rest",-2100466189,null);
|
||||
cljs.core.cst$sym$meta1395 = new cljs.core.Symbol(null,"meta1395","meta1395",-1131043213,null);
|
||||
cljs.core.cst$kw$list = new cljs.core.Keyword(null,"list","list",765357683);
|
||||
cljs.core.cst$sym$fn_STAR_ = new cljs.core.Symbol(null,"fn*","fn*",-752876845,null);
|
||||
cljs.core.cst$sym$val = new cljs.core.Symbol(null,"val","val",1769233139,null);
|
||||
cljs.core.cst$kw$keyword = new cljs.core.Keyword(null,"keyword","keyword",811389747);
|
||||
cljs.core.cst$sym$ascending_QMARK_ = new cljs.core.Symbol(null,"ascending?","ascending?",-1938452653,null);
|
||||
cljs.core.cst$sym$recur = new cljs.core.Symbol(null,"recur","recur",1202958259,null);
|
||||
cljs.core.cst$sym$xf = new cljs.core.Symbol(null,"xf","xf",2042434515,null);
|
||||
cljs.core.cst$sym$ci = new cljs.core.Symbol(null,"ci","ci",2049808339,null);
|
||||
cljs.core.cst$kw$status = new cljs.core.Keyword(null,"status","status",-1997798413);
|
||||
cljs.core.cst$kw$span_SHARP_add_DASH_list$btn = new cljs.core.Keyword(null,"span#add-list.btn","span#add-list.btn",-1477394412);
|
||||
cljs.core.cst$kw$response_DASH_ready = new cljs.core.Keyword(null,"response-ready","response-ready",245208276);
|
||||
cljs.core.cst$kw$print_DASH_length = new cljs.core.Keyword(null,"print-length","print-length",1931866356);
|
||||
cljs.core.cst$kw$writer = new cljs.core.Keyword(null,"writer","writer",-277568236);
|
||||
cljs.core.cst$kw$col = new cljs.core.Keyword(null,"col","col",-1959363084);
|
||||
cljs.core.cst$kw$on_DASH_double_DASH_click = new cljs.core.Keyword(null,"on-double-click","on-double-click",1434856980);
|
||||
cljs.core.cst$kw$id = new cljs.core.Keyword(null,"id","id",-1388402092);
|
||||
cljs.core.cst$sym$ratom = new cljs.core.Symbol(null,"ratom","ratom",1514010260,null);
|
||||
cljs.core.cst$kw$i$btn$update_DASH_item_DASH_done = new cljs.core.Keyword(null,"i.btn.update-item-done","i.btn.update-item-done",-366159180);
|
||||
cljs.core.cst$kw$class = new cljs.core.Keyword(null,"class","class",-2030961996);
|
||||
cljs.core.cst$sym$state = new cljs.core.Symbol(null,"state","state",-348086572,null);
|
||||
cljs.core.cst$kw$ok = new cljs.core.Keyword(null,"ok","ok",967785236);
|
||||
cljs.core.cst$sym$vals = new cljs.core.Symbol(null,"vals","vals",-1886377036,null);
|
||||
cljs.core.cst$sym$all = new cljs.core.Symbol(null,"all","all",-1762306027,null);
|
||||
cljs.core.cst$sym$clojure$core_SLASH_deref = new cljs.core.Symbol("clojure.core","deref","clojure.core/deref",188719157,null);
|
||||
cljs.core.cst$kw$catch_DASH_exception = new cljs.core.Keyword(null,"catch-exception","catch-exception",-1997306795);
|
||||
cljs.core.cst$kw$cljs$core_SLASH_halt = new cljs.core.Keyword("cljs.core","halt","cljs.core/halt",-1049036715);
|
||||
cljs.core.cst$kw$nil = new cljs.core.Keyword(null,"nil","nil",99600501);
|
||||
cljs.core.cst$sym$timestamps = new cljs.core.Symbol(null,"timestamps","timestamps",819472597,null);
|
||||
cljs.core.cst$sym$cached_DASH_hierarchy = new cljs.core.Symbol(null,"cached-hierarchy","cached-hierarchy",-1085460203,null);
|
||||
cljs.core.cst$sym$header = new cljs.core.Symbol(null,"header","header",1759972661,null);
|
||||
cljs.core.cst$kw$auto_DASH_run = new cljs.core.Keyword(null,"auto-run","auto-run",1958400437);
|
||||
cljs.core.cst$kw$reader = new cljs.core.Keyword(null,"reader","reader",169660853);
|
||||
cljs.core.cst$kw$checked = new cljs.core.Keyword(null,"checked","checked",-50955819);
|
||||
cljs.core.cst$sym$s = new cljs.core.Symbol(null,"s","s",-948495851,null);
|
||||
cljs.core.cst$kw$cljsName = new cljs.core.Keyword(null,"cljsName","cljsName",999824949);
|
||||
cljs.core.cst$kw$parents = new cljs.core.Keyword(null,"parents","parents",-2027538891);
|
||||
cljs.core.cst$sym$cnt = new cljs.core.Symbol(null,"cnt","cnt",1924510325,null);
|
||||
cljs.core.cst$kw$parse = new cljs.core.Keyword(null,"parse","parse",-1162164619);
|
||||
cljs.core.cst$sym$_SLASH_ = new cljs.core.Symbol(null,"/","/",-1371932971,null);
|
||||
cljs.core.cst$kw$initk = new cljs.core.Keyword(null,"initk","initk",-1693342987);
|
||||
cljs.core.cst$sym$meta10820 = new cljs.core.Symbol(null,"meta10820","meta10820",179373909,null);
|
||||
cljs.core.cst$sym$node = new cljs.core.Symbol(null,"node","node",-2073234571,null);
|
||||
cljs.core.cst$kw$component_DASH_will_DASH_unmount = new cljs.core.Keyword(null,"component-will-unmount","component-will-unmount",-2058314698);
|
||||
cljs.core.cst$kw$prev = new cljs.core.Keyword(null,"prev","prev",-1597069226);
|
||||
cljs.core.cst$sym$sym = new cljs.core.Symbol(null,"sym","sym",195671222,null);
|
||||
cljs.core.cst$sym$column = new cljs.core.Symbol(null,"column","column",-576213674,null);
|
||||
cljs.core.cst$kw$url = new cljs.core.Keyword(null,"url","url",276297046);
|
||||
cljs.core.cst$sym$sb = new cljs.core.Symbol(null,"sb","sb",-1249746442,null);
|
||||
cljs.core.cst$kw$continue_DASH_block = new cljs.core.Keyword(null,"continue-block","continue-block",-1852047850);
|
||||
cljs.core.cst$sym$clojure$core_SLASH_unquote = new cljs.core.Symbol("clojure.core","unquote","clojure.core/unquote",843087510,null);
|
||||
cljs.core.cst$kw$query_DASH_params = new cljs.core.Keyword(null,"query-params","query-params",900640534);
|
||||
cljs.core.cst$sym$seed = new cljs.core.Symbol(null,"seed","seed",1709144854,null);
|
||||
cljs.core.cst$kw$content_DASH_type = new cljs.core.Keyword(null,"content-type","content-type",-508222634);
|
||||
cljs.core.cst$sym$ch = new cljs.core.Symbol(null,"ch","ch",1085813622,null);
|
||||
cljs.core.cst$sym$level = new cljs.core.Symbol(null,"level","level",-1363938217,null);
|
||||
cljs.core.cst$kw$end_DASH_line = new cljs.core.Keyword(null,"end-line","end-line",1837326455);
|
||||
cljs.core.cst$kw$auto_DASH_focus = new cljs.core.Keyword(null,"auto-focus","auto-focus",1250006231);
|
||||
cljs.core.cst$sym$prev_DASH_seed = new cljs.core.Symbol(null,"prev-seed","prev-seed",2126381367,null);
|
||||
cljs.core.cst$kw$_DASH_elem_DASH_count = new cljs.core.Keyword(null,"-elem-count","-elem-count",663797079);
|
||||
cljs.core.cst$sym$buf_DASH_pos = new cljs.core.Symbol(null,"buf-pos","buf-pos",-807229033,null);
|
||||
cljs.core.cst$kw$max_DASH_retries = new cljs.core.Keyword(null,"max-retries","max-retries",-1933762121);
|
||||
cljs.core.cst$kw$display_DASH_name = new cljs.core.Keyword(null,"display-name","display-name",694513143);
|
||||
cljs.core.cst$kw$h3$list_DASH_title = new cljs.core.Keyword(null,"h3.list-title","h3.list-title",345558615);
|
||||
cljs.core.cst$sym$omgnata$core_SLASH_todo_DASH_page = new cljs.core.Symbol("omgnata.core","todo-page","omgnata.core/todo-page",-1085648265,null);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_vec = new cljs.core.Symbol("cljs.core","vec","cljs.core/vec",307622519,null);
|
||||
cljs.core.cst$kw$post = new cljs.core.Keyword(null,"post","post",269697687);
|
||||
cljs.core.cst$sym$_DASH_Inf = new cljs.core.Symbol(null,"-Inf","-Inf",-2123243689,null);
|
||||
cljs.core.cst$kw$div$todo_DASH_text = new cljs.core.Keyword(null,"div.todo-text","div.todo-text",-1124244424);
|
||||
cljs.core.cst$sym$str_DASH_rep_DASH_fn = new cljs.core.Symbol(null,"str-rep-fn","str-rep-fn",-1179615016,null);
|
||||
cljs.core.cst$sym$_hash = new cljs.core.Symbol(null,"_hash","_hash",-2130838312,null);
|
||||
cljs.core.cst$sym$filename = new cljs.core.Symbol(null,"filename","filename",211690744,null);
|
||||
cljs.core.cst$kw$on_DASH_dispose = new cljs.core.Keyword(null,"on-dispose","on-dispose",2105306360);
|
||||
cljs.core.cst$kw$action = new cljs.core.Keyword(null,"action","action",-811238024);
|
||||
cljs.core.cst$sym$calc_DASH_state = new cljs.core.Symbol(null,"calc-state","calc-state",-349968968,null);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_sequence = new cljs.core.Symbol("cljs.core","sequence","cljs.core/sequence",1908459032,null);
|
||||
cljs.core.cst$kw$pause = new cljs.core.Keyword(null,"pause","pause",-2095325672);
|
||||
cljs.core.cst$kw$error = new cljs.core.Keyword(null,"error","error",-978969032);
|
||||
cljs.core.cst$kw$regex = new cljs.core.Keyword(null,"regex","regex",939488856);
|
||||
cljs.core.cst$kw$componentFunction = new cljs.core.Keyword(null,"componentFunction","componentFunction",825866104);
|
||||
cljs.core.cst$sym$topic_DASH_fn = new cljs.core.Symbol(null,"topic-fn","topic-fn",-862449736,null);
|
||||
cljs.core.cst$kw$i_SHARP_clear_DASH_completed$btn = new cljs.core.Keyword(null,"i#clear-completed.btn","i#clear-completed.btn",2100368344);
|
||||
cljs.core.cst$sym$head = new cljs.core.Symbol(null,"head","head",869147608,null);
|
||||
cljs.core.cst$kw$exception = new cljs.core.Keyword(null,"exception","exception",-335277064);
|
||||
cljs.core.cst$sym$keys = new cljs.core.Symbol(null,"keys","keys",-1586012071,null);
|
||||
cljs.core.cst$sym$meta5714 = new cljs.core.Symbol(null,"meta5714","meta5714",269087833,null);
|
||||
cljs.core.cst$sym$vec__10816 = new cljs.core.Symbol(null,"vec__10816","vec__10816",-1184809767,null);
|
||||
cljs.core.cst$sym$set_BANG_ = new cljs.core.Symbol(null,"set!","set!",250714521,null);
|
||||
cljs.core.cst$kw$unsupported_DASH_operation = new cljs.core.Keyword(null,"unsupported-operation","unsupported-operation",1890540953);
|
||||
cljs.core.cst$sym$splicing_QMARK_ = new cljs.core.Symbol(null,"splicing?","splicing?",1211935161,null);
|
||||
cljs.core.cst$kw$uri = new cljs.core.Keyword(null,"uri","uri",-774711847);
|
||||
cljs.core.cst$kw$form = new cljs.core.Keyword(null,"form","form",-1624062471);
|
||||
cljs.core.cst$kw$tag = new cljs.core.Keyword(null,"tag","tag",-1290361223);
|
||||
cljs.core.cst$sym$tree_DASH_map = new cljs.core.Symbol(null,"tree-map","tree-map",1373073049,null);
|
||||
cljs.core.cst$sym$meta9433 = new cljs.core.Symbol(null,"meta9433","meta9433",-1569560807,null);
|
||||
cljs.core.cst$kw$input = new cljs.core.Keyword(null,"input","input",556931961);
|
||||
cljs.core.cst$kw$secretary$core_SLASH_sequential = new cljs.core.Keyword("secretary.core","sequential","secretary.core/sequential",-347187207);
|
||||
cljs.core.cst$sym$_DOT_ = new cljs.core.Symbol(null,".",".",1975675962,null);
|
||||
cljs.core.cst$sym$var = new cljs.core.Symbol(null,"var","var",870848730,null);
|
||||
cljs.core.cst$kw$mutable = new cljs.core.Keyword(null,"mutable","mutable",875778266);
|
||||
cljs.core.cst$kw$json = new cljs.core.Keyword(null,"json","json",1279968570);
|
||||
cljs.core.cst$sym$tag_DASH_fn = new cljs.core.Symbol(null,"tag-fn","tag-fn",242055482,null);
|
||||
cljs.core.cst$sym$quote = new cljs.core.Symbol(null,"quote","quote",1377916282,null);
|
||||
cljs.core.cst$kw$set = new cljs.core.Keyword(null,"set","set",304602554);
|
||||
cljs.core.cst$kw$timeout = new cljs.core.Keyword(null,"timeout","timeout",-318625318);
|
||||
cljs.core.cst$sym$line_DASH_start_QMARK_ = new cljs.core.Symbol(null,"line-start?","line-start?",1357012474,null);
|
||||
cljs.core.cst$sym$root = new cljs.core.Symbol(null,"root","root",1191874074,null);
|
||||
cljs.core.cst$sym$dirty_DASH_takes = new cljs.core.Symbol(null,"dirty-takes","dirty-takes",575642138,null);
|
||||
cljs.core.cst$sym$multi = new cljs.core.Symbol(null,"multi","multi",1450238522,null);
|
||||
cljs.core.cst$sym$str = new cljs.core.Symbol(null,"str","str",-1564826950,null);
|
||||
cljs.core.cst$sym$next = new cljs.core.Symbol(null,"next","next",1522830042,null);
|
||||
cljs.core.cst$kw$i$delete_DASH_list$btn = new cljs.core.Keyword(null,"i.delete-list.btn","i.delete-list.btn",-1371286758);
|
||||
cljs.core.cst$sym$nodes = new cljs.core.Symbol(null,"nodes","nodes",-459054278,null);
|
||||
cljs.core.cst$sym$seen = new cljs.core.Symbol(null,"seen","seen",1121531738,null);
|
||||
cljs.core.cst$sym$hash_DASH_map = new cljs.core.Symbol(null,"hash-map","hash-map",-439030950,null);
|
||||
cljs.core.cst$kw$arglists = new cljs.core.Keyword(null,"arglists","arglists",1661989754);
|
||||
cljs.core.cst$sym$line = new cljs.core.Symbol(null,"line","line",1852876762,null);
|
||||
cljs.core.cst$sym$out = new cljs.core.Symbol(null,"out","out",729986010,null);
|
||||
cljs.core.cst$kw$vf = new cljs.core.Keyword(null,"vf","vf",-321423269);
|
||||
cljs.core.cst$kw$on_DASH_change = new cljs.core.Keyword(null,"on-change","on-change",-732046149);
|
||||
cljs.core.cst$sym$p__2237 = new cljs.core.Symbol(null,"p__2237","p__2237",1307436219,null);
|
||||
cljs.core.cst$kw$eof = new cljs.core.Keyword(null,"eof","eof",-489063237);
|
||||
cljs.core.cst$kw$hierarchy = new cljs.core.Keyword(null,"hierarchy","hierarchy",-1053470341);
|
||||
cljs.core.cst$sym$catch = new cljs.core.Symbol(null,"catch","catch",-1616370245,null);
|
||||
cljs.core.cst$kw$timestamp = new cljs.core.Keyword(null,"timestamp","timestamp",579478971);
|
||||
cljs.core.cst$kw$on_DASH_key_DASH_down = new cljs.core.Keyword(null,"on-key-down","on-key-down",-1374733765);
|
||||
cljs.core.cst$kw$connection_DASH_established = new cljs.core.Keyword(null,"connection-established","connection-established",-1403749733);
|
||||
cljs.core.cst$sym$s_DASH_len = new cljs.core.Symbol(null,"s-len","s-len",1869978331,null);
|
||||
cljs.core.cst$kw$alt_DASH_impl = new cljs.core.Keyword(null,"alt-impl","alt-impl",670969595);
|
||||
cljs.core.cst$sym$ext_DASH_map_DASH_iter = new cljs.core.Symbol(null,"ext-map-iter","ext-map-iter",-1215982757,null);
|
||||
cljs.core.cst$sym$tail = new cljs.core.Symbol(null,"tail","tail",494507963,null);
|
||||
cljs.core.cst$kw$doc = new cljs.core.Keyword(null,"doc","doc",1913296891);
|
||||
cljs.core.cst$sym$file_DASH_name = new cljs.core.Symbol(null,"file-name","file-name",-13685732,null);
|
||||
cljs.core.cst$sym$record = new cljs.core.Symbol(null,"record","record",861424668,null);
|
||||
cljs.core.cst$sym$changed = new cljs.core.Symbol(null,"changed","changed",-2083710852,null);
|
||||
cljs.core.cst$sym$mseq = new cljs.core.Symbol(null,"mseq","mseq",1602647196,null);
|
||||
cljs.core.cst$sym$count = new cljs.core.Symbol(null,"count","count",-514511684,null);
|
||||
cljs.core.cst$sym$dirty_DASH_puts = new cljs.core.Symbol(null,"dirty-puts","dirty-puts",57041148,null);
|
||||
cljs.core.cst$sym$initk = new cljs.core.Symbol(null,"initk","initk",-52811460,null);
|
||||
cljs.core.cst$sym$solo_DASH_modes = new cljs.core.Symbol(null,"solo-modes","solo-modes",882180540,null);
|
||||
cljs.core.cst$sym$catch_DASH_exception = new cljs.core.Symbol(null,"catch-exception","catch-exception",-356775268,null);
|
||||
cljs.core.cst$kw$handler = new cljs.core.Keyword(null,"handler","handler",-195596612);
|
||||
cljs.core.cst$kw$keywordize_DASH_keys = new cljs.core.Keyword(null,"keywordize-keys","keywordize-keys",1310784252);
|
||||
cljs.core.cst$sym$takes = new cljs.core.Symbol(null,"takes","takes",298247964,null);
|
||||
cljs.core.cst$sym$current = new cljs.core.Symbol(null,"current","current",552492924,null);
|
||||
cljs.core.cst$sym$off = new cljs.core.Symbol(null,"off","off",-2047994980,null);
|
||||
cljs.core.cst$kw$current_DASH_page = new cljs.core.Keyword(null,"current-page","current-page",-101294180);
|
||||
cljs.core.cst$kw$textarea$add_DASH_item_DASH_text = new cljs.core.Keyword(null,"textarea.add-item-text","textarea.add-item-text",1628747740);
|
||||
cljs.core.cst$sym$auto_DASH_run = new cljs.core.Symbol(null,"auto-run","auto-run",-696035332,null);
|
||||
cljs.core.cst$sym$length = new cljs.core.Symbol(null,"length","length",-2065447907,null);
|
||||
cljs.core.cst$sym$continue_DASH_block = new cljs.core.Symbol(null,"continue-block","continue-block",-211516323,null);
|
||||
cljs.core.cst$sym$stack = new cljs.core.Symbol(null,"stack","stack",847125597,null);
|
||||
cljs.core.cst$kw$p = new cljs.core.Keyword(null,"p","p",151049309);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_hash_DASH_set = new cljs.core.Symbol("cljs.core","hash-set","cljs.core/hash-set",1130426749,null);
|
||||
cljs.core.cst$sym$transient_DASH_map = new cljs.core.Symbol(null,"transient-map","transient-map",351764893,null);
|
||||
cljs.core.cst$kw$character = new cljs.core.Keyword(null,"character","character",380652989);
|
||||
cljs.core.cst$kw$map = new cljs.core.Keyword(null,"map","map",1371690461);
|
||||
cljs.core.cst$sym$cljs$core_SLASH_list = new cljs.core.Symbol("cljs.core","list","cljs.core/list",-1331406371,null);
|
||||
cljs.core.cst$kw$eofthrow = new cljs.core.Keyword(null,"eofthrow","eofthrow",-334166531);
|
||||
cljs.core.cst$sym$map__2238 = new cljs.core.Symbol(null,"map__2238","map__2238",-1136596483,null);
|
||||
cljs.core.cst$kw$with_DASH_credentials = new cljs.core.Keyword(null,"with-credentials","with-credentials",-1163127235);
|
||||
cljs.core.cst$sym$prev = new cljs.core.Symbol(null,"prev","prev",43462301,null);
|
||||
cljs.core.cst$sym$len = new cljs.core.Symbol(null,"len","len",-1230778691,null);
|
||||
cljs.core.cst$sym$meta8785 = new cljs.core.Symbol(null,"meta8785","meta8785",1337781949,null);
|
||||
cljs.core.cst$kw$componentWillMount = new cljs.core.Keyword(null,"componentWillMount","componentWillMount",-285327619);
|
||||
cljs.core.cst$kw$i = new cljs.core.Keyword(null,"i","i",-1386841315);
|
||||
cljs.core.cst$kw$test = new cljs.core.Keyword(null,"test","test",577538877);
|
||||
cljs.core.cst$kw$span$edit_DASH_mode = new cljs.core.Keyword(null,"span.edit-mode","span.edit-mode",-1495820483);
|
||||
cljs.core.cst$sym$right = new cljs.core.Symbol(null,"right","right",1187949694,null);
|
||||
cljs.core.cst$sym$buf_DASH_len = new cljs.core.Symbol(null,"buf-len","buf-len",404510846,null);
|
||||
cljs.core.cst$kw$runtime_DASH_exception = new cljs.core.Keyword(null,"runtime-exception","runtime-exception",-1495664514);
|
||||
cljs.core.cst$sym$meta5887 = new cljs.core.Symbol(null,"meta5887","meta5887",314048670,null);
|
||||
cljs.core.cst$sym$throw = new cljs.core.Symbol(null,"throw","throw",595905694,null);
|
||||
cljs.core.cst$kw$none = new cljs.core.Keyword(null,"none","none",1333468478);
|
||||
cljs.core.cst$kw$buffer = new cljs.core.Keyword(null,"buffer","buffer",617295198);
|
||||
cljs.core.cst$kw$poller_DASH_time = new cljs.core.Keyword(null,"poller-time","poller-time",364073438);
|
||||
cljs.core.cst$sym$fseq = new cljs.core.Symbol(null,"fseq","fseq",-1466412450,null);
|
||||
cljs.core.cst$sym$meta9892 = new cljs.core.Symbol(null,"meta9892","meta9892",483024702,null);
|
||||
cljs.core.cst$kw$mute = new cljs.core.Keyword(null,"mute","mute",1151223646);
|
||||
cljs.core.cst$sym$chunk_DASH_next = new cljs.core.Symbol(null,"chunk-next","chunk-next",-547810434,null);
|
||||
cljs.core.cst$sym$attrs = new cljs.core.Symbol(null,"attrs","attrs",-450137186,null);
|
||||
cljs.core.cst$kw$cljs$core_SLASH_not_DASH_found = new cljs.core.Keyword("cljs.core","not-found","cljs.core/not-found",-1572889185);
|
||||
cljs.core.cst$sym$more = new cljs.core.Symbol(null,"more","more",-418290273,null);
|
||||
cljs.core.cst$sym$def = new cljs.core.Symbol(null,"def","def",597100991,null);
|
||||
cljs.core.cst$kw$span = new cljs.core.Keyword(null,"span","span",1394872991);
|
||||
cljs.core.cst$kw$reads = new cljs.core.Keyword(null,"reads","reads",-1215067361);
|
||||
cljs.core.cst$sym$on_DASH_dispose = new cljs.core.Symbol(null,"on-dispose","on-dispose",-549129409,null);
|
||||
cljs.core.cst$sym$f = new cljs.core.Symbol(null,"f","f",43394975,null);
|
||||
cljs.core.cst$sym$next_DASH_iter = new cljs.core.Symbol(null,"next-iter","next-iter",1526626239,null);
|
||||
Executable
+214
@@ -0,0 +1,214 @@
|
||||
; Copyright (c) Rich Hickey. All rights reserved.
|
||||
; The use and distribution terms for this software are covered by the
|
||||
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
; By using this software in any fashion, you are agreeing to be bound by
|
||||
; the terms of this license.
|
||||
; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.reader
|
||||
(:require-macros [cljs.reader :refer [add-data-readers]])
|
||||
(:require [goog.object :as gobject]
|
||||
[cljs.tools.reader :as treader]
|
||||
[cljs.tools.reader.edn :as edn])
|
||||
(:import [goog.string StringBuffer]))
|
||||
|
||||
(defn ^:private zero-fill-right-and-truncate [s width]
|
||||
(cond
|
||||
(= width (count s)) s
|
||||
(< width (count s)) (subs s 0 width)
|
||||
:else
|
||||
(loop [b (StringBuffer. s)]
|
||||
(if (< (.getLength b) width)
|
||||
(recur (.append b "0"))
|
||||
(.toString b)))))
|
||||
|
||||
(defn ^:private divisible?
|
||||
[num div]
|
||||
(zero? (mod num div)))
|
||||
|
||||
(defn ^:private indivisible?
|
||||
[num div]
|
||||
(not (divisible? num div)))
|
||||
|
||||
(defn ^:private leap-year?
|
||||
[year]
|
||||
(and (divisible? year 4)
|
||||
(or (indivisible? year 100)
|
||||
(divisible? year 400))))
|
||||
|
||||
(def ^:private days-in-month
|
||||
(let [dim-norm [nil 31 28 31 30 31 30 31 31 30 31 30 31]
|
||||
dim-leap [nil 31 29 31 30 31 30 31 31 30 31 30 31]]
|
||||
(fn [month leap-year?]
|
||||
(get (if leap-year? dim-leap dim-norm) month))))
|
||||
|
||||
(def ^:private timestamp-regex #"(\d\d\d\d)(?:-(\d\d)(?:-(\d\d)(?:[T](\d\d)(?::(\d\d)(?::(\d\d)(?:[.](\d+))?)?)?)?)?)?(?:[Z]|([-+])(\d\d):(\d\d))?")
|
||||
|
||||
(defn ^:private parse-int [s]
|
||||
(let [n (js/parseInt s 10)]
|
||||
(if-not (js/isNaN n)
|
||||
n)))
|
||||
|
||||
(defn ^:private check [low n high msg]
|
||||
(when-not (<= low n high)
|
||||
(throw (js/Error. (str msg " Failed: " low "<=" n "<=" high))))
|
||||
n)
|
||||
|
||||
(defn parse-and-validate-timestamp [s]
|
||||
(let [[_ years months days hours minutes seconds fraction offset-sign offset-hours offset-minutes :as v]
|
||||
(re-matches timestamp-regex s)]
|
||||
(if-not v
|
||||
(throw (js/Error. (str "Unrecognized date/time syntax: " s)))
|
||||
(let [years (parse-int years)
|
||||
months (or (parse-int months) 1)
|
||||
days (or (parse-int days) 1)
|
||||
hours (or (parse-int hours) 0)
|
||||
minutes (or (parse-int minutes) 0)
|
||||
seconds (or (parse-int seconds) 0)
|
||||
fraction (or (parse-int (zero-fill-right-and-truncate fraction 3)) 0)
|
||||
offset-sign (if (= offset-sign "-") -1 1)
|
||||
offset-hours (or (parse-int offset-hours) 0)
|
||||
offset-minutes (or (parse-int offset-minutes) 0)
|
||||
offset (* offset-sign (+ (* offset-hours 60) offset-minutes))]
|
||||
[years
|
||||
(check 1 months 12 "timestamp month field must be in range 1..12")
|
||||
(check 1 days (days-in-month months (leap-year? years)) "timestamp day field must be in range 1..last day in month")
|
||||
(check 0 hours 23 "timestamp hour field must be in range 0..23")
|
||||
(check 0 minutes 59 "timestamp minute field must be in range 0..59")
|
||||
(check 0 seconds (if (= minutes 59) 60 59) "timestamp second field must be in range 0..60")
|
||||
(check 0 fraction 999 "timestamp millisecond field must be in range 0..999")
|
||||
offset]))))
|
||||
|
||||
(defn parse-timestamp
|
||||
[ts]
|
||||
(if-let [[years months days hours minutes seconds ms offset]
|
||||
(parse-and-validate-timestamp ts)]
|
||||
(js/Date.
|
||||
(- (.UTC js/Date years (dec months) days hours minutes seconds ms)
|
||||
(* offset 60 1000)))
|
||||
(throw (js/Error. (str "Unrecognized date/time syntax: " ts)))))
|
||||
|
||||
(defn ^:private read-date
|
||||
[s]
|
||||
(if (string? s)
|
||||
(parse-timestamp s)
|
||||
(throw (js/Error. "Instance literal expects a string for its timestamp."))))
|
||||
|
||||
(defn ^:private read-queue
|
||||
[elems]
|
||||
(if (vector? elems)
|
||||
(into cljs.core/PersistentQueue.EMPTY elems)
|
||||
(throw (js/Error. "Queue literal expects a vector for its elements."))))
|
||||
|
||||
(defn ^:private read-js
|
||||
[form]
|
||||
(cond
|
||||
(vector? form)
|
||||
(let [arr (array)]
|
||||
(doseq [x form]
|
||||
(.push arr x))
|
||||
arr)
|
||||
|
||||
(map? form)
|
||||
(let [obj (js-obj)]
|
||||
(doseq [[k v] form]
|
||||
(gobject/set obj (name k) v))
|
||||
obj)
|
||||
|
||||
:else
|
||||
(throw
|
||||
(js/Error.
|
||||
(str "JS literal expects a vector or map containing "
|
||||
"only string or unqualified keyword keys")))))
|
||||
|
||||
(defn ^:private read-uuid
|
||||
[uuid]
|
||||
(if (string? uuid)
|
||||
(cljs.core/uuid uuid)
|
||||
(throw (js/Error. "UUID literal expects a string as its representation."))))
|
||||
|
||||
(def ^:dynamic *default-data-reader-fn*
|
||||
(atom nil))
|
||||
|
||||
(def ^:dynamic *tag-table*
|
||||
(atom
|
||||
(add-data-readers
|
||||
{'inst read-date
|
||||
'uuid read-uuid
|
||||
'queue read-queue
|
||||
'js read-js})))
|
||||
|
||||
(defn read
|
||||
"Reads the first object from an cljs.tools.reader.reader-types/IPushbackReader.
|
||||
Returns the object read. If EOF, throws if eof-error? is true otherwise returns eof.
|
||||
If no reader is provided, *in* will be used.
|
||||
|
||||
Reads data in the edn format (subset of Clojure data):
|
||||
http://edn-format.org
|
||||
|
||||
cljs.tools.reader.edn/read doesn't depend on dynamic Vars, all configuration
|
||||
is done by passing an opt map.
|
||||
|
||||
opts is a map that can include the following keys:
|
||||
:eof - value to return on end-of-file. When not supplied, eof throws an exception.
|
||||
:readers - a map of tag symbols to data-reader functions to be considered before default-data-readers.
|
||||
When not supplied, only the default-data-readers will be used.
|
||||
:default - A function of two args, that will, if present and no reader is found for a tag,
|
||||
be called with the tag and the value."
|
||||
([reader]
|
||||
(edn/read
|
||||
{:readers @*tag-table*
|
||||
:default @*default-data-reader-fn*
|
||||
:eof nil}
|
||||
reader))
|
||||
([{:keys [eof] :as opts} reader]
|
||||
(edn/read
|
||||
(update (merge opts {:default @*default-data-reader-fn*})
|
||||
:readers (fn [m] (merge @*tag-table* m))) reader))
|
||||
([reader eof-error? eof opts]
|
||||
(edn/read reader eof-error? eof
|
||||
(update (merge opts {:default @*default-data-reader-fn*})
|
||||
:readers (fn [m] (merge @*tag-table* m))))))
|
||||
|
||||
(defn read-string
|
||||
"Reads one object from the string s.
|
||||
Returns nil when s is nil or empty.
|
||||
|
||||
Reads data in the edn format (subset of Clojure data):
|
||||
http://edn-format.org
|
||||
|
||||
opts is a map as per cljs.tools.reader.edn/read"
|
||||
([s]
|
||||
(edn/read-string
|
||||
{:readers @*tag-table*
|
||||
:default @*default-data-reader-fn*
|
||||
:eof nil} s))
|
||||
([opts s]
|
||||
(edn/read-string
|
||||
(update (merge {:default @*default-data-reader-fn*} opts)
|
||||
:readers (fn [m] (merge @*tag-table* m))) s)))
|
||||
|
||||
(defn register-tag-parser!
|
||||
[tag f]
|
||||
(let [old-parser (get @*tag-table* tag)]
|
||||
(swap! *tag-table* assoc tag f)
|
||||
old-parser))
|
||||
|
||||
(defn deregister-tag-parser!
|
||||
[tag]
|
||||
(let [old-parser (get @*tag-table* tag)]
|
||||
(swap! *tag-table* dissoc tag)
|
||||
old-parser))
|
||||
|
||||
(defn register-default-tag-parser!
|
||||
[f]
|
||||
(let [old-parser @*default-data-reader-fn*]
|
||||
(swap! *default-data-reader-fn* (fn [_] f))
|
||||
old-parser))
|
||||
|
||||
(defn deregister-default-tag-parser!
|
||||
[]
|
||||
(let [old-parser @*default-data-reader-fn*]
|
||||
(swap! *default-data-reader-fn* (fn [_] nil))
|
||||
old-parser))
|
||||
Executable
+448
@@ -0,0 +1,448 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.reader');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.tools.reader');
|
||||
goog.require('cljs.tools.reader.edn');
|
||||
goog.require('goog.string.StringBuffer');
|
||||
goog.require('goog.object');
|
||||
goog.scope(function(){
|
||||
cljs.reader.goog$module$goog$object = goog.module.get('goog.object');
|
||||
});
|
||||
cljs.reader.zero_fill_right_and_truncate = (function cljs$reader$zero_fill_right_and_truncate(s,width){
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(width,cljs.core.count(s))){
|
||||
return s;
|
||||
} else {
|
||||
if((width < cljs.core.count(s))){
|
||||
return cljs.core.subs.cljs$core$IFn$_invoke$arity$3(s,(0),width);
|
||||
} else {
|
||||
var b = (new goog.string.StringBuffer(s));
|
||||
while(true){
|
||||
if((b.getLength() < width)){
|
||||
var G__5976 = b.append("0");
|
||||
b = G__5976;
|
||||
continue;
|
||||
} else {
|
||||
return b.toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.reader.divisible_QMARK_ = (function cljs$reader$divisible_QMARK_(num,div){
|
||||
return (cljs.core.mod(num,div) === (0));
|
||||
});
|
||||
cljs.reader.indivisible_QMARK_ = (function cljs$reader$indivisible_QMARK_(num,div){
|
||||
return (!(cljs.reader.divisible_QMARK_(num,div)));
|
||||
});
|
||||
cljs.reader.leap_year_QMARK_ = (function cljs$reader$leap_year_QMARK_(year){
|
||||
return ((cljs.reader.divisible_QMARK_(year,(4))) && (((cljs.reader.indivisible_QMARK_(year,(100))) || (cljs.reader.divisible_QMARK_(year,(400))))));
|
||||
});
|
||||
cljs.reader.days_in_month = (function (){var dim_norm = new cljs.core.PersistentVector(null, 13, 5, cljs.core.PersistentVector.EMPTY_NODE, [null,(31),(28),(31),(30),(31),(30),(31),(31),(30),(31),(30),(31)], null);
|
||||
var dim_leap = new cljs.core.PersistentVector(null, 13, 5, cljs.core.PersistentVector.EMPTY_NODE, [null,(31),(29),(31),(30),(31),(30),(31),(31),(30),(31),(30),(31)], null);
|
||||
return (function (month,leap_year_QMARK_){
|
||||
return cljs.core.get.cljs$core$IFn$_invoke$arity$2((cljs.core.truth_(leap_year_QMARK_)?dim_leap:dim_norm),month);
|
||||
});
|
||||
})();
|
||||
cljs.reader.timestamp_regex = /(\d\d\d\d)(?:-(\d\d)(?:-(\d\d)(?:[T](\d\d)(?::(\d\d)(?::(\d\d)(?:[.](\d+))?)?)?)?)?)?(?:[Z]|([-+])(\d\d):(\d\d))?/;
|
||||
cljs.reader.parse_int = (function cljs$reader$parse_int(s){
|
||||
var n = parseInt(s,(10));
|
||||
if(cljs.core.not(isNaN(n))){
|
||||
return n;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.reader.check = (function cljs$reader$check(low,n,high,msg){
|
||||
if((((low <= n)) && ((n <= high)))){
|
||||
} else {
|
||||
throw (new Error([cljs.core.str.cljs$core$IFn$_invoke$arity$1(msg)," Failed: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(low),"<=",cljs.core.str.cljs$core$IFn$_invoke$arity$1(n),"<=",cljs.core.str.cljs$core$IFn$_invoke$arity$1(high)].join('')));
|
||||
}
|
||||
|
||||
return n;
|
||||
});
|
||||
cljs.reader.parse_and_validate_timestamp = (function cljs$reader$parse_and_validate_timestamp(s){
|
||||
var vec__5977 = cljs.core.re_matches(cljs.reader.timestamp_regex,s);
|
||||
var _ = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(0),null);
|
||||
var years = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(1),null);
|
||||
var months = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(2),null);
|
||||
var days = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(3),null);
|
||||
var hours = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(4),null);
|
||||
var minutes = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(5),null);
|
||||
var seconds = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(6),null);
|
||||
var fraction = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(7),null);
|
||||
var offset_sign = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(8),null);
|
||||
var offset_hours = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(9),null);
|
||||
var offset_minutes = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5977,(10),null);
|
||||
var v = vec__5977;
|
||||
if(cljs.core.not(v)){
|
||||
throw (new Error(["Unrecognized date/time syntax: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(s)].join('')));
|
||||
} else {
|
||||
var years__$1 = cljs.reader.parse_int(years);
|
||||
var months__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(months);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (1);
|
||||
}
|
||||
})();
|
||||
var days__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(days);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (1);
|
||||
}
|
||||
})();
|
||||
var hours__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(hours);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
})();
|
||||
var minutes__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(minutes);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
})();
|
||||
var seconds__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(seconds);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
})();
|
||||
var fraction__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(cljs.reader.zero_fill_right_and_truncate(fraction,(3)));
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
})();
|
||||
var offset_sign__$1 = ((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(offset_sign,"-"))?(-1):(1));
|
||||
var offset_hours__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(offset_hours);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
})();
|
||||
var offset_minutes__$1 = (function (){var or__5045__auto__ = cljs.reader.parse_int(offset_minutes);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
})();
|
||||
var offset = (offset_sign__$1 * ((offset_hours__$1 * (60)) + offset_minutes__$1));
|
||||
return new cljs.core.PersistentVector(null, 8, 5, cljs.core.PersistentVector.EMPTY_NODE, [years__$1,cljs.reader.check((1),months__$1,(12),"timestamp month field must be in range 1..12"),cljs.reader.check((1),days__$1,(function (){var G__5980 = months__$1;
|
||||
var G__5981 = cljs.reader.leap_year_QMARK_(years__$1);
|
||||
return (cljs.reader.days_in_month.cljs$core$IFn$_invoke$arity$2 ? cljs.reader.days_in_month.cljs$core$IFn$_invoke$arity$2(G__5980,G__5981) : cljs.reader.days_in_month.call(null,G__5980,G__5981));
|
||||
})(),"timestamp day field must be in range 1..last day in month"),cljs.reader.check((0),hours__$1,(23),"timestamp hour field must be in range 0..23"),cljs.reader.check((0),minutes__$1,(59),"timestamp minute field must be in range 0..59"),cljs.reader.check((0),seconds__$1,((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(minutes__$1,(59)))?(60):(59)),"timestamp second field must be in range 0..60"),cljs.reader.check((0),fraction__$1,(999),"timestamp millisecond field must be in range 0..999"),offset], null);
|
||||
}
|
||||
});
|
||||
cljs.reader.parse_timestamp = (function cljs$reader$parse_timestamp(ts){
|
||||
var temp__4655__auto__ = cljs.reader.parse_and_validate_timestamp(ts);
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var vec__5982 = temp__4655__auto__;
|
||||
var years = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(0),null);
|
||||
var months = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(1),null);
|
||||
var days = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(2),null);
|
||||
var hours = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(3),null);
|
||||
var minutes = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(4),null);
|
||||
var seconds = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(5),null);
|
||||
var ms = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(6),null);
|
||||
var offset = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5982,(7),null);
|
||||
return (new Date((Date.UTC(years,(months - (1)),days,hours,minutes,seconds,ms) - ((offset * (60)) * (1000)))));
|
||||
} else {
|
||||
throw (new Error(["Unrecognized date/time syntax: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(ts)].join('')));
|
||||
}
|
||||
});
|
||||
cljs.reader.read_date = (function cljs$reader$read_date(s){
|
||||
if(typeof s === 'string'){
|
||||
return cljs.reader.parse_timestamp(s);
|
||||
} else {
|
||||
throw (new Error("Instance literal expects a string for its timestamp."));
|
||||
}
|
||||
});
|
||||
cljs.reader.read_queue = (function cljs$reader$read_queue(elems){
|
||||
if(cljs.core.vector_QMARK_(elems)){
|
||||
return cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentQueue.EMPTY,elems);
|
||||
} else {
|
||||
throw (new Error("Queue literal expects a vector for its elements."));
|
||||
}
|
||||
});
|
||||
cljs.reader.read_js = (function cljs$reader$read_js(form){
|
||||
if(cljs.core.vector_QMARK_(form)){
|
||||
var arr = [];
|
||||
var seq__5985_6019 = cljs.core.seq(form);
|
||||
var chunk__5986_6020 = null;
|
||||
var count__5987_6021 = (0);
|
||||
var i__5988_6022 = (0);
|
||||
while(true){
|
||||
if((i__5988_6022 < count__5987_6021)){
|
||||
var x_6023 = chunk__5986_6020.cljs$core$IIndexed$_nth$arity$2(null,i__5988_6022);
|
||||
arr.push(x_6023);
|
||||
|
||||
|
||||
var G__6024 = seq__5985_6019;
|
||||
var G__6025 = chunk__5986_6020;
|
||||
var G__6026 = count__5987_6021;
|
||||
var G__6027 = (i__5988_6022 + (1));
|
||||
seq__5985_6019 = G__6024;
|
||||
chunk__5986_6020 = G__6025;
|
||||
count__5987_6021 = G__6026;
|
||||
i__5988_6022 = G__6027;
|
||||
continue;
|
||||
} else {
|
||||
var temp__4657__auto___6028 = cljs.core.seq(seq__5985_6019);
|
||||
if(temp__4657__auto___6028){
|
||||
var seq__5985_6029__$1 = temp__4657__auto___6028;
|
||||
if(cljs.core.chunked_seq_QMARK_(seq__5985_6029__$1)){
|
||||
var c__5568__auto___6030 = cljs.core.chunk_first(seq__5985_6029__$1);
|
||||
var G__6031 = cljs.core.chunk_rest(seq__5985_6029__$1);
|
||||
var G__6032 = c__5568__auto___6030;
|
||||
var G__6033 = cljs.core.count(c__5568__auto___6030);
|
||||
var G__6034 = (0);
|
||||
seq__5985_6019 = G__6031;
|
||||
chunk__5986_6020 = G__6032;
|
||||
count__5987_6021 = G__6033;
|
||||
i__5988_6022 = G__6034;
|
||||
continue;
|
||||
} else {
|
||||
var x_6035 = cljs.core.first(seq__5985_6029__$1);
|
||||
arr.push(x_6035);
|
||||
|
||||
|
||||
var G__6036 = cljs.core.next(seq__5985_6029__$1);
|
||||
var G__6037 = null;
|
||||
var G__6038 = (0);
|
||||
var G__6039 = (0);
|
||||
seq__5985_6019 = G__6036;
|
||||
chunk__5986_6020 = G__6037;
|
||||
count__5987_6021 = G__6038;
|
||||
i__5988_6022 = G__6039;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return arr;
|
||||
} else {
|
||||
if(cljs.core.map_QMARK_(form)){
|
||||
var obj = ({});
|
||||
var seq__5991_6040 = cljs.core.seq(form);
|
||||
var chunk__5992_6041 = null;
|
||||
var count__5993_6042 = (0);
|
||||
var i__5994_6043 = (0);
|
||||
while(true){
|
||||
if((i__5994_6043 < count__5993_6042)){
|
||||
var vec__6007_6044 = chunk__5992_6041.cljs$core$IIndexed$_nth$arity$2(null,i__5994_6043);
|
||||
var k_6045 = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__6007_6044,(0),null);
|
||||
var v_6046 = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__6007_6044,(1),null);
|
||||
var G__6010_6047 = obj;
|
||||
var G__6011_6048 = cljs.core.name(k_6045);
|
||||
var G__6012_6049 = v_6046;
|
||||
cljs.reader.goog$module$goog$object.set.call(null,G__6010_6047,G__6011_6048,G__6012_6049);
|
||||
|
||||
|
||||
var G__6050 = seq__5991_6040;
|
||||
var G__6051 = chunk__5992_6041;
|
||||
var G__6052 = count__5993_6042;
|
||||
var G__6053 = (i__5994_6043 + (1));
|
||||
seq__5991_6040 = G__6050;
|
||||
chunk__5992_6041 = G__6051;
|
||||
count__5993_6042 = G__6052;
|
||||
i__5994_6043 = G__6053;
|
||||
continue;
|
||||
} else {
|
||||
var temp__4657__auto___6054 = cljs.core.seq(seq__5991_6040);
|
||||
if(temp__4657__auto___6054){
|
||||
var seq__5991_6055__$1 = temp__4657__auto___6054;
|
||||
if(cljs.core.chunked_seq_QMARK_(seq__5991_6055__$1)){
|
||||
var c__5568__auto___6056 = cljs.core.chunk_first(seq__5991_6055__$1);
|
||||
var G__6057 = cljs.core.chunk_rest(seq__5991_6055__$1);
|
||||
var G__6058 = c__5568__auto___6056;
|
||||
var G__6059 = cljs.core.count(c__5568__auto___6056);
|
||||
var G__6060 = (0);
|
||||
seq__5991_6040 = G__6057;
|
||||
chunk__5992_6041 = G__6058;
|
||||
count__5993_6042 = G__6059;
|
||||
i__5994_6043 = G__6060;
|
||||
continue;
|
||||
} else {
|
||||
var vec__6013_6061 = cljs.core.first(seq__5991_6055__$1);
|
||||
var k_6062 = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__6013_6061,(0),null);
|
||||
var v_6063 = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__6013_6061,(1),null);
|
||||
var G__6016_6064 = obj;
|
||||
var G__6017_6065 = cljs.core.name(k_6062);
|
||||
var G__6018_6066 = v_6063;
|
||||
cljs.reader.goog$module$goog$object.set.call(null,G__6016_6064,G__6017_6065,G__6018_6066);
|
||||
|
||||
|
||||
var G__6067 = cljs.core.next(seq__5991_6055__$1);
|
||||
var G__6068 = null;
|
||||
var G__6069 = (0);
|
||||
var G__6070 = (0);
|
||||
seq__5991_6040 = G__6067;
|
||||
chunk__5992_6041 = G__6068;
|
||||
count__5993_6042 = G__6069;
|
||||
i__5994_6043 = G__6070;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return obj;
|
||||
} else {
|
||||
throw (new Error(["JS literal expects a vector or map containing ","only string or unqualified keyword keys"].join('')));
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.reader.read_uuid = (function cljs$reader$read_uuid(uuid){
|
||||
if(typeof uuid === 'string'){
|
||||
return cljs.core.uuid(uuid);
|
||||
} else {
|
||||
throw (new Error("UUID literal expects a string as its representation."));
|
||||
}
|
||||
});
|
||||
cljs.reader._STAR_default_data_reader_fn_STAR_ = cljs.core.atom.cljs$core$IFn$_invoke$arity$1(null);
|
||||
cljs.reader._STAR_tag_table_STAR_ = cljs.core.atom.cljs$core$IFn$_invoke$arity$1(cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([new cljs.core.PersistentArrayMap(null, 4, [cljs.core.cst$sym$inst,cljs.reader.read_date,cljs.core.cst$sym$uuid,cljs.reader.read_uuid,cljs.core.cst$sym$queue,cljs.reader.read_queue,cljs.core.cst$sym$js,cljs.reader.read_js], null),cljs.core.PersistentArrayMap.EMPTY], 0)));
|
||||
/**
|
||||
* Reads the first object from an cljs.tools.reader.reader-types/IPushbackReader.
|
||||
* Returns the object read. If EOF, throws if eof-error? is true otherwise returns eof.
|
||||
* If no reader is provided, *in* will be used.
|
||||
*
|
||||
* Reads data in the edn format (subset of Clojure data):
|
||||
* http://edn-format.org
|
||||
*
|
||||
* cljs.tools.reader.edn/read doesn't depend on dynamic Vars, all configuration
|
||||
* is done by passing an opt map.
|
||||
*
|
||||
* opts is a map that can include the following keys:
|
||||
* :eof - value to return on end-of-file. When not supplied, eof throws an exception.
|
||||
* :readers - a map of tag symbols to data-reader functions to be considered before default-data-readers.
|
||||
* When not supplied, only the default-data-readers will be used.
|
||||
* :default - A function of two args, that will, if present and no reader is found for a tag,
|
||||
* be called with the tag and the value.
|
||||
*/
|
||||
cljs.reader.read = (function cljs$reader$read(var_args){
|
||||
var G__6072 = arguments.length;
|
||||
switch (G__6072) {
|
||||
case 1:
|
||||
return cljs.reader.read.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.reader.read.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 4:
|
||||
return cljs.reader.read.cljs$core$IFn$_invoke$arity$4((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.reader.read.cljs$core$IFn$_invoke$arity$1 = (function (reader){
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentArrayMap(null, 3, [cljs.core.cst$kw$readers,cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),cljs.core.cst$kw$default,cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_),cljs.core.cst$kw$eof,null], null),reader);
|
||||
}));
|
||||
|
||||
(cljs.reader.read.cljs$core$IFn$_invoke$arity$2 = (function (p__6073,reader){
|
||||
var map__6074 = p__6073;
|
||||
var map__6074__$1 = cljs.core.__destructure_map(map__6074);
|
||||
var opts = map__6074__$1;
|
||||
var eof = cljs.core.get.cljs$core$IFn$_invoke$arity$2(map__6074__$1,cljs.core.cst$kw$eof);
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$2(cljs.core.update.cljs$core$IFn$_invoke$arity$3(cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([opts,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$default,cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_)], null)], 0)),cljs.core.cst$kw$readers,(function (m){
|
||||
return cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),m], 0));
|
||||
})),reader);
|
||||
}));
|
||||
|
||||
(cljs.reader.read.cljs$core$IFn$_invoke$arity$4 = (function (reader,eof_error_QMARK_,eof,opts){
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(reader,eof_error_QMARK_,eof,cljs.core.update.cljs$core$IFn$_invoke$arity$3(cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([opts,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$default,cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_)], null)], 0)),cljs.core.cst$kw$readers,(function (m){
|
||||
return cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),m], 0));
|
||||
})));
|
||||
}));
|
||||
|
||||
(cljs.reader.read.cljs$lang$maxFixedArity = 4);
|
||||
|
||||
/**
|
||||
* Reads one object from the string s.
|
||||
* Returns nil when s is nil or empty.
|
||||
*
|
||||
* Reads data in the edn format (subset of Clojure data):
|
||||
* http://edn-format.org
|
||||
*
|
||||
* opts is a map as per cljs.tools.reader.edn/read
|
||||
*/
|
||||
cljs.reader.read_string = (function cljs$reader$read_string(var_args){
|
||||
var G__6077 = arguments.length;
|
||||
switch (G__6077) {
|
||||
case 1:
|
||||
return cljs.reader.read_string.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.reader.read_string.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.reader.read_string.cljs$core$IFn$_invoke$arity$1 = (function (s){
|
||||
return cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentArrayMap(null, 3, [cljs.core.cst$kw$readers,cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),cljs.core.cst$kw$default,cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_),cljs.core.cst$kw$eof,null], null),s);
|
||||
}));
|
||||
|
||||
(cljs.reader.read_string.cljs$core$IFn$_invoke$arity$2 = (function (opts,s){
|
||||
return cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$2(cljs.core.update.cljs$core$IFn$_invoke$arity$3(cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$default,cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_)], null),opts], 0)),cljs.core.cst$kw$readers,(function (m){
|
||||
return cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),m], 0));
|
||||
})),s);
|
||||
}));
|
||||
|
||||
(cljs.reader.read_string.cljs$lang$maxFixedArity = 2);
|
||||
|
||||
cljs.reader.register_tag_parser_BANG_ = (function cljs$reader$register_tag_parser_BANG_(tag,f){
|
||||
var old_parser = cljs.core.get.cljs$core$IFn$_invoke$arity$2(cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),tag);
|
||||
cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$4(cljs.reader._STAR_tag_table_STAR_,cljs.core.assoc,tag,f);
|
||||
|
||||
return old_parser;
|
||||
});
|
||||
cljs.reader.deregister_tag_parser_BANG_ = (function cljs$reader$deregister_tag_parser_BANG_(tag){
|
||||
var old_parser = cljs.core.get.cljs$core$IFn$_invoke$arity$2(cljs.core.deref(cljs.reader._STAR_tag_table_STAR_),tag);
|
||||
cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$3(cljs.reader._STAR_tag_table_STAR_,cljs.core.dissoc,tag);
|
||||
|
||||
return old_parser;
|
||||
});
|
||||
cljs.reader.register_default_tag_parser_BANG_ = (function cljs$reader$register_default_tag_parser_BANG_(f){
|
||||
var old_parser = cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_);
|
||||
cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$2(cljs.reader._STAR_default_data_reader_fn_STAR_,(function (_){
|
||||
return f;
|
||||
}));
|
||||
|
||||
return old_parser;
|
||||
});
|
||||
cljs.reader.deregister_default_tag_parser_BANG_ = (function cljs$reader$deregister_default_tag_parser_BANG_(){
|
||||
var old_parser = cljs.core.deref(cljs.reader._STAR_default_data_reader_fn_STAR_);
|
||||
cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$2(cljs.reader._STAR_default_data_reader_fn_STAR_,(function (_){
|
||||
return null;
|
||||
}));
|
||||
|
||||
return old_parser;
|
||||
});
|
||||
Executable
+965
@@ -0,0 +1,965 @@
|
||||
;; Copyright (c) Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns ^{:doc "A clojure reader in clojure"
|
||||
:author "Bronsa"}
|
||||
cljs.tools.reader
|
||||
(:refer-clojure :exclude [read read-line read-string char read+string
|
||||
default-data-readers *default-data-reader-fn*
|
||||
*data-readers* *suppress-read*])
|
||||
(:require-macros [cljs.tools.reader.reader-types :refer [log-source]])
|
||||
(:require [cljs.tools.reader.reader-types :refer
|
||||
[read-char unread peek-char indexing-reader?
|
||||
get-line-number get-column-number get-file-name
|
||||
string-push-back-reader]]
|
||||
[cljs.tools.reader.impl.utils :refer
|
||||
[char ex-info? whitespace? numeric? desugar-meta next-id namespace-keys second'
|
||||
ReaderConditional reader-conditional reader-conditional? char-code]]
|
||||
[cljs.tools.reader.impl.commons :refer
|
||||
[number-literal? read-past match-number parse-symbol read-comment throwing-reader]]
|
||||
[cljs.tools.reader.impl.errors :as err]
|
||||
[goog.array :as garray]
|
||||
[goog.string :as gstring])
|
||||
(:import goog.string.StringBuffer))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(declare ^:private read*
|
||||
macros dispatch-macros
|
||||
^:dynamic *data-readers*
|
||||
^:dynamic *default-data-reader-fn*
|
||||
^:dynamic *suppress-read*
|
||||
default-data-readers)
|
||||
|
||||
(defn- ^boolean macro-terminating? [ch]
|
||||
(case ch
|
||||
(\" \; \@ \^ \` \~ \( \) \[ \] \{ \} \\) true
|
||||
false))
|
||||
|
||||
(def sb (StringBuffer.))
|
||||
|
||||
(defn- read-token
|
||||
"Read in a single logical token from the reader"
|
||||
[^not-native rdr kind initch]
|
||||
(if (nil? initch)
|
||||
(err/throw-eof-at-start rdr kind)
|
||||
(do
|
||||
(.clear sb)
|
||||
(loop [ch initch]
|
||||
(if (or (whitespace? ch)
|
||||
(macro-terminating? ch)
|
||||
(nil? ch))
|
||||
(do
|
||||
(when-not (nil? ch)
|
||||
(unread rdr ch))
|
||||
(.toString sb))
|
||||
(do
|
||||
(.append sb ch)
|
||||
(recur (read-char rdr))))))))
|
||||
|
||||
(declare read-tagged)
|
||||
|
||||
(defn- read-dispatch
|
||||
[^not-native rdr _ opts pending-forms]
|
||||
(if-let [ch (read-char rdr)]
|
||||
(if-let [dm (dispatch-macros ch)]
|
||||
(dm rdr ch opts pending-forms)
|
||||
(read-tagged (doto rdr (unread ch)) ch opts pending-forms)) ;; ctor reader is implemented as a tagged literal
|
||||
(err/throw-eof-at-dispatch rdr)))
|
||||
|
||||
(defn- read-unmatched-delimiter
|
||||
[rdr ch opts pending-forms]
|
||||
(err/throw-unmatch-delimiter rdr ch))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; readers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn read-regex
|
||||
[^not-native rdr ch opts pending-forms]
|
||||
(let [sb (StringBuffer.)]
|
||||
(loop [ch (read-char rdr)]
|
||||
(if (identical? \" ch)
|
||||
(re-pattern (str sb))
|
||||
(if (nil? ch)
|
||||
(err/throw-eof-reading rdr :regex sb)
|
||||
(do
|
||||
(.append sb ch )
|
||||
(when (identical? \\ ch)
|
||||
(let [ch (read-char rdr)]
|
||||
(if (nil? ch)
|
||||
(err/throw-eof-reading rdr :regex sb))
|
||||
(.append sb ch)))
|
||||
(recur (read-char rdr))))))))
|
||||
|
||||
(defn- read-unicode-char
|
||||
([token offset length base]
|
||||
(let [l (+ offset length)]
|
||||
(when-not (== (count token) l)
|
||||
(err/throw-invalid-unicode-literal nil token))
|
||||
(loop [i offset uc 0]
|
||||
(if (== i l)
|
||||
(js/String.fromCharCode uc)
|
||||
(let [d (char-code (nth token i) base)]
|
||||
(if (== d -1)
|
||||
(err/throw-invalid-unicode-digit-in-token nil (nth token i) token)
|
||||
(recur (inc i) (+ d (* uc base)))))))))
|
||||
|
||||
([^not-native rdr initch base length exact?]
|
||||
(loop [i 1 uc (char-code initch base)]
|
||||
(if (== uc -1)
|
||||
(err/throw-invalid-unicode-digit rdr initch)
|
||||
(if-not (== i length)
|
||||
(let [ch (peek-char rdr)]
|
||||
(if (or (whitespace? ch)
|
||||
(macros ch)
|
||||
(nil? ch))
|
||||
(if exact?
|
||||
(err/throw-invalid-unicode-len rdr i length)
|
||||
(js/String.fromCharCode uc))
|
||||
(let [d (char-code ch base)]
|
||||
(read-char rdr)
|
||||
(if (== d -1)
|
||||
(err/throw-invalid-unicode-digit rdr ch)
|
||||
(recur (inc i) (+ d (* uc base)))))))
|
||||
(js/String.fromCharCode uc))))))
|
||||
|
||||
(def ^:private ^:const upper-limit (.charCodeAt \uD7ff 0))
|
||||
(def ^:private ^:const lower-limit (.charCodeAt \uE000 0))
|
||||
|
||||
(defn- valid-octal? [token base]
|
||||
(<= (js/parseInt token base) 0377))
|
||||
|
||||
(defn- read-char*
|
||||
"Read in a character literal"
|
||||
[^not-native rdr backslash opts pending-forms]
|
||||
(let [ch (read-char rdr)]
|
||||
(if-not (nil? ch)
|
||||
(let [token (if (or (macro-terminating? ch)
|
||||
(whitespace? ch))
|
||||
(str ch)
|
||||
(read-token rdr :character ch))
|
||||
token-len (. token -length)]
|
||||
(cond
|
||||
|
||||
(== 1 token-len) (.charAt token 0) ;;; no char type - so can't ensure/cache char
|
||||
|
||||
(= token "newline") \newline
|
||||
(= token "space") \space
|
||||
(= token "tab") \tab
|
||||
(= token "backspace") \backspace
|
||||
(= token "formfeed") \formfeed
|
||||
(= token "return") \return
|
||||
|
||||
(gstring/startsWith token "u")
|
||||
(let [c (read-unicode-char token 1 4 16)
|
||||
ic (.charCodeAt c 0)]
|
||||
(if (and (> ic upper-limit)
|
||||
(< ic lower-limit))
|
||||
(err/throw-invalid-character-literal rdr (.toString ic 16))
|
||||
c))
|
||||
|
||||
(gstring/startsWith token "o")
|
||||
(let [len (dec token-len)]
|
||||
(if (> len 3)
|
||||
(err/throw-invalid-octal-len rdr token)
|
||||
(let [offset 1
|
||||
base 8
|
||||
uc (read-unicode-char token offset len base)]
|
||||
(if-not (valid-octal? (subs token offset) base)
|
||||
(err/throw-bad-octal-number rdr)
|
||||
uc))))
|
||||
|
||||
:else (err/throw-unsupported-character rdr token)))
|
||||
(err/throw-eof-in-character rdr))))
|
||||
|
||||
(defn- starting-line-col-info [^not-native rdr]
|
||||
(when (indexing-reader? rdr)
|
||||
[(get-line-number rdr) (int (dec (get-column-number rdr)))]))
|
||||
|
||||
(defn- ending-line-col-info [^not-native rdr]
|
||||
(when (indexing-reader? rdr)
|
||||
[(get-line-number rdr) (get-column-number rdr)]))
|
||||
|
||||
(defonce ^:private READ_EOF (js/Object.))
|
||||
(defonce ^:private READ_FINISHED (js/Object.))
|
||||
|
||||
(def ^:dynamic *read-delim* false)
|
||||
|
||||
(defn- read-delimited-internal [kind delim rdr opts pending-forms]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
delim (char delim)]
|
||||
(loop [a (transient [])]
|
||||
(let [form (read* rdr false READ_EOF delim opts pending-forms)]
|
||||
(if (identical? form READ_FINISHED)
|
||||
(persistent! a)
|
||||
(if (identical? form READ_EOF)
|
||||
(err/throw-eof-delimited rdr kind start-line start-column (count a))
|
||||
(recur (conj! a form))))))))
|
||||
|
||||
(defn- read-delimited
|
||||
"Reads and returns a collection ended with delim"
|
||||
[kind delim rdr opts pending-forms]
|
||||
(binding [*read-delim* true]
|
||||
(read-delimited-internal kind delim rdr opts pending-forms)))
|
||||
|
||||
(defn- read-list
|
||||
"Read in a list, including its location if the reader is an indexing reader"
|
||||
[rdr _ opts pending-forms]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
the-list (read-delimited :list \) rdr opts pending-forms)
|
||||
[end-line end-column] (ending-line-col-info rdr)]
|
||||
(with-meta (if (empty? the-list)
|
||||
'()
|
||||
(apply list the-list))
|
||||
(when start-line
|
||||
(merge
|
||||
(when-let [file (get-file-name rdr)]
|
||||
{:file file})
|
||||
{:line start-line
|
||||
:column start-column
|
||||
:end-line end-line
|
||||
:end-column end-column})))))
|
||||
|
||||
(defn- read-vector
|
||||
"Read in a vector, including its location if the reader is an indexing reader"
|
||||
[rdr _ opts pending-forms]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
the-vector (read-delimited :vector \] rdr opts pending-forms)
|
||||
[end-line end-column] (ending-line-col-info rdr)]
|
||||
(with-meta the-vector
|
||||
(when start-line
|
||||
(merge
|
||||
(when-let [file (get-file-name rdr)]
|
||||
{:file file})
|
||||
{:line start-line
|
||||
:column start-column
|
||||
:end-line end-line
|
||||
:end-column end-column})))))
|
||||
|
||||
(defn- read-map
|
||||
"Read in a map, including its location if the reader is an indexing reader"
|
||||
[rdr _ opts pending-forms]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
the-map (read-delimited :map \} rdr opts pending-forms)
|
||||
map-count (count the-map)
|
||||
ks (take-nth 2 the-map)
|
||||
key-set (set ks)
|
||||
[end-line end-column] (ending-line-col-info rdr)]
|
||||
(when (odd? map-count)
|
||||
(err/throw-odd-map rdr start-line start-column the-map))
|
||||
(when-not (= (count key-set) (count ks))
|
||||
(err/throw-dup-keys rdr :map ks))
|
||||
(with-meta
|
||||
(if (<= map-count (* 2 (.-HASHMAP-THRESHOLD cljs.core/PersistentArrayMap)))
|
||||
(.fromArray cljs.core/PersistentArrayMap (to-array the-map) true true)
|
||||
(.fromArray cljs.core/PersistentHashMap (to-array the-map) true))
|
||||
(when start-line
|
||||
(merge
|
||||
(when-let [file (get-file-name rdr)]
|
||||
{:file file})
|
||||
{:line start-line
|
||||
:column start-column
|
||||
:end-line end-line
|
||||
:end-column end-column})))))
|
||||
|
||||
(defn- read-number
|
||||
[^not-native rdr initch]
|
||||
(loop [sb (doto (StringBuffer.) (.append initch))
|
||||
ch (read-char rdr)]
|
||||
(if (or (whitespace? ch) (macros ch) (nil? ch))
|
||||
(let [s (str sb)]
|
||||
(unread rdr ch)
|
||||
(or (match-number s)
|
||||
(err/throw-invalid-number rdr s)))
|
||||
(recur (doto sb (.append ch)) (read-char rdr)))))
|
||||
|
||||
(defn- escape-char [sb ^not-native rdr]
|
||||
(let [ch (read-char rdr)]
|
||||
(case ch
|
||||
\t "\t"
|
||||
\r "\r"
|
||||
\n "\n"
|
||||
\\ "\\"
|
||||
\" "\""
|
||||
\b "\b"
|
||||
\f "\f"
|
||||
\u (let [ch (read-char rdr)]
|
||||
(if (== -1 (js/parseInt (int ch) 16))
|
||||
(err/throw-invalid-unicode-escape rdr ch)
|
||||
(read-unicode-char rdr ch 16 4 true)))
|
||||
(if (numeric? ch)
|
||||
(let [ch (read-unicode-char rdr ch 8 3 false)]
|
||||
(if (> (int ch) 0377)
|
||||
(err/throw-bad-octal-number rdr)
|
||||
ch))
|
||||
(err/throw-bad-escape-char rdr ch)))))
|
||||
|
||||
(defn- read-string*
|
||||
[^not-native reader _ opts pending-forms]
|
||||
(loop [sb (StringBuffer.)
|
||||
ch (read-char reader)]
|
||||
(if (nil? ch)
|
||||
(err/throw-eof-reading reader :string \" sb)
|
||||
(case ch
|
||||
\\ (recur (doto sb (.append (escape-char sb reader)))
|
||||
(read-char reader))
|
||||
\" (str sb)
|
||||
(recur (doto sb (.append ch)) (read-char reader))))))
|
||||
|
||||
(defn- loc-info [rdr line column]
|
||||
(when-not (nil? line)
|
||||
(let [file (get-file-name rdr)
|
||||
filem (when-not (nil? file) {:file file})
|
||||
[end-line end-column] (ending-line-col-info rdr)
|
||||
lcm {:line line
|
||||
:column column
|
||||
:end-line end-line
|
||||
:end-column end-column}]
|
||||
(merge filem lcm))))
|
||||
|
||||
(defn- read-symbol
|
||||
[rdr initch]
|
||||
(let [[line column] (starting-line-col-info rdr)
|
||||
token (read-token rdr :symbol initch)]
|
||||
(when-not (nil? token)
|
||||
(case token
|
||||
|
||||
;; special symbols
|
||||
"nil" nil
|
||||
"true" true
|
||||
"false" false
|
||||
"/" '/
|
||||
|
||||
(let [^not-native p (parse-symbol token)]
|
||||
(if-not (nil? p)
|
||||
(let [^not-native sym (symbol (-nth p 0) (-nth p 1))]
|
||||
(-with-meta sym (loc-info rdr line column)))
|
||||
(err/throw-invalid rdr :symbol token)))))))
|
||||
|
||||
(def ^:dynamic *alias-map*
|
||||
"Map from ns alias to ns, if non-nil, it will be used to resolve read-time
|
||||
ns aliases.
|
||||
|
||||
Defaults to nil"
|
||||
nil)
|
||||
|
||||
(defn- resolve-alias [sym]
|
||||
(get *alias-map* sym))
|
||||
|
||||
(defn- resolve-ns [sym]
|
||||
(or (resolve-alias sym)
|
||||
(when-let [ns (find-ns sym)]
|
||||
(symbol (ns-name ns)))))
|
||||
|
||||
(defn- read-keyword
|
||||
[^not-native reader initch opts pending-forms]
|
||||
(let [ch (read-char reader)]
|
||||
(if-not (whitespace? ch)
|
||||
(let [token (read-token reader :keyword ch)
|
||||
^not-native s (parse-symbol token)]
|
||||
(if-not (nil? s)
|
||||
(let [ns (-nth s 0)
|
||||
name (-nth s 1)]
|
||||
(if (identical? \: (.charAt token 0))
|
||||
(if-not (nil? ns)
|
||||
(if-let [ns (resolve-alias (symbol (subs ns 1)))]
|
||||
(keyword (str ns) name)
|
||||
(err/throw-invalid reader :keyword (str \: token)))
|
||||
(if-let [ns *ns*]
|
||||
(keyword (str ns) (subs name 1))
|
||||
(err/reader-error reader "Invalid token: :" token)))
|
||||
(keyword ns name)))
|
||||
(err/throw-invalid reader :keyword (str \: token))))
|
||||
(err/throw-single-colon reader))))
|
||||
|
||||
(defn- wrapping-reader
|
||||
"Returns a function which wraps a reader in a call to sym"
|
||||
[sym]
|
||||
(fn [rdr _ opts pending-forms]
|
||||
(list sym (read* rdr true nil opts pending-forms))))
|
||||
|
||||
(defn- read-meta
|
||||
"Read metadata and return the following object with the metadata applied"
|
||||
[rdr _ opts pending-forms]
|
||||
(log-source rdr
|
||||
(let [[line column] (starting-line-col-info rdr)
|
||||
m (desugar-meta (read* rdr true nil opts pending-forms))]
|
||||
(when-not (map? m)
|
||||
(err/throw-bad-metadata rdr m))
|
||||
(let [o (read* rdr true nil opts pending-forms)]
|
||||
(if (implements? IMeta o)
|
||||
(let [m (if (and line (seq? o))
|
||||
(assoc m :line line :column column)
|
||||
m)]
|
||||
(if (implements? IWithMeta o)
|
||||
(with-meta o (merge (meta o) m))
|
||||
(reset-meta! o m)))
|
||||
(err/throw-bad-metadata-target rdr o))))))
|
||||
|
||||
(defn- read-set
|
||||
[rdr _ opts pending-forms]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
;; subtract 1 from start-column so it includes the # in the leading #{
|
||||
start-column (if start-column (int (dec start-column)))
|
||||
coll (read-delimited :set \} rdr opts pending-forms)
|
||||
the-set (set coll)
|
||||
[end-line end-column] (ending-line-col-info rdr)]
|
||||
(when-not (= (count coll) (count the-set))
|
||||
(err/reader-error rdr (err/throw-dup-keys rdr :set coll)))
|
||||
(with-meta the-set
|
||||
(when start-line
|
||||
(merge
|
||||
(when-let [file (get-file-name rdr)]
|
||||
{:file file})
|
||||
{:line start-line
|
||||
:column start-column
|
||||
:end-line end-line
|
||||
:end-column end-column})))))
|
||||
|
||||
(defn- read-discard
|
||||
"Read and discard the first object from rdr"
|
||||
[rdr _ opts pending-forms]
|
||||
(doto rdr
|
||||
(read* true nil opts pending-forms)))
|
||||
|
||||
(defn- read-symbolic-value
|
||||
[rdr _ opts pending-forms]
|
||||
(let [sym (read* rdr true nil opts pending-forms)]
|
||||
(case sym
|
||||
|
||||
NaN js/Number.NaN
|
||||
-Inf js/Number.NEGATIVE_INFINITY
|
||||
Inf js/Number.POSITIVE_INFINITY
|
||||
|
||||
(err/reader-error rdr (str "Invalid token: ##" sym)))))
|
||||
|
||||
(def ^:private RESERVED_FEATURES #{:else :none})
|
||||
|
||||
(defn- has-feature?
|
||||
[rdr feature opts]
|
||||
(if (keyword? feature)
|
||||
(or (= :default feature) (contains? (get opts :features) feature))
|
||||
(err/reader-error rdr "Feature should be a keyword: " feature)))
|
||||
|
||||
(defn- check-eof-error
|
||||
[form rdr first-line]
|
||||
(when (identical? form READ_EOF)
|
||||
(err/throw-eof-error rdr (and (< first-line 0) first-line))))
|
||||
|
||||
(defn- check-reserved-features
|
||||
[rdr form]
|
||||
(when (get RESERVED_FEATURES form)
|
||||
(err/reader-error rdr "Feature name " form " is reserved")))
|
||||
|
||||
(defn- check-invalid-read-cond
|
||||
[form rdr first-line]
|
||||
(when (identical? form READ_FINISHED)
|
||||
(if (< first-line 0)
|
||||
(err/reader-error rdr "read-cond requires an even number of forms")
|
||||
(err/reader-error rdr "read-cond starting on line " first-line " requires an even number of forms"))))
|
||||
|
||||
(defn- read-suppress
|
||||
"Read next form and suppress. Return nil or READ_FINISHED."
|
||||
[first-line rdr opts pending-forms]
|
||||
(binding [*suppress-read* true]
|
||||
(let [form (read* rdr false READ_EOF \) opts pending-forms)]
|
||||
(check-eof-error form rdr first-line)
|
||||
(when (identical? form READ_FINISHED)
|
||||
READ_FINISHED))))
|
||||
|
||||
(defonce ^:private NO_MATCH (js/Object.))
|
||||
|
||||
(defn- match-feature
|
||||
"Read next feature. If matched, read next form and return.
|
||||
Otherwise, read and skip next form, returning READ_FINISHED or nil."
|
||||
[first-line rdr opts pending-forms]
|
||||
(let [feature (read* rdr false READ_EOF \) opts pending-forms)]
|
||||
(check-eof-error feature rdr first-line)
|
||||
(if (= feature READ_FINISHED)
|
||||
READ_FINISHED
|
||||
(do
|
||||
(check-reserved-features rdr feature)
|
||||
(if (has-feature? rdr feature opts)
|
||||
;; feature matched, read selected form
|
||||
(doto (read* rdr false READ_EOF \) opts pending-forms)
|
||||
(check-eof-error rdr first-line)
|
||||
(check-invalid-read-cond rdr first-line))
|
||||
;; feature not matched, ignore next form
|
||||
(or (read-suppress first-line rdr opts pending-forms)
|
||||
NO_MATCH))))))
|
||||
|
||||
(defn- read-cond-delimited
|
||||
[rdr splicing opts pending-forms]
|
||||
(let [first-line (if (indexing-reader? rdr) (get-line-number rdr) -1)
|
||||
result (loop [matched NO_MATCH
|
||||
finished nil]
|
||||
(cond
|
||||
;; still looking for match, read feature+form
|
||||
(identical? matched NO_MATCH)
|
||||
(let [match (match-feature first-line rdr opts pending-forms)]
|
||||
(if (identical? match READ_FINISHED)
|
||||
READ_FINISHED
|
||||
(recur match nil)))
|
||||
|
||||
;; found match, just read and ignore the rest
|
||||
(not (identical? finished READ_FINISHED))
|
||||
(recur matched (read-suppress first-line rdr opts pending-forms))
|
||||
|
||||
:else
|
||||
matched))]
|
||||
(if (identical? result READ_FINISHED)
|
||||
rdr
|
||||
(if splicing
|
||||
(do
|
||||
(if (implements? ISequential result)
|
||||
(do
|
||||
(garray/insertArrayAt pending-forms (to-array result) 0)
|
||||
rdr)
|
||||
(err/reader-error rdr "Spliced form list in read-cond-splicing must implement ISequential")))
|
||||
result))))
|
||||
|
||||
(defn- read-cond
|
||||
[^not-native rdr _ opts pending-forms]
|
||||
(when (not (and opts (#{:allow :preserve} (:read-cond opts))))
|
||||
(throw (ex-info "Conditional read not allowed"
|
||||
{:type :runtime-exception})))
|
||||
(if-let [ch (read-char rdr)]
|
||||
(let [splicing (= ch \@)
|
||||
ch (if splicing (read-char rdr) ch)]
|
||||
(when splicing
|
||||
(when-not *read-delim*
|
||||
(err/reader-error rdr "cond-splice not in list")))
|
||||
(if-let [ch (if (whitespace? ch) (read-past whitespace? rdr) ch)]
|
||||
(if (not= ch \()
|
||||
(throw (ex-info "read-cond body must be a list"
|
||||
{:type :runtime-exception}))
|
||||
(binding [*suppress-read* (or *suppress-read* (= :preserve (:read-cond opts)))]
|
||||
(if *suppress-read*
|
||||
(reader-conditional (read-list rdr ch opts pending-forms) splicing)
|
||||
(read-cond-delimited rdr splicing opts pending-forms))))
|
||||
(err/throw-eof-in-character rdr)))
|
||||
(err/throw-eof-in-character rdr)))
|
||||
|
||||
(def ^:private ^:dynamic arg-env nil)
|
||||
|
||||
(defn- garg
|
||||
"Get a symbol for an anonymous ?argument?"
|
||||
[n]
|
||||
(symbol (str (if (== -1 n) "rest" (str "p" n))
|
||||
"__" (next-id) "#")))
|
||||
|
||||
(defn- read-fn
|
||||
[rdr _ opts pending-forms]
|
||||
(if arg-env
|
||||
(throw (ex-info "Nested #()s are not allowed" {:type :illegal-state})))
|
||||
(binding [arg-env (sorted-map)]
|
||||
(let [form (read* (doto rdr (unread \()) true nil opts pending-forms) ;; this sets bindings
|
||||
rargs (rseq arg-env)
|
||||
args (if rargs
|
||||
(let [higharg (key (first rargs))]
|
||||
(let [args (loop [i 1 args (transient [])]
|
||||
(if (> i higharg)
|
||||
(persistent! args)
|
||||
(recur (inc i) (conj! args (or (get arg-env i)
|
||||
(garg i))))))
|
||||
args (if (arg-env -1)
|
||||
(conj args '& (arg-env -1))
|
||||
args)]
|
||||
args))
|
||||
[])]
|
||||
(list 'fn* args form))))
|
||||
|
||||
(defn- register-arg
|
||||
"Registers an argument to the arg-env"
|
||||
[n]
|
||||
(if arg-env
|
||||
(if-let [ret (arg-env n)]
|
||||
ret
|
||||
(let [g (garg n)]
|
||||
(set! arg-env (assoc arg-env n g))
|
||||
g))
|
||||
(throw (ex-info "Arg literal not in #()"
|
||||
{:type :illegal-state})))) ;; should never hit this
|
||||
|
||||
(declare read-symbol)
|
||||
|
||||
(defn- read-arg
|
||||
[^not-native rdr pct opts pending-forms]
|
||||
(if (nil? arg-env)
|
||||
(read-symbol rdr pct)
|
||||
(let [ch (peek-char rdr)]
|
||||
(cond
|
||||
(or (whitespace? ch)
|
||||
(macro-terminating? ch)
|
||||
(nil? ch))
|
||||
(register-arg 1)
|
||||
|
||||
(= ch \&)
|
||||
(do (read-char rdr)
|
||||
(register-arg -1))
|
||||
|
||||
:else
|
||||
(let [n (read* rdr true nil opts pending-forms)]
|
||||
(if-not (integer? n)
|
||||
(throw (ex-info "Arg literal must be %, %& or %integer"
|
||||
{:type :illegal-state}))
|
||||
(register-arg n)))))))
|
||||
|
||||
(def ^:private ^:dynamic gensym-env nil)
|
||||
|
||||
(defn- read-unquote
|
||||
[^not-native rdr comma opts pending-forms]
|
||||
(if-let [ch (peek-char rdr)]
|
||||
(if (= \@ ch)
|
||||
((wrapping-reader 'clojure.core/unquote-splicing) (doto rdr read-char) \@ opts pending-forms)
|
||||
((wrapping-reader 'clojure.core/unquote) rdr \~ opts pending-forms))))
|
||||
|
||||
(declare syntax-quote*)
|
||||
|
||||
(defn- unquote-splicing? [form]
|
||||
(and (seq? form)
|
||||
(= (first form) 'clojure.core/unquote-splicing)))
|
||||
|
||||
(defn- unquote? [form]
|
||||
(and (seq? form)
|
||||
(= (first form) 'clojure.core/unquote)))
|
||||
|
||||
(defn- expand-list
|
||||
"Expand a list by resolving its syntax quotes and unquotes"
|
||||
[s]
|
||||
(loop [s (seq s) r (transient [])]
|
||||
(if s
|
||||
(let [item (first s)
|
||||
ret (conj! r
|
||||
(cond
|
||||
(unquote? item) (list 'clojure.core/list (second item))
|
||||
(unquote-splicing? item) (second item)
|
||||
:else (list 'clojure.core/list (syntax-quote* item))))]
|
||||
(recur (next s) ret))
|
||||
(seq (persistent! r)))))
|
||||
|
||||
(defn- flatten-map
|
||||
"Flatten a map into a seq of alternate keys and values"
|
||||
[form]
|
||||
(loop [s (seq form) key-vals (transient [])]
|
||||
(if s
|
||||
(let [e (first s)]
|
||||
(recur (next s) (-> key-vals
|
||||
(conj! (key e))
|
||||
(conj! (val e)))))
|
||||
(seq (persistent! key-vals)))))
|
||||
|
||||
(defn- register-gensym [sym]
|
||||
(if-not gensym-env
|
||||
(throw (ex-info "Gensym literal not in syntax-quote"
|
||||
{:type :illegal-state})))
|
||||
(or (get gensym-env sym)
|
||||
(let [gs (symbol (str (subs (name sym)
|
||||
0 (dec (count (name sym))))
|
||||
"__" (next-id) "__auto__"))]
|
||||
(set! gensym-env (assoc gensym-env sym gs))
|
||||
gs)))
|
||||
|
||||
(defn- add-meta [form ret]
|
||||
(if (and (implements? IWithMeta form)
|
||||
(seq (dissoc (meta form) :line :column :end-line :end-column :file :source)))
|
||||
(list 'cljs.core/with-meta ret (syntax-quote* (meta form)))
|
||||
ret))
|
||||
|
||||
(defn- syntax-quote-coll [type coll]
|
||||
(let [res (list 'cljs.core/sequence
|
||||
(cons 'cljs.core/concat
|
||||
(expand-list coll)))]
|
||||
(if type
|
||||
(list 'cljs.core/apply type res)
|
||||
res)))
|
||||
|
||||
(defn map-func
|
||||
"Decide which map type to use, array-map if less than 16 elements"
|
||||
[coll]
|
||||
(if (>= (count coll) 16)
|
||||
'cljs.core/hash-map
|
||||
'cljs.core/array-map))
|
||||
|
||||
(defn bool? [x]
|
||||
(or (instance? js/Boolean x)
|
||||
(true? x)
|
||||
(false? x)))
|
||||
|
||||
(defn ^:dynamic resolve-symbol
|
||||
"Resolve a symbol s into its fully qualified namespace version"
|
||||
[s]
|
||||
(throw (ex-info "resolve-symbol is not implemented" {:sym s})))
|
||||
|
||||
(defn- syntax-quote* [form]
|
||||
(->>
|
||||
(cond
|
||||
(special-symbol? form) (list 'quote form)
|
||||
|
||||
(symbol? form)
|
||||
(list 'quote
|
||||
(if (and (not (namespace form))
|
||||
(gstring/endsWith (name form) "#"))
|
||||
(register-gensym form)
|
||||
(let [sym (str form)]
|
||||
(if (gstring/endsWith sym ".")
|
||||
(let [csym (symbol (subs sym 0 (dec (count sym))))]
|
||||
(symbol (str (resolve-symbol csym) ".")))
|
||||
(resolve-symbol form)))))
|
||||
|
||||
(unquote? form) (second form)
|
||||
(unquote-splicing? form) (throw (ex-info "unquote-splice not in list"
|
||||
{:type :illegal-state}))
|
||||
|
||||
(coll? form)
|
||||
(cond
|
||||
|
||||
(implements? IRecord form) form
|
||||
(map? form) (syntax-quote-coll (map-func form) (flatten-map form))
|
||||
(vector? form) (list 'cljs.core/vec (syntax-quote-coll nil form))
|
||||
(set? form) (syntax-quote-coll 'cljs.core/hash-set form)
|
||||
(or (seq? form) (list? form))
|
||||
(let [seq (seq form)]
|
||||
(if seq
|
||||
(syntax-quote-coll nil seq)
|
||||
'(cljs.core/list)))
|
||||
|
||||
:else (throw (ex-info "Unknown Collection type"
|
||||
{:type :unsupported-operation})))
|
||||
|
||||
(or (keyword? form)
|
||||
(number? form)
|
||||
(string? form)
|
||||
(nil? form)
|
||||
(bool? form)
|
||||
(instance? js/RegExp form))
|
||||
form
|
||||
|
||||
:else (list 'quote form))
|
||||
(add-meta form)))
|
||||
|
||||
(defn- read-syntax-quote
|
||||
[rdr backquote opts pending-forms]
|
||||
(binding [gensym-env {}]
|
||||
(-> (read* rdr true nil opts pending-forms)
|
||||
syntax-quote*)))
|
||||
|
||||
(defn- read-namespaced-map
|
||||
[rdr _ opts pending-forms]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
token (read-token rdr :namespaced-map (read-char rdr))]
|
||||
(if-let [ns (cond
|
||||
(= token ":")
|
||||
(ns-name *ns*)
|
||||
|
||||
(= \: (first token))
|
||||
(some-> token (subs 1) parse-symbol second' symbol resolve-ns)
|
||||
|
||||
:else
|
||||
(some-> token parse-symbol second'))]
|
||||
|
||||
(let [ch (read-past whitespace? rdr)]
|
||||
(if (identical? ch \{)
|
||||
(let [items (read-delimited :namespaced-map \} rdr opts pending-forms)
|
||||
[end-line end-column] (ending-line-col-info rdr)]
|
||||
(when (odd? (count items))
|
||||
(err/throw-odd-map rdr nil nil items))
|
||||
(let [keys (namespace-keys (str ns) (take-nth 2 items))
|
||||
vals (take-nth 2 (rest items))]
|
||||
(when-not (= (count (set keys)) (count keys))
|
||||
(err/throw-dup-keys rdr :namespaced-map keys))
|
||||
(with-meta (zipmap keys vals)
|
||||
(when start-line
|
||||
(merge
|
||||
(when-let [file (get-file-name rdr)]
|
||||
{:file file})
|
||||
{:line start-line
|
||||
:column start-column
|
||||
:end-line end-line
|
||||
:end-column end-column})))))
|
||||
(err/throw-ns-map-no-map rdr token)))
|
||||
(err/throw-bad-ns rdr token))))
|
||||
|
||||
(defn- macros [ch]
|
||||
(case ch
|
||||
\" read-string*
|
||||
\: read-keyword
|
||||
\; read-comment
|
||||
\' (wrapping-reader 'quote)
|
||||
\@ (wrapping-reader 'clojure.core/deref)
|
||||
\^ read-meta
|
||||
\` read-syntax-quote
|
||||
\~ read-unquote
|
||||
\( read-list
|
||||
\) read-unmatched-delimiter
|
||||
\[ read-vector
|
||||
\] read-unmatched-delimiter
|
||||
\{ read-map
|
||||
\} read-unmatched-delimiter
|
||||
\\ read-char*
|
||||
\% read-arg
|
||||
\# read-dispatch
|
||||
nil))
|
||||
|
||||
(defn- dispatch-macros [ch]
|
||||
(case ch
|
||||
\^ read-meta ;; deprecated
|
||||
\' (wrapping-reader 'var)
|
||||
\( read-fn
|
||||
\{ read-set
|
||||
\< (throwing-reader "Unreadable form")
|
||||
\= (throwing-reader "read-eval not supported")
|
||||
\" read-regex
|
||||
\! read-comment
|
||||
\_ read-discard
|
||||
\? read-cond
|
||||
\: read-namespaced-map
|
||||
\# read-symbolic-value
|
||||
nil))
|
||||
|
||||
(defn- read-tagged [^not-native rdr initch opts pending-forms]
|
||||
(let [tag (read* rdr true nil opts pending-forms)]
|
||||
(if-not (symbol? tag)
|
||||
(err/throw-bad-reader-tag rdr tag))
|
||||
(if *suppress-read*
|
||||
(tagged-literal tag (read* rdr true nil opts pending-forms))
|
||||
(if-let [f (or (*data-readers* tag)
|
||||
(default-data-readers tag))]
|
||||
(f (read* rdr true nil opts pending-forms))
|
||||
(if-let [f *default-data-reader-fn*]
|
||||
(f tag (read* rdr true nil opts pending-forms))
|
||||
(err/throw-unknown-reader-tag rdr tag))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Public API
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(def ^:dynamic *data-readers*
|
||||
"Map from reader tag symbols to data reader Vars.
|
||||
Reader tags without namespace qualifiers are reserved for Clojure.
|
||||
This light version of tools.reader has no implementation for default
|
||||
reader tags such as #inst and #uuid."
|
||||
{})
|
||||
|
||||
(def ^:dynamic *default-data-reader-fn*
|
||||
"When no data reader is found for a tag and *default-data-reader-fn*
|
||||
is non-nil, it will be called with two arguments, the tag and the value.
|
||||
If *default-data-reader-fn* is nil (the default value), an exception
|
||||
will be thrown for the unknown tag."
|
||||
nil)
|
||||
|
||||
(def ^:dynamic *suppress-read* false)
|
||||
|
||||
(def default-data-readers
|
||||
"Default map of data reader functions provided by Clojure.
|
||||
May be overridden by binding *data-readers*"
|
||||
{})
|
||||
|
||||
(defn- read*-internal
|
||||
[^not-native reader ^boolean eof-error? sentinel return-on opts pending-forms]
|
||||
(loop []
|
||||
(log-source reader
|
||||
(if-not ^boolean (garray/isEmpty pending-forms)
|
||||
(let [form (aget pending-forms 0)]
|
||||
(garray/removeAt pending-forms 0)
|
||||
form)
|
||||
(let [ch (read-char reader)]
|
||||
(cond
|
||||
(whitespace? ch) (recur)
|
||||
(nil? ch) (if eof-error? (err/throw-eof-error reader nil) sentinel)
|
||||
(identical? ch return-on) READ_FINISHED
|
||||
(number-literal? reader ch) (read-number reader ch)
|
||||
:else (let [f (macros ch)]
|
||||
(if-not (nil? f)
|
||||
(let [res (f reader ch opts pending-forms)]
|
||||
(if (identical? res reader)
|
||||
(recur)
|
||||
res))
|
||||
(read-symbol reader ch)))))))))
|
||||
|
||||
(defn- read*
|
||||
([reader eof-error? sentinel opts pending-forms]
|
||||
(read* reader eof-error? sentinel nil opts pending-forms))
|
||||
([^not-native reader eof-error? sentinel return-on opts pending-forms]
|
||||
(try
|
||||
(read*-internal reader eof-error? sentinel return-on opts pending-forms)
|
||||
(catch js/Error e
|
||||
(if (ex-info? e)
|
||||
(let [d (ex-data e)]
|
||||
(if (= :reader-exception (:type d))
|
||||
(throw e)
|
||||
(throw (ex-info (.-message e)
|
||||
(merge {:type :reader-exception}
|
||||
d
|
||||
(if (indexing-reader? reader)
|
||||
{:line (get-line-number reader)
|
||||
:column (get-column-number reader)
|
||||
:file (get-file-name reader)}))
|
||||
e))))
|
||||
(throw (ex-info (.-message e)
|
||||
(merge {:type :reader-exception}
|
||||
(if (indexing-reader? reader)
|
||||
{:line (get-line-number reader)
|
||||
:column (get-column-number reader)
|
||||
:file (get-file-name reader)}))
|
||||
e)))))))
|
||||
|
||||
(defn read
|
||||
"Reads the first object from an IPushbackReader.
|
||||
Returns the object read. If EOF, throws if eof-error? is true.
|
||||
Otherwise returns sentinel. If no stream is provided, *in* will be used.
|
||||
|
||||
Opts is a persistent map with valid keys:
|
||||
:read-cond - :allow to process reader conditionals, or
|
||||
:preserve to keep all branches
|
||||
:features - persistent set of feature keywords for reader conditionals
|
||||
:eof - on eof, return value unless :eofthrow, then throw.
|
||||
if not specified, will throw
|
||||
|
||||
To read data structures only, use cljs.tools.reader.edn/read
|
||||
|
||||
Note that the function signature of cljs.tools.reader/read and
|
||||
cljs.tools.reader.edn/read is not the same for eof-handling"
|
||||
{:arglists '([reader] [opts reader] [reader eof-error? eof-value])}
|
||||
([reader] (read reader true nil))
|
||||
([{eof :eof :as opts :or {eof :eofthrow}} reader] (read* reader (= eof :eofthrow) eof nil opts (to-array [])))
|
||||
([reader eof-error? sentinel] (read* reader eof-error? sentinel nil {} (to-array []))))
|
||||
|
||||
(defn read-string
|
||||
"Reads one object from the string s.
|
||||
Returns nil when s is nil or empty.
|
||||
|
||||
To read data structures only, use cljs.tools.reader.edn/read-string
|
||||
|
||||
Note that the function signature of cljs.tools.reader/read-string and
|
||||
cljs.tools.reader.edn/read-string is not the same for eof-handling"
|
||||
([s]
|
||||
(read-string {} s))
|
||||
([opts s]
|
||||
(when (and s (not (identical? s "")))
|
||||
(read opts (string-push-back-reader s)))))
|
||||
|
||||
(defn read+string
|
||||
"Like read, and taking the same args. reader must be a SourceLoggingPushbackReader.
|
||||
Returns a vector containing the object read and the (whitespace-trimmed) string read."
|
||||
([stream] (read+string stream true nil))
|
||||
([stream eof-error? eof-value]
|
||||
(let [buf (fn [stream] (str (:buffer @(.-frames stream))))
|
||||
offset (count (buf stream))
|
||||
o (log-source stream (read stream eof-error? eof-value))
|
||||
s (.trim (subs (buf stream) offset))]
|
||||
[o s]))
|
||||
([opts stream]
|
||||
(let [buf (fn [stream] (str (:buffer @(.-frames stream))))
|
||||
offset (count (buf stream))
|
||||
o (log-source stream (read opts stream))
|
||||
s (.trim (subs (buf stream) offset))]
|
||||
[o s])))
|
||||
Executable
+1816
File diff suppressed because it is too large
Load Diff
Executable
+446
@@ -0,0 +1,446 @@
|
||||
;; Copyright (c) Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns ^{:doc "An EDN reader in clojure"
|
||||
:author "Bronsa"}
|
||||
cljs.tools.reader.edn
|
||||
(:refer-clojure :exclude [read read-string char default-data-readers])
|
||||
(:require [cljs.tools.reader.impl.errors :as err]
|
||||
[cljs.tools.reader.reader-types :refer
|
||||
[read-char unread peek-char indexing-reader?
|
||||
get-line-number get-column-number get-file-name string-push-back-reader]]
|
||||
[cljs.tools.reader.impl.utils :refer
|
||||
[char ex-info? whitespace? numeric? desugar-meta namespace-keys second' char-code]]
|
||||
[cljs.tools.reader.impl.commons :refer
|
||||
[number-literal? read-past match-number parse-symbol read-comment throwing-reader]]
|
||||
[cljs.tools.reader :refer [default-data-readers]]
|
||||
[goog.string :as gstring])
|
||||
(:import goog.string.StringBuffer))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(declare read macros dispatch-macros)
|
||||
|
||||
(defn- ^boolean macro-terminating? [ch]
|
||||
(and (not (identical? \# ch))
|
||||
(not (identical? \' ch))
|
||||
(not (identical? \: ch))
|
||||
(macros ch)))
|
||||
|
||||
(defn- ^boolean not-constituent? [ch]
|
||||
(or (identical? \@ ch)
|
||||
(identical? \` ch)
|
||||
(identical? \~ ch)))
|
||||
|
||||
(defn- read-token
|
||||
([rdr kind initch]
|
||||
(read-token rdr kind initch true))
|
||||
([rdr kind initch validate-leading?]
|
||||
(cond
|
||||
(not initch)
|
||||
(err/throw-eof-at-start rdr kind)
|
||||
|
||||
(and validate-leading?
|
||||
(not-constituent? initch))
|
||||
(err/throw-bad-char rdr kind initch)
|
||||
|
||||
:else
|
||||
(loop [sb (StringBuffer.)
|
||||
ch (do (unread rdr initch) initch)]
|
||||
(if (or (whitespace? ch)
|
||||
(macro-terminating? ch)
|
||||
(nil? ch))
|
||||
(str sb)
|
||||
(if (not-constituent? ch)
|
||||
(err/throw-bad-char rdr kind ch)
|
||||
(recur (doto sb (.append (read-char rdr))) (peek-char rdr))))))))
|
||||
|
||||
(declare read-tagged)
|
||||
|
||||
(defn- read-dispatch
|
||||
[rdr _ opts]
|
||||
(if-let [ch (read-char rdr)]
|
||||
(if-let [dm (dispatch-macros ch)]
|
||||
(dm rdr ch opts)
|
||||
(read-tagged (doto rdr (unread ch)) ch opts))
|
||||
(err/throw-eof-at-dispatch rdr)))
|
||||
|
||||
(defn- read-unmatched-delimiter
|
||||
[rdr ch opts]
|
||||
(err/throw-unmatch-delimiter rdr ch))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; readers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- read-unicode-char
|
||||
([token offset length base]
|
||||
(let [l (+ offset length)]
|
||||
(when-not (== (count token) l)
|
||||
(err/throw-invalid-unicode-literal nil token))
|
||||
(loop [i offset uc 0]
|
||||
(if (== i l)
|
||||
(js/String.fromCharCode uc)
|
||||
(let [d (char-code (nth token i) base)]
|
||||
(if (== d -1)
|
||||
(err/throw-invalid-unicode-digit-in-token nil (nth token i) token)
|
||||
(recur (inc i) (+ d (* uc base)))))))))
|
||||
|
||||
([rdr initch base length exact?]
|
||||
(loop [i 1 uc (char-code initch base)]
|
||||
(if (== uc -1)
|
||||
(err/throw-invalid-unicode-digit rdr initch)
|
||||
(if-not (== i length)
|
||||
(let [ch (peek-char rdr)]
|
||||
(if (or (whitespace? ch)
|
||||
(macros ch)
|
||||
(nil? ch))
|
||||
(if exact?
|
||||
(err/throw-invalid-unicode-len rdr i length)
|
||||
(js/String.fromCharCode uc))
|
||||
(let [d (char-code ch base)]
|
||||
(read-char rdr)
|
||||
(if (== d -1)
|
||||
(err/throw-invalid-unicode-digit rdr ch)
|
||||
(recur (inc i) (+ d (* uc base)))))))
|
||||
(js/String.fromCharCode uc))))))
|
||||
|
||||
(def ^:private ^:const upper-limit (.charCodeAt \uD7ff 0))
|
||||
(def ^:private ^:const lower-limit (.charCodeAt \uE000 0))
|
||||
|
||||
(defn- read-char*
|
||||
[rdr backslash opts]
|
||||
(let [ch (read-char rdr)]
|
||||
(if-not (nil? ch)
|
||||
(let [token (if (or (macro-terminating? ch)
|
||||
(not-constituent? ch)
|
||||
(whitespace? ch))
|
||||
(str ch)
|
||||
(read-token rdr :character ch false))
|
||||
token-len (count token)]
|
||||
(cond
|
||||
|
||||
(== 1 token-len) (nth token 0)
|
||||
|
||||
(identical? token "newline") \newline
|
||||
(identical? token "space") \space
|
||||
(identical? token "tab") \tab
|
||||
(identical? token "backspace") \backspace
|
||||
(identical? token "formfeed") \formfeed
|
||||
(identical? token "return") \return
|
||||
|
||||
(gstring/startsWith token "u")
|
||||
(let [c (read-unicode-char token 1 4 16)
|
||||
ic (.charCodeAt c)]
|
||||
(if (and (> ic upper-limit)
|
||||
(< ic lower-limit))
|
||||
(err/throw-invalid-character-literal rdr (.toString ic 16))
|
||||
c))
|
||||
|
||||
(gstring/startsWith token "o")
|
||||
(let [len (dec token-len)]
|
||||
(if (> len 3)
|
||||
(err/throw-invalid-octal-len rdr token)
|
||||
(let [uc (read-unicode-char token 1 len 8)]
|
||||
(if (> (int uc) 0377)
|
||||
(err/throw-bad-octal-number rdr)
|
||||
uc))))
|
||||
|
||||
:else (err/throw-unsupported-character rdr token)))
|
||||
(err/throw-eof-in-character rdr))))
|
||||
|
||||
(defn ^:private starting-line-col-info [rdr]
|
||||
(when (indexing-reader? rdr)
|
||||
[(get-line-number rdr) (int (dec (int (get-column-number rdr))))]))
|
||||
|
||||
(defn- read-delimited
|
||||
[kind delim rdr opts]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
delim (char delim)]
|
||||
(loop [a (transient [])]
|
||||
(let [ch (read-past whitespace? rdr)]
|
||||
(when-not ch
|
||||
(err/throw-eof-delimited rdr kind start-line start-column (count a)))
|
||||
(if (= delim (char ch))
|
||||
(persistent! a)
|
||||
(if-let [macrofn (macros ch)]
|
||||
(let [mret (macrofn rdr ch opts)]
|
||||
(recur (if-not (identical? mret rdr) (conj! a mret) a)))
|
||||
(let [o (read (doto rdr (unread ch)) true nil opts)]
|
||||
(recur (if-not (identical? o rdr) (conj! a o) a)))))))))
|
||||
|
||||
(defn- read-list
|
||||
[rdr _ opts]
|
||||
(let [the-list (read-delimited :list \) rdr opts)]
|
||||
(if (empty? the-list)
|
||||
'()
|
||||
(apply list the-list))))
|
||||
|
||||
(defn- read-vector
|
||||
[rdr _ opts]
|
||||
(read-delimited :vector \] rdr opts))
|
||||
|
||||
|
||||
(defn- read-map
|
||||
[rdr _ opts]
|
||||
(let [[start-line start-column] (starting-line-col-info rdr)
|
||||
the-map (read-delimited :map \} rdr opts)
|
||||
map-count (count the-map)
|
||||
ks (take-nth 2 the-map)
|
||||
key-set (set ks)]
|
||||
(when (odd? map-count)
|
||||
(err/throw-odd-map rdr start-line start-column the-map))
|
||||
(when-not (= (count key-set) (count ks))
|
||||
(err/throw-dup-keys rdr :map ks))
|
||||
(if (<= map-count (* 2 (.-HASHMAP-THRESHOLD cljs.core/PersistentArrayMap)))
|
||||
(.fromArray cljs.core/PersistentArrayMap (to-array the-map) true true)
|
||||
(.fromArray cljs.core/PersistentHashMap (to-array the-map) true))))
|
||||
|
||||
(defn- read-number
|
||||
[rdr initch opts]
|
||||
(loop [sb (doto (StringBuffer.) (.append initch))
|
||||
ch (read-char rdr)]
|
||||
(if (or (whitespace? ch) (macros ch) (nil? ch))
|
||||
(let [s (str sb)]
|
||||
(unread rdr ch)
|
||||
(or (match-number s)
|
||||
(err/throw-invalid-number rdr s)))
|
||||
(recur (doto sb (.append ch)) (read-char rdr)))))
|
||||
|
||||
(defn- escape-char [sb rdr]
|
||||
(let [ch (read-char rdr)]
|
||||
(case ch
|
||||
\t "\t"
|
||||
\r "\r"
|
||||
\n "\n"
|
||||
\\ "\\"
|
||||
\" "\""
|
||||
\b "\b"
|
||||
\f "\f"
|
||||
\u (let [ch (read-char rdr)]
|
||||
(if (== -1 (js/parseInt (int ch) 16))
|
||||
(err/throw-invalid-unicode-escape rdr ch)
|
||||
(read-unicode-char rdr ch 16 4 true)))
|
||||
(if (numeric? ch)
|
||||
(let [ch (read-unicode-char rdr ch 8 3 false)]
|
||||
(if (> (int ch) 0377)
|
||||
(err/throw-bad-octal-number rdr)
|
||||
ch))
|
||||
(err/throw-bad-escape-char rdr ch)))))
|
||||
|
||||
(defn- read-string*
|
||||
[rdr _ opts]
|
||||
(loop [sb (StringBuffer.)
|
||||
ch (read-char rdr)]
|
||||
(case ch
|
||||
nil (err/throw-eof-reading rdr :string \" sb)
|
||||
\\ (recur (doto sb (.append (escape-char sb rdr)))
|
||||
(read-char rdr))
|
||||
\" (str sb)
|
||||
(recur (doto sb (.append ch)) (read-char rdr)))))
|
||||
|
||||
(defn- read-symbol
|
||||
[rdr initch]
|
||||
(when-let [token (read-token rdr :symbol initch)]
|
||||
(case token
|
||||
|
||||
;; special symbols
|
||||
"nil" nil
|
||||
"true" true
|
||||
"false" false
|
||||
"/" '/
|
||||
|
||||
(or (when-let [p (parse-symbol token)]
|
||||
(symbol (p 0) (p 1)))
|
||||
(err/throw-invalid rdr :symbol token)))))
|
||||
|
||||
(defn- read-keyword
|
||||
[reader initch opts]
|
||||
(let [ch (read-char reader)]
|
||||
(if-not (whitespace? ch)
|
||||
(let [token (read-token reader :keyword ch)
|
||||
s (parse-symbol token)]
|
||||
(if (and s (== -1 (.indexOf token "::")))
|
||||
(let [ns (s 0)
|
||||
name (s 1)]
|
||||
(if (identical? \: (nth token 0))
|
||||
(err/throw-invalid reader :keyword (str \: token)) ;; no ::keyword in edn
|
||||
(keyword ns name)))
|
||||
(err/throw-invalid reader :keyword (str \: token))))
|
||||
(err/throw-single-colon reader))))
|
||||
|
||||
(defn- wrapping-reader
|
||||
[sym]
|
||||
(fn [rdr _ opts]
|
||||
(list sym (read rdr true nil opts))))
|
||||
|
||||
(defn- read-meta
|
||||
[rdr _ opts]
|
||||
(let [m (desugar-meta (read rdr true nil opts))]
|
||||
(when-not (map? m)
|
||||
(err/throw-bad-metadata rdr m))
|
||||
(let [o (read rdr true nil opts)]
|
||||
(if (implements? IMeta o)
|
||||
(with-meta o (merge (meta o) m))
|
||||
(err/throw-bad-metadata-target rdr o)))))
|
||||
|
||||
(defn- read-set
|
||||
[rdr _ opts]
|
||||
(let [coll (read-delimited :set \} rdr opts)
|
||||
the-set (set coll)]
|
||||
(when-not (= (count coll) (count the-set))
|
||||
(err/throw-dup-keys rdr :set coll))
|
||||
the-set))
|
||||
|
||||
(defn- read-discard
|
||||
[rdr _ opts]
|
||||
(doto rdr
|
||||
(read true nil true)))
|
||||
|
||||
(defn- read-namespaced-map
|
||||
[rdr _ opts]
|
||||
(let [token (read-token rdr :namespaced-map (read-char rdr))]
|
||||
(if-let [ns (some-> token parse-symbol second')]
|
||||
(let [ch (read-past whitespace? rdr)]
|
||||
(if (identical? ch \{)
|
||||
(let [items (read-delimited :namespaced-map \} rdr opts)]
|
||||
(when (odd? (count items))
|
||||
(err/throw-odd-map rdr nil nil items))
|
||||
(let [keys (namespace-keys (str ns) (take-nth 2 items))
|
||||
vals (take-nth 2 (rest items))]
|
||||
(when-not (= (count (set keys)) (count keys))
|
||||
(err/throw-dup-keys rdr :namespaced-map keys))
|
||||
(zipmap keys vals)))
|
||||
(err/throw-ns-map-no-map rdr token)))
|
||||
(err/throw-bad-ns rdr token))))
|
||||
|
||||
(defn- read-symbolic-value
|
||||
[rdr _ opts]
|
||||
(let [sym (read rdr true nil opts)]
|
||||
(case sym
|
||||
|
||||
NaN js/Number.NaN
|
||||
-Inf js/Number.NEGATIVE_INFINITY
|
||||
Inf js/Number.POSITIVE_INFINITY
|
||||
|
||||
(err/reader-error rdr (str "Invalid token: ##" sym)))))
|
||||
|
||||
(defn- macros [ch]
|
||||
(case ch
|
||||
\" read-string*
|
||||
\: read-keyword
|
||||
\; read-comment
|
||||
\^ read-meta
|
||||
\( read-list
|
||||
\) read-unmatched-delimiter
|
||||
\[ read-vector
|
||||
\] read-unmatched-delimiter
|
||||
\{ read-map
|
||||
\} read-unmatched-delimiter
|
||||
\\ read-char*
|
||||
\# read-dispatch
|
||||
nil))
|
||||
|
||||
(defn- dispatch-macros [ch]
|
||||
(case ch
|
||||
\^ read-meta ;deprecated
|
||||
\{ read-set
|
||||
\< (throwing-reader "Unreadable form")
|
||||
\! read-comment
|
||||
\_ read-discard
|
||||
\: read-namespaced-map
|
||||
\# read-symbolic-value
|
||||
nil))
|
||||
|
||||
(defn- read-tagged [rdr initch opts]
|
||||
(let [tag (read rdr true nil opts)
|
||||
object (read rdr true nil opts)]
|
||||
(if-not (symbol? tag)
|
||||
(err/throw-bad-reader-tag rdr "Reader tag must be a symbol"))
|
||||
(if-let [f (or (get (:readers opts) tag)
|
||||
(default-data-readers tag))]
|
||||
(f object)
|
||||
(if-let [d (:default opts)]
|
||||
(d tag object)
|
||||
(err/throw-unknown-reader-tag rdr tag)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Public API
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn read
|
||||
"Reads the first object from an IPushbackReader.
|
||||
Returns the object read. If EOF, throws if eof-error? is true otherwise returns eof.
|
||||
If no reader is provided, *in* will be used.
|
||||
|
||||
Reads data in the edn format (subset of Clojure data):
|
||||
http://edn-format.org
|
||||
|
||||
cljs.tools.reader.edn/read doesn't depend on dynamic Vars, all configuration
|
||||
is done by passing an opt map.
|
||||
|
||||
opts is a map that can include the following keys:
|
||||
:eof - value to return on end-of-file. When not supplied, eof throws an exception.
|
||||
:readers - a map of tag symbols to data-reader functions to be considered before default-data-readers.
|
||||
When not supplied, only the default-data-readers will be used.
|
||||
:default - A function of two args, that will, if present and no reader is found for a tag,
|
||||
be called with the tag and the value."
|
||||
([reader] (read {} reader))
|
||||
([{:keys [eof] :as opts} reader]
|
||||
(let [eof-error? (not (contains? opts :eof))]
|
||||
(read reader eof-error? eof opts)))
|
||||
([reader eof-error? eof opts]
|
||||
(try
|
||||
(loop []
|
||||
(let [ch (read-char reader)]
|
||||
(cond
|
||||
(whitespace? ch) (recur)
|
||||
(nil? ch) (if eof-error? (err/throw-eof-error reader nil) eof)
|
||||
(number-literal? reader ch) (read-number reader ch opts)
|
||||
:else (let [f (macros ch)]
|
||||
(if f
|
||||
(let [res (f reader ch opts)]
|
||||
(if (identical? res reader)
|
||||
(recur)
|
||||
res))
|
||||
(read-symbol reader ch))))))
|
||||
(catch js/Error e
|
||||
(if (ex-info? e)
|
||||
(let [d (ex-data e)]
|
||||
(if (= :reader-exception (:type d))
|
||||
(throw e)
|
||||
(throw (ex-info (.-message e)
|
||||
(merge {:type :reader-exception}
|
||||
d
|
||||
(if (indexing-reader? reader)
|
||||
{:line (get-line-number reader)
|
||||
:column (get-column-number reader)
|
||||
:file (get-file-name reader)}))
|
||||
e))))
|
||||
(throw (ex-info (.-message e)
|
||||
(merge {:type :reader-exception}
|
||||
(if (indexing-reader? reader)
|
||||
{:line (get-line-number reader)
|
||||
:column (get-column-number reader)
|
||||
:file (get-file-name reader)}))
|
||||
e)))))))
|
||||
|
||||
(defn read-string
|
||||
"Reads one object from the string s.
|
||||
Returns nil when s is nil or empty.
|
||||
|
||||
Reads data in the edn format (subset of Clojure data):
|
||||
http://edn-format.org
|
||||
|
||||
opts is a map as per cljs.tools.reader.edn/read"
|
||||
([s] (read-string {:eof nil} s))
|
||||
([opts s]
|
||||
(when (and s (not= s ""))
|
||||
(read opts (string-push-back-reader s)))))
|
||||
Executable
+934
@@ -0,0 +1,934 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.tools.reader.edn');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.tools.reader.impl.errors');
|
||||
goog.require('cljs.tools.reader.reader_types');
|
||||
goog.require('cljs.tools.reader.impl.utils');
|
||||
goog.require('cljs.tools.reader.impl.commons');
|
||||
goog.require('cljs.tools.reader');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.string.StringBuffer');
|
||||
|
||||
|
||||
cljs.tools.reader.edn.macro_terminating_QMARK_ = (function cljs$tools$reader$edn$macro_terminating_QMARK_(ch){
|
||||
var and__5043__auto__ = (!(("#" === ch)));
|
||||
if(and__5043__auto__){
|
||||
var and__5043__auto____$1 = (!(("'" === ch)));
|
||||
if(and__5043__auto____$1){
|
||||
var and__5043__auto____$2 = (!((":" === ch)));
|
||||
if(and__5043__auto____$2){
|
||||
return (cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1 ? cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1(ch) : cljs.tools.reader.edn.macros.call(null,ch));
|
||||
} else {
|
||||
return and__5043__auto____$2;
|
||||
}
|
||||
} else {
|
||||
return and__5043__auto____$1;
|
||||
}
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.not_constituent_QMARK_ = (function cljs$tools$reader$edn$not_constituent_QMARK_(ch){
|
||||
return ((("@" === ch)) || (((("`" === ch)) || (("~" === ch)))));
|
||||
});
|
||||
cljs.tools.reader.edn.read_token = (function cljs$tools$reader$edn$read_token(var_args){
|
||||
var G__5893 = arguments.length;
|
||||
switch (G__5893) {
|
||||
case 3:
|
||||
return cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
case 4:
|
||||
return cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$4((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$3 = (function (rdr,kind,initch){
|
||||
return cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$4(rdr,kind,initch,true);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$4 = (function (rdr,kind,initch,validate_leading_QMARK_){
|
||||
if(cljs.core.not(initch)){
|
||||
return cljs.tools.reader.impl.errors.throw_eof_at_start(rdr,kind);
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = validate_leading_QMARK_;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return cljs.tools.reader.edn.not_constituent_QMARK_(initch);
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
return cljs.tools.reader.impl.errors.throw_bad_char(rdr,kind,initch);
|
||||
} else {
|
||||
var sb = (new goog.string.StringBuffer());
|
||||
var ch = (function (){
|
||||
cljs.tools.reader.reader_types.unread(rdr,initch);
|
||||
|
||||
return initch;
|
||||
})()
|
||||
;
|
||||
while(true){
|
||||
if(((cljs.tools.reader.impl.utils.whitespace_QMARK_(ch)) || (((cljs.tools.reader.edn.macro_terminating_QMARK_(ch)) || ((ch == null)))))){
|
||||
return cljs.core.str.cljs$core$IFn$_invoke$arity$1(sb);
|
||||
} else {
|
||||
if(cljs.tools.reader.edn.not_constituent_QMARK_(ch)){
|
||||
return cljs.tools.reader.impl.errors.throw_bad_char(rdr,kind,ch);
|
||||
} else {
|
||||
var G__5896 = (function (){var G__5894 = sb;
|
||||
G__5894.append(cljs.tools.reader.reader_types.read_char(rdr));
|
||||
|
||||
return G__5894;
|
||||
})();
|
||||
var G__5897 = cljs.tools.reader.reader_types.peek_char(rdr);
|
||||
sb = G__5896;
|
||||
ch = G__5897;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read_token.cljs$lang$maxFixedArity = 4);
|
||||
|
||||
cljs.tools.reader.edn.read_dispatch = (function cljs$tools$reader$edn$read_dispatch(rdr,_,opts){
|
||||
var temp__4655__auto__ = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var ch = temp__4655__auto__;
|
||||
var temp__4655__auto____$1 = (cljs.tools.reader.edn.dispatch_macros.cljs$core$IFn$_invoke$arity$1 ? cljs.tools.reader.edn.dispatch_macros.cljs$core$IFn$_invoke$arity$1(ch) : cljs.tools.reader.edn.dispatch_macros.call(null,ch));
|
||||
if(cljs.core.truth_(temp__4655__auto____$1)){
|
||||
var dm = temp__4655__auto____$1;
|
||||
return (dm.cljs$core$IFn$_invoke$arity$3 ? dm.cljs$core$IFn$_invoke$arity$3(rdr,ch,opts) : dm.call(null,rdr,ch,opts));
|
||||
} else {
|
||||
var G__5898 = (function (){var G__5901 = rdr;
|
||||
cljs.tools.reader.reader_types.unread(G__5901,ch);
|
||||
|
||||
return G__5901;
|
||||
})();
|
||||
var G__5899 = ch;
|
||||
var G__5900 = opts;
|
||||
return (cljs.tools.reader.edn.read_tagged.cljs$core$IFn$_invoke$arity$3 ? cljs.tools.reader.edn.read_tagged.cljs$core$IFn$_invoke$arity$3(G__5898,G__5899,G__5900) : cljs.tools.reader.edn.read_tagged.call(null,G__5898,G__5899,G__5900));
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_eof_at_dispatch(rdr);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_unmatched_delimiter = (function cljs$tools$reader$edn$read_unmatched_delimiter(rdr,ch,opts){
|
||||
return cljs.tools.reader.impl.errors.throw_unmatch_delimiter(rdr,ch);
|
||||
});
|
||||
cljs.tools.reader.edn.read_unicode_char = (function cljs$tools$reader$edn$read_unicode_char(var_args){
|
||||
var G__5903 = arguments.length;
|
||||
switch (G__5903) {
|
||||
case 4:
|
||||
return cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$4((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]));
|
||||
|
||||
break;
|
||||
case 5:
|
||||
return cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$5((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]),(arguments[(4)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$4 = (function (token,offset,length,base){
|
||||
var l = (offset + length);
|
||||
if((cljs.core.count(token) === l)){
|
||||
} else {
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_literal(null,token);
|
||||
}
|
||||
|
||||
var i = offset;
|
||||
var uc = (0);
|
||||
while(true){
|
||||
if((i === l)){
|
||||
return String.fromCharCode(uc);
|
||||
} else {
|
||||
var d = cljs.tools.reader.impl.utils.char_code(cljs.core.nth.cljs$core$IFn$_invoke$arity$2(token,i),base);
|
||||
if((d === (-1))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_unicode_digit_in_token(null,cljs.core.nth.cljs$core$IFn$_invoke$arity$2(token,i),token);
|
||||
} else {
|
||||
var G__5905 = (i + (1));
|
||||
var G__5906 = (d + (uc * base));
|
||||
i = G__5905;
|
||||
uc = G__5906;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$5 = (function (rdr,initch,base,length,exact_QMARK_){
|
||||
var i = (1);
|
||||
var uc = cljs.tools.reader.impl.utils.char_code(initch,base);
|
||||
while(true){
|
||||
if((uc === (-1))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_unicode_digit(rdr,initch);
|
||||
} else {
|
||||
if((!((i === length)))){
|
||||
var ch = cljs.tools.reader.reader_types.peek_char(rdr);
|
||||
if(cljs.core.truth_((function (){var or__5045__auto__ = cljs.tools.reader.impl.utils.whitespace_QMARK_(ch);
|
||||
if(or__5045__auto__){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
var or__5045__auto____$1 = (cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1 ? cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1(ch) : cljs.tools.reader.edn.macros.call(null,ch));
|
||||
if(cljs.core.truth_(or__5045__auto____$1)){
|
||||
return or__5045__auto____$1;
|
||||
} else {
|
||||
return (ch == null);
|
||||
}
|
||||
}
|
||||
})())){
|
||||
if(cljs.core.truth_(exact_QMARK_)){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_unicode_len(rdr,i,length);
|
||||
} else {
|
||||
return String.fromCharCode(uc);
|
||||
}
|
||||
} else {
|
||||
var d = cljs.tools.reader.impl.utils.char_code(ch,base);
|
||||
cljs.tools.reader.reader_types.read_char(rdr);
|
||||
|
||||
if((d === (-1))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_unicode_digit(rdr,ch);
|
||||
} else {
|
||||
var G__5907 = (i + (1));
|
||||
var G__5908 = (d + (uc * base));
|
||||
i = G__5907;
|
||||
uc = G__5908;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return String.fromCharCode(uc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read_unicode_char.cljs$lang$maxFixedArity = 5);
|
||||
|
||||
cljs.tools.reader.edn.upper_limit = "\uD7FF".charCodeAt((0));
|
||||
cljs.tools.reader.edn.lower_limit = "\uE000".charCodeAt((0));
|
||||
cljs.tools.reader.edn.read_char_STAR_ = (function cljs$tools$reader$edn$read_char_STAR_(rdr,backslash,opts){
|
||||
var ch = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
if((!((ch == null)))){
|
||||
var token = ((((cljs.tools.reader.edn.macro_terminating_QMARK_(ch)) || (((cljs.tools.reader.edn.not_constituent_QMARK_(ch)) || (cljs.tools.reader.impl.utils.whitespace_QMARK_(ch))))))?cljs.core.str.cljs$core$IFn$_invoke$arity$1(ch):cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$4(rdr,cljs.core.cst$kw$character,ch,false));
|
||||
var token_len = ((token).length);
|
||||
if(((1) === token_len)){
|
||||
return cljs.core.nth.cljs$core$IFn$_invoke$arity$2(token,(0));
|
||||
} else {
|
||||
if((token === "newline")){
|
||||
return "\n";
|
||||
} else {
|
||||
if((token === "space")){
|
||||
return " ";
|
||||
} else {
|
||||
if((token === "tab")){
|
||||
return "\t";
|
||||
} else {
|
||||
if((token === "backspace")){
|
||||
return "\b";
|
||||
} else {
|
||||
if((token === "formfeed")){
|
||||
return "\f";
|
||||
} else {
|
||||
if((token === "return")){
|
||||
return "\r";
|
||||
} else {
|
||||
if(goog.string.startsWith(token,"u")){
|
||||
var c = cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$4(token,(1),(4),(16));
|
||||
var ic = c.charCodeAt();
|
||||
if((((ic > cljs.tools.reader.edn.upper_limit)) && ((ic < cljs.tools.reader.edn.lower_limit)))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_character_literal(rdr,ic.toString((16)));
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
} else {
|
||||
if(goog.string.startsWith(token,"o")){
|
||||
var len = (token_len - (1));
|
||||
if((len > (3))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_octal_len(rdr,token);
|
||||
} else {
|
||||
var uc = cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$4(token,(1),len,(8));
|
||||
if(((uc | (0)) > (255))){
|
||||
return cljs.tools.reader.impl.errors.throw_bad_octal_number(rdr);
|
||||
} else {
|
||||
return uc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_unsupported_character(rdr,token);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_eof_in_character(rdr);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.starting_line_col_info = (function cljs$tools$reader$edn$starting_line_col_info(rdr){
|
||||
if(cljs.tools.reader.reader_types.indexing_reader_QMARK_(rdr)){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.tools.reader.reader_types.get_line_number(rdr),(((cljs.tools.reader.reader_types.get_column_number(rdr) | (0)) - (1)) | (0))], null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_delimited = (function cljs$tools$reader$edn$read_delimited(kind,delim,rdr,opts){
|
||||
var vec__5909 = cljs.tools.reader.edn.starting_line_col_info(rdr);
|
||||
var start_line = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5909,(0),null);
|
||||
var start_column = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5909,(1),null);
|
||||
var delim__$1 = cljs.tools.reader.impl.utils.char$(delim);
|
||||
var a = cljs.core.transient$(cljs.core.PersistentVector.EMPTY);
|
||||
while(true){
|
||||
var ch = cljs.tools.reader.impl.commons.read_past(cljs.tools.reader.impl.utils.whitespace_QMARK_,rdr);
|
||||
if(cljs.core.truth_(ch)){
|
||||
} else {
|
||||
cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$core$IFn$_invoke$arity$5(rdr,kind,start_line,start_column,cljs.core.count(a));
|
||||
}
|
||||
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(delim__$1,cljs.tools.reader.impl.utils.char$(ch))){
|
||||
return cljs.core.persistent_BANG_(a);
|
||||
} else {
|
||||
var temp__4655__auto__ = (cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1 ? cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1(ch) : cljs.tools.reader.edn.macros.call(null,ch));
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var macrofn = temp__4655__auto__;
|
||||
var mret = (macrofn.cljs$core$IFn$_invoke$arity$3 ? macrofn.cljs$core$IFn$_invoke$arity$3(rdr,ch,opts) : macrofn.call(null,rdr,ch,opts));
|
||||
var G__5917 = (((!((mret === rdr))))?cljs.core.conj_BANG_.cljs$core$IFn$_invoke$arity$2(a,mret):a);
|
||||
a = G__5917;
|
||||
continue;
|
||||
} else {
|
||||
var o = (function (){var G__5912 = (function (){var G__5916 = rdr;
|
||||
cljs.tools.reader.reader_types.unread(G__5916,ch);
|
||||
|
||||
return G__5916;
|
||||
})();
|
||||
var G__5913 = true;
|
||||
var G__5914 = null;
|
||||
var G__5915 = opts;
|
||||
return (cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(G__5912,G__5913,G__5914,G__5915) : cljs.tools.reader.edn.read.call(null,G__5912,G__5913,G__5914,G__5915));
|
||||
})();
|
||||
var G__5918 = (((!((o === rdr))))?cljs.core.conj_BANG_.cljs$core$IFn$_invoke$arity$2(a,o):a);
|
||||
a = G__5918;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_list = (function cljs$tools$reader$edn$read_list(rdr,_,opts){
|
||||
var the_list = cljs.tools.reader.edn.read_delimited(cljs.core.cst$kw$list,")",rdr,opts);
|
||||
if(cljs.core.empty_QMARK_(the_list)){
|
||||
return cljs.core.List.EMPTY;
|
||||
} else {
|
||||
return cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.list,the_list);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_vector = (function cljs$tools$reader$edn$read_vector(rdr,_,opts){
|
||||
return cljs.tools.reader.edn.read_delimited(cljs.core.cst$kw$vector,"]",rdr,opts);
|
||||
});
|
||||
cljs.tools.reader.edn.read_map = (function cljs$tools$reader$edn$read_map(rdr,_,opts){
|
||||
var vec__5919 = cljs.tools.reader.edn.starting_line_col_info(rdr);
|
||||
var start_line = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5919,(0),null);
|
||||
var start_column = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5919,(1),null);
|
||||
var the_map = cljs.tools.reader.edn.read_delimited(cljs.core.cst$kw$map,"}",rdr,opts);
|
||||
var map_count = cljs.core.count(the_map);
|
||||
var ks = cljs.core.take_nth.cljs$core$IFn$_invoke$arity$2((2),the_map);
|
||||
var key_set = cljs.core.set(ks);
|
||||
if(cljs.core.odd_QMARK_(map_count)){
|
||||
cljs.tools.reader.impl.errors.throw_odd_map(rdr,start_line,start_column,the_map);
|
||||
} else {
|
||||
}
|
||||
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.count(key_set),cljs.core.count(ks))){
|
||||
} else {
|
||||
cljs.tools.reader.impl.errors.throw_dup_keys(rdr,cljs.core.cst$kw$map,ks);
|
||||
}
|
||||
|
||||
if((map_count <= ((2) * cljs.core.PersistentArrayMap.HASHMAP_THRESHOLD))){
|
||||
return cljs.core.PersistentArrayMap.fromArray(cljs.core.to_array(the_map),true,true);
|
||||
} else {
|
||||
return cljs.core.PersistentHashMap.fromArray(cljs.core.to_array(the_map),true);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_number = (function cljs$tools$reader$edn$read_number(rdr,initch,opts){
|
||||
var sb = (function (){var G__5922 = (new goog.string.StringBuffer());
|
||||
G__5922.append(initch);
|
||||
|
||||
return G__5922;
|
||||
})();
|
||||
var ch = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
while(true){
|
||||
if(cljs.core.truth_((function (){var or__5045__auto__ = cljs.tools.reader.impl.utils.whitespace_QMARK_(ch);
|
||||
if(or__5045__auto__){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
var or__5045__auto____$1 = (cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1 ? cljs.tools.reader.edn.macros.cljs$core$IFn$_invoke$arity$1(ch) : cljs.tools.reader.edn.macros.call(null,ch));
|
||||
if(cljs.core.truth_(or__5045__auto____$1)){
|
||||
return or__5045__auto____$1;
|
||||
} else {
|
||||
return (ch == null);
|
||||
}
|
||||
}
|
||||
})())){
|
||||
var s = cljs.core.str.cljs$core$IFn$_invoke$arity$1(sb);
|
||||
cljs.tools.reader.reader_types.unread(rdr,ch);
|
||||
|
||||
var or__5045__auto__ = cljs.tools.reader.impl.commons.match_number(s);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_number(rdr,s);
|
||||
}
|
||||
} else {
|
||||
var G__5924 = (function (){var G__5923 = sb;
|
||||
G__5923.append(ch);
|
||||
|
||||
return G__5923;
|
||||
})();
|
||||
var G__5925 = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
sb = G__5924;
|
||||
ch = G__5925;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.escape_char = (function cljs$tools$reader$edn$escape_char(sb,rdr){
|
||||
var ch = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
var G__5926 = ch;
|
||||
switch (G__5926) {
|
||||
case "t":
|
||||
return "\t";
|
||||
|
||||
break;
|
||||
case "r":
|
||||
return "\r";
|
||||
|
||||
break;
|
||||
case "n":
|
||||
return "\n";
|
||||
|
||||
break;
|
||||
case "\\":
|
||||
return "\\";
|
||||
|
||||
break;
|
||||
case "\"":
|
||||
return "\"";
|
||||
|
||||
break;
|
||||
case "b":
|
||||
return "\b";
|
||||
|
||||
break;
|
||||
case "f":
|
||||
return "\f";
|
||||
|
||||
break;
|
||||
case "u":
|
||||
var ch__$1 = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
if(((-1) === parseInt((ch__$1 | (0)),(16)))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid_unicode_escape(rdr,ch__$1);
|
||||
} else {
|
||||
return cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$5(rdr,ch__$1,(16),(4),true);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if(cljs.tools.reader.impl.utils.numeric_QMARK_(ch)){
|
||||
var ch__$1 = cljs.tools.reader.edn.read_unicode_char.cljs$core$IFn$_invoke$arity$5(rdr,ch,(8),(3),false);
|
||||
if(((ch__$1 | (0)) > (255))){
|
||||
return cljs.tools.reader.impl.errors.throw_bad_octal_number(rdr);
|
||||
} else {
|
||||
return ch__$1;
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_bad_escape_char(rdr,ch);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_string_STAR_ = (function cljs$tools$reader$edn$read_string_STAR_(rdr,_,opts){
|
||||
var sb = (new goog.string.StringBuffer());
|
||||
var ch = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
while(true){
|
||||
var G__5928 = ch;
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(null,G__5928)){
|
||||
return cljs.tools.reader.impl.errors.throw_eof_reading.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.cst$kw$string,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["\"",sb], 0));
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2("\\",G__5928)){
|
||||
var G__5931 = (function (){var G__5929 = sb;
|
||||
G__5929.append(cljs.tools.reader.edn.escape_char(sb,rdr));
|
||||
|
||||
return G__5929;
|
||||
})();
|
||||
var G__5932 = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
sb = G__5931;
|
||||
ch = G__5932;
|
||||
continue;
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2("\"",G__5928)){
|
||||
return cljs.core.str.cljs$core$IFn$_invoke$arity$1(sb);
|
||||
} else {
|
||||
var G__5933 = (function (){var G__5930 = sb;
|
||||
G__5930.append(ch);
|
||||
|
||||
return G__5930;
|
||||
})();
|
||||
var G__5934 = cljs.tools.reader.reader_types.read_char(rdr);
|
||||
sb = G__5933;
|
||||
ch = G__5934;
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_symbol = (function cljs$tools$reader$edn$read_symbol(rdr,initch){
|
||||
var temp__4657__auto__ = cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$3(rdr,cljs.core.cst$kw$symbol,initch);
|
||||
if(cljs.core.truth_(temp__4657__auto__)){
|
||||
var token = temp__4657__auto__;
|
||||
var G__5935 = token;
|
||||
switch (G__5935) {
|
||||
case "nil":
|
||||
return null;
|
||||
|
||||
break;
|
||||
case "true":
|
||||
return true;
|
||||
|
||||
break;
|
||||
case "false":
|
||||
return false;
|
||||
|
||||
break;
|
||||
case "/":
|
||||
return cljs.core.cst$sym$_SLASH_;
|
||||
|
||||
break;
|
||||
default:
|
||||
var or__5045__auto__ = (function (){var temp__4657__auto____$1 = cljs.tools.reader.impl.commons.parse_symbol(token);
|
||||
if(cljs.core.truth_(temp__4657__auto____$1)){
|
||||
var p = temp__4657__auto____$1;
|
||||
return cljs.core.symbol.cljs$core$IFn$_invoke$arity$2((p.cljs$core$IFn$_invoke$arity$1 ? p.cljs$core$IFn$_invoke$arity$1((0)) : p.call(null,(0))),(p.cljs$core$IFn$_invoke$arity$1 ? p.cljs$core$IFn$_invoke$arity$1((1)) : p.call(null,(1))));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_invalid(rdr,cljs.core.cst$kw$symbol,token);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_keyword = (function cljs$tools$reader$edn$read_keyword(reader,initch,opts){
|
||||
var ch = cljs.tools.reader.reader_types.read_char(reader);
|
||||
if((!(cljs.tools.reader.impl.utils.whitespace_QMARK_(ch)))){
|
||||
var token = cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$3(reader,cljs.core.cst$kw$keyword,ch);
|
||||
var s = cljs.tools.reader.impl.commons.parse_symbol(token);
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = s;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return ((-1) === token.indexOf("::"));
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
var ns = (s.cljs$core$IFn$_invoke$arity$1 ? s.cljs$core$IFn$_invoke$arity$1((0)) : s.call(null,(0)));
|
||||
var name = (s.cljs$core$IFn$_invoke$arity$1 ? s.cljs$core$IFn$_invoke$arity$1((1)) : s.call(null,(1)));
|
||||
if((":" === cljs.core.nth.cljs$core$IFn$_invoke$arity$2(token,(0)))){
|
||||
return cljs.tools.reader.impl.errors.throw_invalid(reader,cljs.core.cst$kw$keyword,[":",cljs.core.str.cljs$core$IFn$_invoke$arity$1(token)].join(''));
|
||||
} else {
|
||||
return cljs.core.keyword.cljs$core$IFn$_invoke$arity$2(ns,name);
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_invalid(reader,cljs.core.cst$kw$keyword,[":",cljs.core.str.cljs$core$IFn$_invoke$arity$1(token)].join(''));
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_single_colon(reader);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.wrapping_reader = (function cljs$tools$reader$edn$wrapping_reader(sym){
|
||||
return (function (rdr,_,opts){
|
||||
return (new cljs.core.List(null,sym,(new cljs.core.List(null,(cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(rdr,true,null,opts) : cljs.tools.reader.edn.read.call(null,rdr,true,null,opts)),null,(1),null)),(2),null));
|
||||
});
|
||||
});
|
||||
cljs.tools.reader.edn.read_meta = (function cljs$tools$reader$edn$read_meta(rdr,_,opts){
|
||||
var m = cljs.tools.reader.impl.utils.desugar_meta((cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(rdr,true,null,opts) : cljs.tools.reader.edn.read.call(null,rdr,true,null,opts)));
|
||||
if(cljs.core.map_QMARK_(m)){
|
||||
} else {
|
||||
cljs.tools.reader.impl.errors.throw_bad_metadata(rdr,m);
|
||||
}
|
||||
|
||||
var o = (cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(rdr,true,null,opts) : cljs.tools.reader.edn.read.call(null,rdr,true,null,opts));
|
||||
if((((!((o == null))))?(((((o.cljs$lang$protocol_mask$partition0$ & (131072))) || ((cljs.core.PROTOCOL_SENTINEL === o.cljs$core$IMeta$))))?true:false):false)){
|
||||
return cljs.core.with_meta(o,cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.meta(o),m], 0)));
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_bad_metadata_target(rdr,o);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_set = (function cljs$tools$reader$edn$read_set(rdr,_,opts){
|
||||
var coll = cljs.tools.reader.edn.read_delimited(cljs.core.cst$kw$set,"}",rdr,opts);
|
||||
var the_set = cljs.core.set(coll);
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.count(coll),cljs.core.count(the_set))){
|
||||
} else {
|
||||
cljs.tools.reader.impl.errors.throw_dup_keys(rdr,cljs.core.cst$kw$set,coll);
|
||||
}
|
||||
|
||||
return the_set;
|
||||
});
|
||||
cljs.tools.reader.edn.read_discard = (function cljs$tools$reader$edn$read_discard(rdr,_,opts){
|
||||
var G__5938 = rdr;
|
||||
(cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(G__5938,true,null,true) : cljs.tools.reader.edn.read.call(null,G__5938,true,null,true));
|
||||
|
||||
return G__5938;
|
||||
});
|
||||
cljs.tools.reader.edn.read_namespaced_map = (function cljs$tools$reader$edn$read_namespaced_map(rdr,_,opts){
|
||||
var token = cljs.tools.reader.edn.read_token.cljs$core$IFn$_invoke$arity$3(rdr,cljs.core.cst$kw$namespaced_DASH_map,cljs.tools.reader.reader_types.read_char(rdr));
|
||||
var temp__4655__auto__ = (function (){var G__5939 = token;
|
||||
var G__5939__$1 = (((G__5939 == null))?null:cljs.tools.reader.impl.commons.parse_symbol(G__5939));
|
||||
if((G__5939__$1 == null)){
|
||||
return null;
|
||||
} else {
|
||||
return cljs.tools.reader.impl.utils.second_SINGLEQUOTE_(G__5939__$1);
|
||||
}
|
||||
})();
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var ns = temp__4655__auto__;
|
||||
var ch = cljs.tools.reader.impl.commons.read_past(cljs.tools.reader.impl.utils.whitespace_QMARK_,rdr);
|
||||
if((ch === "{")){
|
||||
var items = cljs.tools.reader.edn.read_delimited(cljs.core.cst$kw$namespaced_DASH_map,"}",rdr,opts);
|
||||
if(cljs.core.odd_QMARK_(cljs.core.count(items))){
|
||||
cljs.tools.reader.impl.errors.throw_odd_map(rdr,null,null,items);
|
||||
} else {
|
||||
}
|
||||
|
||||
var keys = cljs.tools.reader.impl.utils.namespace_keys(cljs.core.str.cljs$core$IFn$_invoke$arity$1(ns),cljs.core.take_nth.cljs$core$IFn$_invoke$arity$2((2),items));
|
||||
var vals = cljs.core.take_nth.cljs$core$IFn$_invoke$arity$2((2),cljs.core.rest(items));
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.count(cljs.core.set(keys)),cljs.core.count(keys))){
|
||||
} else {
|
||||
cljs.tools.reader.impl.errors.throw_dup_keys(rdr,cljs.core.cst$kw$namespaced_DASH_map,keys);
|
||||
}
|
||||
|
||||
return cljs.core.zipmap(keys,vals);
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_ns_map_no_map(rdr,token);
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_bad_ns(rdr,token);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_symbolic_value = (function cljs$tools$reader$edn$read_symbolic_value(rdr,_,opts){
|
||||
var sym = (cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(rdr,true,null,opts) : cljs.tools.reader.edn.read.call(null,rdr,true,null,opts));
|
||||
var G__5940 = sym;
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.cst$sym$NaN,G__5940)){
|
||||
return Number.NaN;
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.cst$sym$_DASH_Inf,G__5940)){
|
||||
return Number.NEGATIVE_INFINITY;
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.cst$sym$Inf,G__5940)){
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([["Invalid token: ##",cljs.core.str.cljs$core$IFn$_invoke$arity$1(sym)].join('')], 0));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.macros = (function cljs$tools$reader$edn$macros(ch){
|
||||
var G__5941 = ch;
|
||||
switch (G__5941) {
|
||||
case "\"":
|
||||
return cljs.tools.reader.edn.read_string_STAR_;
|
||||
|
||||
break;
|
||||
case ":":
|
||||
return cljs.tools.reader.edn.read_keyword;
|
||||
|
||||
break;
|
||||
case ";":
|
||||
return cljs.tools.reader.impl.commons.read_comment;
|
||||
|
||||
break;
|
||||
case "^":
|
||||
return cljs.tools.reader.edn.read_meta;
|
||||
|
||||
break;
|
||||
case "(":
|
||||
return cljs.tools.reader.edn.read_list;
|
||||
|
||||
break;
|
||||
case ")":
|
||||
return cljs.tools.reader.edn.read_unmatched_delimiter;
|
||||
|
||||
break;
|
||||
case "[":
|
||||
return cljs.tools.reader.edn.read_vector;
|
||||
|
||||
break;
|
||||
case "]":
|
||||
return cljs.tools.reader.edn.read_unmatched_delimiter;
|
||||
|
||||
break;
|
||||
case "{":
|
||||
return cljs.tools.reader.edn.read_map;
|
||||
|
||||
break;
|
||||
case "}":
|
||||
return cljs.tools.reader.edn.read_unmatched_delimiter;
|
||||
|
||||
break;
|
||||
case "\\":
|
||||
return cljs.tools.reader.edn.read_char_STAR_;
|
||||
|
||||
break;
|
||||
case "#":
|
||||
return cljs.tools.reader.edn.read_dispatch;
|
||||
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.dispatch_macros = (function cljs$tools$reader$edn$dispatch_macros(ch){
|
||||
var G__5943 = ch;
|
||||
switch (G__5943) {
|
||||
case "^":
|
||||
return cljs.tools.reader.edn.read_meta;
|
||||
|
||||
break;
|
||||
case "{":
|
||||
return cljs.tools.reader.edn.read_set;
|
||||
|
||||
break;
|
||||
case "<":
|
||||
return cljs.tools.reader.impl.commons.throwing_reader("Unreadable form");
|
||||
|
||||
break;
|
||||
case "!":
|
||||
return cljs.tools.reader.impl.commons.read_comment;
|
||||
|
||||
break;
|
||||
case "_":
|
||||
return cljs.tools.reader.edn.read_discard;
|
||||
|
||||
break;
|
||||
case ":":
|
||||
return cljs.tools.reader.edn.read_namespaced_map;
|
||||
|
||||
break;
|
||||
case "#":
|
||||
return cljs.tools.reader.edn.read_symbolic_value;
|
||||
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.edn.read_tagged = (function cljs$tools$reader$edn$read_tagged(rdr,initch,opts){
|
||||
var tag = (cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(rdr,true,null,opts) : cljs.tools.reader.edn.read.call(null,rdr,true,null,opts));
|
||||
var object = (cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 ? cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(rdr,true,null,opts) : cljs.tools.reader.edn.read.call(null,rdr,true,null,opts));
|
||||
if((!((tag instanceof cljs.core.Symbol)))){
|
||||
cljs.tools.reader.impl.errors.throw_bad_reader_tag(rdr,"Reader tag must be a symbol");
|
||||
} else {
|
||||
}
|
||||
|
||||
var temp__4655__auto__ = (function (){var or__5045__auto__ = cljs.core.get.cljs$core$IFn$_invoke$arity$2(cljs.core.cst$kw$readers.cljs$core$IFn$_invoke$arity$1(opts),tag);
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return (cljs.tools.reader.default_data_readers.cljs$core$IFn$_invoke$arity$1 ? cljs.tools.reader.default_data_readers.cljs$core$IFn$_invoke$arity$1(tag) : cljs.tools.reader.default_data_readers.call(null,tag));
|
||||
}
|
||||
})();
|
||||
if(cljs.core.truth_(temp__4655__auto__)){
|
||||
var f = temp__4655__auto__;
|
||||
return (f.cljs$core$IFn$_invoke$arity$1 ? f.cljs$core$IFn$_invoke$arity$1(object) : f.call(null,object));
|
||||
} else {
|
||||
var temp__4655__auto____$1 = cljs.core.cst$kw$default.cljs$core$IFn$_invoke$arity$1(opts);
|
||||
if(cljs.core.truth_(temp__4655__auto____$1)){
|
||||
var d = temp__4655__auto____$1;
|
||||
return (d.cljs$core$IFn$_invoke$arity$2 ? d.cljs$core$IFn$_invoke$arity$2(tag,object) : d.call(null,tag,object));
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.throw_unknown_reader_tag(rdr,tag);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Reads the first object from an IPushbackReader.
|
||||
* Returns the object read. If EOF, throws if eof-error? is true otherwise returns eof.
|
||||
* If no reader is provided, *in* will be used.
|
||||
*
|
||||
* Reads data in the edn format (subset of Clojure data):
|
||||
* http://edn-format.org
|
||||
*
|
||||
* cljs.tools.reader.edn/read doesn't depend on dynamic Vars, all configuration
|
||||
* is done by passing an opt map.
|
||||
*
|
||||
* opts is a map that can include the following keys:
|
||||
* :eof - value to return on end-of-file. When not supplied, eof throws an exception.
|
||||
* :readers - a map of tag symbols to data-reader functions to be considered before default-data-readers.
|
||||
* When not supplied, only the default-data-readers will be used.
|
||||
* :default - A function of two args, that will, if present and no reader is found for a tag,
|
||||
* be called with the tag and the value.
|
||||
*/
|
||||
cljs.tools.reader.edn.read = (function cljs$tools$reader$edn$read(var_args){
|
||||
var G__5946 = arguments.length;
|
||||
switch (G__5946) {
|
||||
case 1:
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 4:
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$1 = (function (reader){
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,reader);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$2 = (function (p__5947,reader){
|
||||
var map__5948 = p__5947;
|
||||
var map__5948__$1 = cljs.core.__destructure_map(map__5948);
|
||||
var opts = map__5948__$1;
|
||||
var eof = cljs.core.get.cljs$core$IFn$_invoke$arity$2(map__5948__$1,cljs.core.cst$kw$eof);
|
||||
var eof_error_QMARK_ = (!(cljs.core.contains_QMARK_(opts,cljs.core.cst$kw$eof)));
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4(reader,eof_error_QMARK_,eof,opts);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$4 = (function (reader,eof_error_QMARK_,eof,opts){
|
||||
try{while(true){
|
||||
var ch = cljs.tools.reader.reader_types.read_char(reader);
|
||||
if(cljs.tools.reader.impl.utils.whitespace_QMARK_(ch)){
|
||||
continue;
|
||||
} else {
|
||||
if((ch == null)){
|
||||
if(cljs.core.truth_(eof_error_QMARK_)){
|
||||
return cljs.tools.reader.impl.errors.throw_eof_error(reader,null);
|
||||
} else {
|
||||
return eof;
|
||||
}
|
||||
} else {
|
||||
if(cljs.tools.reader.impl.commons.number_literal_QMARK_(reader,ch)){
|
||||
return cljs.tools.reader.edn.read_number(reader,ch,opts);
|
||||
} else {
|
||||
var f = cljs.tools.reader.edn.macros(ch);
|
||||
if(cljs.core.truth_(f)){
|
||||
var res = (f.cljs$core$IFn$_invoke$arity$3 ? f.cljs$core$IFn$_invoke$arity$3(reader,ch,opts) : f.call(null,reader,ch,opts));
|
||||
if((res === reader)){
|
||||
continue;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
return cljs.tools.reader.edn.read_symbol(reader,ch);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}catch (e5949){if((e5949 instanceof Error)){
|
||||
var e = e5949;
|
||||
if(cljs.tools.reader.impl.utils.ex_info_QMARK_(e)){
|
||||
var d = cljs.core.ex_data(e);
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.cst$kw$reader_DASH_exception,cljs.core.cst$kw$type.cljs$core$IFn$_invoke$arity$1(d))){
|
||||
throw e;
|
||||
} else {
|
||||
throw cljs.core.ex_info.cljs$core$IFn$_invoke$arity$3(e.message,cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$type,cljs.core.cst$kw$reader_DASH_exception], null),d,((cljs.tools.reader.reader_types.indexing_reader_QMARK_(reader))?new cljs.core.PersistentArrayMap(null, 3, [cljs.core.cst$kw$line,cljs.tools.reader.reader_types.get_line_number(reader),cljs.core.cst$kw$column,cljs.tools.reader.reader_types.get_column_number(reader),cljs.core.cst$kw$file,cljs.tools.reader.reader_types.get_file_name(reader)], null):null)], 0)),e);
|
||||
}
|
||||
} else {
|
||||
throw cljs.core.ex_info.cljs$core$IFn$_invoke$arity$3(e.message,cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$type,cljs.core.cst$kw$reader_DASH_exception], null),((cljs.tools.reader.reader_types.indexing_reader_QMARK_(reader))?new cljs.core.PersistentArrayMap(null, 3, [cljs.core.cst$kw$line,cljs.tools.reader.reader_types.get_line_number(reader),cljs.core.cst$kw$column,cljs.tools.reader.reader_types.get_column_number(reader),cljs.core.cst$kw$file,cljs.tools.reader.reader_types.get_file_name(reader)], null):null)], 0)),e);
|
||||
}
|
||||
} else {
|
||||
throw e5949;
|
||||
|
||||
}
|
||||
}}));
|
||||
|
||||
(cljs.tools.reader.edn.read.cljs$lang$maxFixedArity = 4);
|
||||
|
||||
/**
|
||||
* Reads one object from the string s.
|
||||
* Returns nil when s is nil or empty.
|
||||
*
|
||||
* Reads data in the edn format (subset of Clojure data):
|
||||
* http://edn-format.org
|
||||
*
|
||||
* opts is a map as per cljs.tools.reader.edn/read
|
||||
*/
|
||||
cljs.tools.reader.edn.read_string = (function cljs$tools$reader$edn$read_string(var_args){
|
||||
var G__5952 = arguments.length;
|
||||
switch (G__5952) {
|
||||
case 1:
|
||||
return cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$1 = (function (s){
|
||||
return cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$eof,null], null),s);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read_string.cljs$core$IFn$_invoke$arity$2 = (function (opts,s){
|
||||
if(cljs.core.truth_((function (){var and__5043__auto__ = s;
|
||||
if(cljs.core.truth_(and__5043__auto__)){
|
||||
return cljs.core.not_EQ_.cljs$core$IFn$_invoke$arity$2(s,"");
|
||||
} else {
|
||||
return and__5043__auto__;
|
||||
}
|
||||
})())){
|
||||
return cljs.tools.reader.edn.read.cljs$core$IFn$_invoke$arity$2(opts,cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$1(s));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.edn.read_string.cljs$lang$maxFixedArity = 2);
|
||||
|
||||
Executable
+131
@@ -0,0 +1,131 @@
|
||||
;; Copyright (c) Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.tools.reader.impl.commons
|
||||
(:refer-clojure :exclude [char])
|
||||
(:require
|
||||
[cljs.tools.reader.impl.errors :refer [reader-error]]
|
||||
[cljs.tools.reader.reader-types :refer [peek-char read-char]]
|
||||
[cljs.tools.reader.impl.utils :refer [numeric? newline? char]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn ^boolean number-literal?
|
||||
"Checks whether the reader is at the start of a number literal"
|
||||
[^not-native reader initch]
|
||||
(or (numeric? initch)
|
||||
(and (or (identical? \+ initch) (identical? \- initch))
|
||||
(numeric? (peek-char reader)))))
|
||||
|
||||
(defn read-past
|
||||
"Read until first character that doesn't match pred, returning
|
||||
char."
|
||||
[pred ^not-native rdr]
|
||||
(loop [ch (read-char rdr)]
|
||||
(if ^boolean (pred ch)
|
||||
(recur (read-char rdr))
|
||||
ch)))
|
||||
|
||||
(defn skip-line
|
||||
"Advances the reader to the end of a line. Returns the reader"
|
||||
[^not-native reader]
|
||||
(loop []
|
||||
(when-not (newline? (read-char reader))
|
||||
(recur)))
|
||||
reader)
|
||||
|
||||
(def int-pattern #"^([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)(N)?$")
|
||||
(def ratio-pattern #"([-+]?[0-9]+)/([0-9]+)")
|
||||
(def float-pattern #"([-+]?[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?")
|
||||
|
||||
(defn- match-int
|
||||
[s]
|
||||
(let [m (vec (re-find int-pattern s))]
|
||||
(if-not (nil? (m 2))
|
||||
0
|
||||
(let [^boolean negate? (identical? "-" (m 1))
|
||||
a (cond
|
||||
(not (nil? (m 3))) [(m 3) 10]
|
||||
(not (nil? (m 4))) [(m 4) 16]
|
||||
(not (nil? (m 5))) [(m 5) 8]
|
||||
(not (nil? (m 7))) [(m 7) (js/parseInt (m 6))]
|
||||
:else [nil nil])
|
||||
n (a 0)]
|
||||
(when-not (nil? n)
|
||||
(let [bn (js/parseInt n (a 1))
|
||||
bn (if negate? (* -1 bn) bn)]
|
||||
(when-not (js/isNaN bn)
|
||||
bn)))))))
|
||||
|
||||
(defn- match-ratio
|
||||
[s]
|
||||
(let [m (vec (re-find ratio-pattern s))
|
||||
numerator (m 1)
|
||||
denominator (m 2)
|
||||
numerator (if (re-find #"^\+" numerator)
|
||||
(subs numerator 1)
|
||||
numerator)]
|
||||
(/ (-> numerator js/parseInt) ;;; No ratio type in cljs
|
||||
(-> denominator js/parseInt)))); So will convert to js/Number
|
||||
|
||||
(defn- match-float
|
||||
[s]
|
||||
(let [m (vec (re-find float-pattern s))]
|
||||
(if-not (nil? (m 4)) ;; for BigDecimal "10.03M", as all parsed to js/Number
|
||||
(js/parseFloat (m 1))
|
||||
(js/parseFloat s))))
|
||||
|
||||
(defn ^boolean matches? [pattern s]
|
||||
(let [[match] (re-find pattern s)]
|
||||
(identical? match s)))
|
||||
|
||||
(defn match-number [s]
|
||||
(if (matches? int-pattern s)
|
||||
(match-int s)
|
||||
(if (matches? float-pattern s)
|
||||
(match-float s)
|
||||
(when (matches? ratio-pattern s)
|
||||
(match-ratio s)))))
|
||||
|
||||
(defn parse-symbol
|
||||
"Parses a string into a vector of the namespace and symbol"
|
||||
[token]
|
||||
(when-not (or (identical? "" token)
|
||||
(true? (.test #":$" token))
|
||||
(true? (.test #"^::" token)))
|
||||
(let [ns-idx (.indexOf token "/")
|
||||
ns (when (pos? ns-idx)
|
||||
(subs token 0 ns-idx))]
|
||||
(if-not (nil? ns)
|
||||
(let [ns-idx (inc ns-idx)]
|
||||
(when-not (== ns-idx (count token))
|
||||
(let [sym (subs token ns-idx)]
|
||||
(when (and (not (numeric? (nth sym 0)))
|
||||
(not (identical? "" sym))
|
||||
(false? (.test #":$" ns))
|
||||
(or (identical? sym "/")
|
||||
(== -1 (.indexOf sym "/"))))
|
||||
[ns sym]))))
|
||||
(when (or (identical? token "/")
|
||||
(== -1 (.indexOf token "/")))
|
||||
[nil token])))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; readers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn read-comment
|
||||
[rdr & _]
|
||||
(skip-line rdr))
|
||||
|
||||
(defn throwing-reader
|
||||
[msg]
|
||||
(fn [rdr & _]
|
||||
(reader-error rdr msg)))
|
||||
Executable
+192
@@ -0,0 +1,192 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.tools.reader.impl.commons');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.tools.reader.impl.errors');
|
||||
goog.require('cljs.tools.reader.reader_types');
|
||||
goog.require('cljs.tools.reader.impl.utils');
|
||||
/**
|
||||
* Checks whether the reader is at the start of a number literal
|
||||
*/
|
||||
cljs.tools.reader.impl.commons.number_literal_QMARK_ = (function cljs$tools$reader$impl$commons$number_literal_QMARK_(reader,initch){
|
||||
return ((cljs.tools.reader.impl.utils.numeric_QMARK_(initch)) || (((((("+" === initch)) || (("-" === initch)))) && (cljs.tools.reader.impl.utils.numeric_QMARK_(reader.cljs$tools$reader$reader_types$Reader$peek_char$arity$1(null))))));
|
||||
});
|
||||
/**
|
||||
* Read until first character that doesn't match pred, returning
|
||||
* char.
|
||||
*/
|
||||
cljs.tools.reader.impl.commons.read_past = (function cljs$tools$reader$impl$commons$read_past(pred,rdr){
|
||||
var ch = rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
while(true){
|
||||
if((pred.cljs$core$IFn$_invoke$arity$1 ? pred.cljs$core$IFn$_invoke$arity$1(ch) : pred.call(null,ch))){
|
||||
var G__5357 = rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
ch = G__5357;
|
||||
continue;
|
||||
} else {
|
||||
return ch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Advances the reader to the end of a line. Returns the reader
|
||||
*/
|
||||
cljs.tools.reader.impl.commons.skip_line = (function cljs$tools$reader$impl$commons$skip_line(reader){
|
||||
while(true){
|
||||
if(cljs.tools.reader.impl.utils.newline_QMARK_(reader.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null))){
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return reader;
|
||||
});
|
||||
cljs.tools.reader.impl.commons.int_pattern = /^([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)(N)?$/;
|
||||
cljs.tools.reader.impl.commons.ratio_pattern = /([-+]?[0-9]+)\/([0-9]+)/;
|
||||
cljs.tools.reader.impl.commons.float_pattern = /([-+]?[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?/;
|
||||
cljs.tools.reader.impl.commons.match_int = (function cljs$tools$reader$impl$commons$match_int(s){
|
||||
var m = cljs.core.vec(cljs.core.re_find(cljs.tools.reader.impl.commons.int_pattern,s));
|
||||
if((!(((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((2)) : m.call(null,(2))) == null)))){
|
||||
return (0);
|
||||
} else {
|
||||
var negate_QMARK_ = ("-" === (m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((1)) : m.call(null,(1))));
|
||||
var a = (((!(((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((3)) : m.call(null,(3))) == null))))?new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [(m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((3)) : m.call(null,(3))),(10)], null):(((!(((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((4)) : m.call(null,(4))) == null))))?new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [(m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((4)) : m.call(null,(4))),(16)], null):(((!(((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((5)) : m.call(null,(5))) == null))))?new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [(m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((5)) : m.call(null,(5))),(8)], null):(((!(((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((7)) : m.call(null,(7))) == null))))?new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [(m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((7)) : m.call(null,(7))),parseInt((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((6)) : m.call(null,(6))))], null):new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [null,null], null)
|
||||
))));
|
||||
var n = (a.cljs$core$IFn$_invoke$arity$1 ? a.cljs$core$IFn$_invoke$arity$1((0)) : a.call(null,(0)));
|
||||
if((n == null)){
|
||||
return null;
|
||||
} else {
|
||||
var bn = parseInt(n,(a.cljs$core$IFn$_invoke$arity$1 ? a.cljs$core$IFn$_invoke$arity$1((1)) : a.call(null,(1))));
|
||||
var bn__$1 = ((negate_QMARK_)?((-1) * bn):bn);
|
||||
if(cljs.core.truth_(isNaN(bn__$1))){
|
||||
return null;
|
||||
} else {
|
||||
return bn__$1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.impl.commons.match_ratio = (function cljs$tools$reader$impl$commons$match_ratio(s){
|
||||
var m = cljs.core.vec(cljs.core.re_find(cljs.tools.reader.impl.commons.ratio_pattern,s));
|
||||
var numerator = (m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((1)) : m.call(null,(1)));
|
||||
var denominator = (m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((2)) : m.call(null,(2)));
|
||||
var numerator__$1 = (cljs.core.truth_(cljs.core.re_find(/^\+/,numerator))?cljs.core.subs.cljs$core$IFn$_invoke$arity$2(numerator,(1)):numerator);
|
||||
return (parseInt(numerator__$1) / parseInt(denominator));
|
||||
});
|
||||
cljs.tools.reader.impl.commons.match_float = (function cljs$tools$reader$impl$commons$match_float(s){
|
||||
var m = cljs.core.vec(cljs.core.re_find(cljs.tools.reader.impl.commons.float_pattern,s));
|
||||
if((!(((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((4)) : m.call(null,(4))) == null)))){
|
||||
return parseFloat((m.cljs$core$IFn$_invoke$arity$1 ? m.cljs$core$IFn$_invoke$arity$1((1)) : m.call(null,(1))));
|
||||
} else {
|
||||
return parseFloat(s);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.impl.commons.matches_QMARK_ = (function cljs$tools$reader$impl$commons$matches_QMARK_(pattern,s){
|
||||
var vec__5358 = cljs.core.re_find(pattern,s);
|
||||
var match = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5358,(0),null);
|
||||
return (match === s);
|
||||
});
|
||||
cljs.tools.reader.impl.commons.match_number = (function cljs$tools$reader$impl$commons$match_number(s){
|
||||
if(cljs.tools.reader.impl.commons.matches_QMARK_(cljs.tools.reader.impl.commons.int_pattern,s)){
|
||||
return cljs.tools.reader.impl.commons.match_int(s);
|
||||
} else {
|
||||
if(cljs.tools.reader.impl.commons.matches_QMARK_(cljs.tools.reader.impl.commons.float_pattern,s)){
|
||||
return cljs.tools.reader.impl.commons.match_float(s);
|
||||
} else {
|
||||
if(cljs.tools.reader.impl.commons.matches_QMARK_(cljs.tools.reader.impl.commons.ratio_pattern,s)){
|
||||
return cljs.tools.reader.impl.commons.match_ratio(s);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Parses a string into a vector of the namespace and symbol
|
||||
*/
|
||||
cljs.tools.reader.impl.commons.parse_symbol = (function cljs$tools$reader$impl$commons$parse_symbol(token){
|
||||
if(((("" === token)) || (((/:$/.test(token) === true) || (/^::/.test(token) === true))))){
|
||||
return null;
|
||||
} else {
|
||||
var ns_idx = token.indexOf("/");
|
||||
var ns = (((ns_idx > (0)))?cljs.core.subs.cljs$core$IFn$_invoke$arity$3(token,(0),ns_idx):null);
|
||||
if((!((ns == null)))){
|
||||
var ns_idx__$1 = (ns_idx + (1));
|
||||
if((ns_idx__$1 === cljs.core.count(token))){
|
||||
return null;
|
||||
} else {
|
||||
var sym = cljs.core.subs.cljs$core$IFn$_invoke$arity$2(token,ns_idx__$1);
|
||||
if((((!(cljs.tools.reader.impl.utils.numeric_QMARK_(cljs.core.nth.cljs$core$IFn$_invoke$arity$2(sym,(0)))))) && ((((!(("" === sym)))) && (((/:$/.test(ns) === false) && ((((sym === "/")) || (((-1) === sym.indexOf("/"))))))))))){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [ns,sym], null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((((token === "/")) || (((-1) === token.indexOf("/"))))){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [null,token], null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.impl.commons.read_comment = (function cljs$tools$reader$impl$commons$read_comment(var_args){
|
||||
var args__5775__auto__ = [];
|
||||
var len__5769__auto___5363 = arguments.length;
|
||||
var i__5770__auto___5364 = (0);
|
||||
while(true){
|
||||
if((i__5770__auto___5364 < len__5769__auto___5363)){
|
||||
args__5775__auto__.push((arguments[i__5770__auto___5364]));
|
||||
|
||||
var G__5365 = (i__5770__auto___5364 + (1));
|
||||
i__5770__auto___5364 = G__5365;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var argseq__5776__auto__ = ((((1) < args__5775__auto__.length))?(new cljs.core.IndexedSeq(args__5775__auto__.slice((1)),(0),null)):null);
|
||||
return cljs.tools.reader.impl.commons.read_comment.cljs$core$IFn$_invoke$arity$variadic((arguments[(0)]),argseq__5776__auto__);
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.commons.read_comment.cljs$core$IFn$_invoke$arity$variadic = (function (rdr,_){
|
||||
return cljs.tools.reader.impl.commons.skip_line(rdr);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.commons.read_comment.cljs$lang$maxFixedArity = (1));
|
||||
|
||||
/** @this {Function} */
|
||||
(cljs.tools.reader.impl.commons.read_comment.cljs$lang$applyTo = (function (seq5361){
|
||||
var G__5362 = cljs.core.first(seq5361);
|
||||
var seq5361__$1 = cljs.core.next(seq5361);
|
||||
var self__5754__auto__ = this;
|
||||
return self__5754__auto__.cljs$core$IFn$_invoke$arity$variadic(G__5362,seq5361__$1);
|
||||
}));
|
||||
|
||||
cljs.tools.reader.impl.commons.throwing_reader = (function cljs$tools$reader$impl$commons$throwing_reader(msg){
|
||||
return (function() {
|
||||
var G__5366__delegate = function (rdr,_){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([msg], 0));
|
||||
};
|
||||
var G__5366 = function (rdr,var_args){
|
||||
var _ = null;
|
||||
if (arguments.length > 1) {
|
||||
var G__5367__i = 0, G__5367__a = new Array(arguments.length - 1);
|
||||
while (G__5367__i < G__5367__a.length) {G__5367__a[G__5367__i] = arguments[G__5367__i + 1]; ++G__5367__i;}
|
||||
_ = new cljs.core.IndexedSeq(G__5367__a,0,null);
|
||||
}
|
||||
return G__5366__delegate.call(this,rdr,_);};
|
||||
G__5366.cljs$lang$maxFixedArity = 1;
|
||||
G__5366.cljs$lang$applyTo = (function (arglist__5368){
|
||||
var rdr = cljs.core.first(arglist__5368);
|
||||
var _ = cljs.core.rest(arglist__5368);
|
||||
return G__5366__delegate(rdr,_);
|
||||
});
|
||||
G__5366.cljs$core$IFn$_invoke$arity$variadic = G__5366__delegate;
|
||||
return G__5366;
|
||||
})()
|
||||
;
|
||||
});
|
||||
Executable
+247
@@ -0,0 +1,247 @@
|
||||
;; Copyright (c) Russ Olsen, Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.tools.reader.impl.errors
|
||||
(:require [cljs.tools.reader.reader-types :as types]
|
||||
[clojure.string :as s]
|
||||
[cljs.tools.reader.impl.inspect :as i]))
|
||||
|
||||
(defn- ex-details
|
||||
[rdr ex-type]
|
||||
(let [details {:type :reader-exception
|
||||
:ex-kind ex-type}]
|
||||
(if (types/indexing-reader? rdr)
|
||||
(assoc
|
||||
details
|
||||
:file (types/get-file-name rdr)
|
||||
:line (types/get-line-number rdr)
|
||||
:col (types/get-column-number rdr))
|
||||
details)))
|
||||
|
||||
(defn- throw-ex
|
||||
"Throw an ex-info error."
|
||||
[rdr ex-type & msg]
|
||||
(let [details (ex-details rdr ex-type)
|
||||
file (:file details)
|
||||
line (:line details)
|
||||
col (:col details)
|
||||
msg1 (if file (str file " "))
|
||||
msg2 (if line (str "[line " line ", col " col "]"))
|
||||
msg3 (if (or msg1 msg2) " ")
|
||||
full-msg (apply str msg1 msg2 msg3 msg)]
|
||||
(throw (ex-info full-msg details))))
|
||||
|
||||
(defn reader-error
|
||||
"Throws an ExceptionInfo with the given message.
|
||||
If rdr is an IndexingReader, additional information about column and line number is provided"
|
||||
[rdr & msgs]
|
||||
(throw-ex rdr :reader-error (apply str msgs)))
|
||||
|
||||
(defn illegal-arg-error
|
||||
"Throws an ExceptionInfo with the given message.
|
||||
If rdr is an IndexingReader, additional information about column and line number is provided"
|
||||
[rdr & msgs]
|
||||
(throw-ex rdr :illegal-argument (apply str msgs)))
|
||||
|
||||
(defn eof-error
|
||||
"Throws an ExceptionInfo with the given message.
|
||||
If rdr is an IndexingReader, additional information about column and line number is provided"
|
||||
[rdr & msgs]
|
||||
(throw-ex rdr :eof (apply str msgs)))
|
||||
|
||||
(defn throw-eof-delimited
|
||||
([rdr kind column line] (throw-eof-delimited rdr kind line column nil))
|
||||
([rdr kind line column n]
|
||||
(eof-error
|
||||
rdr
|
||||
"Unexpected EOF while reading "
|
||||
(if n
|
||||
(str "item " n " of "))
|
||||
(name kind)
|
||||
(if line
|
||||
(str ", starting at line " line " and column " column))
|
||||
".")))
|
||||
|
||||
(defn throw-odd-map [rdr line col elements]
|
||||
(reader-error
|
||||
rdr
|
||||
"The map literal starting with "
|
||||
(i/inspect (first elements))
|
||||
(if line (str " on line " line " column " col))
|
||||
" contains "
|
||||
(count elements)
|
||||
" form(s). Map literals must contain an even number of forms."))
|
||||
|
||||
(defn throw-invalid-number [rdr token]
|
||||
(reader-error
|
||||
rdr
|
||||
"Invalid number: "
|
||||
token
|
||||
"."))
|
||||
|
||||
(defn throw-invalid-unicode-literal [rdr token]
|
||||
(throw
|
||||
(illegal-arg-error
|
||||
rdr
|
||||
"Invalid unicode literal: \\"
|
||||
token
|
||||
".")))
|
||||
|
||||
(defn throw-invalid-unicode-escape [rdr ch]
|
||||
(reader-error
|
||||
rdr
|
||||
"Invalid unicode escape: \\u"
|
||||
ch
|
||||
"."))
|
||||
|
||||
(defn throw-invalid [rdr kind token]
|
||||
(reader-error rdr "Invalid " (name kind) ": " token "."))
|
||||
|
||||
(defn throw-eof-at-start [rdr kind]
|
||||
(eof-error rdr "Unexpected EOF while reading start of " (name kind) "."))
|
||||
|
||||
(defn throw-bad-char [rdr kind ch]
|
||||
(reader-error rdr "Invalid character: " ch " found while reading " (name kind) "."))
|
||||
|
||||
(defn throw-eof-at-dispatch [rdr]
|
||||
(eof-error rdr "Unexpected EOF while reading dispatch character."))
|
||||
|
||||
(defn throw-unmatch-delimiter [rdr ch]
|
||||
(reader-error rdr "Unmatched delimiter " ch "."))
|
||||
|
||||
(defn throw-eof-reading [rdr kind & start]
|
||||
(let [init (case kind :regex "#\"" :string \")]
|
||||
(eof-error rdr "Unexpected EOF reading " (name kind) " starting " (apply str init start) ".")))
|
||||
|
||||
(defn throw-invalid-unicode-char[rdr token]
|
||||
(reader-error
|
||||
rdr
|
||||
"Invalid unicode character \\"
|
||||
token
|
||||
"."))
|
||||
|
||||
(defn throw-invalid-unicode-digit-in-token[rdr ch token]
|
||||
(illegal-arg-error
|
||||
rdr
|
||||
"Invalid digit "
|
||||
ch
|
||||
" in unicode character \\"
|
||||
token
|
||||
"."))
|
||||
|
||||
(defn throw-invalid-unicode-digit[rdr ch]
|
||||
(illegal-arg-error
|
||||
rdr
|
||||
"Invalid digit "
|
||||
ch
|
||||
" in unicode character."))
|
||||
|
||||
(defn throw-invalid-unicode-len[rdr actual expected]
|
||||
(illegal-arg-error
|
||||
rdr
|
||||
"Invalid unicode literal. Unicode literals should be "
|
||||
expected
|
||||
"characters long. "
|
||||
"Value supplied is "
|
||||
actual
|
||||
" characters long."))
|
||||
|
||||
(defn throw-invalid-character-literal[rdr token]
|
||||
(reader-error rdr "Invalid character literal \\u" token "."))
|
||||
|
||||
(defn throw-invalid-octal-len[rdr token]
|
||||
(reader-error
|
||||
rdr
|
||||
"Invalid octal escape sequence in a character literal: "
|
||||
token
|
||||
". Octal escape sequences must be 3 or fewer digits."))
|
||||
|
||||
(defn throw-bad-octal-number [rdr]
|
||||
(reader-error rdr "Octal escape sequence must be in range [0, 377]."))
|
||||
|
||||
(defn throw-unsupported-character[rdr token]
|
||||
(reader-error
|
||||
rdr
|
||||
"Unsupported character: "
|
||||
token
|
||||
"."))
|
||||
|
||||
(defn throw-eof-in-character [rdr]
|
||||
(eof-error
|
||||
rdr
|
||||
"Unexpected EOF while reading character."))
|
||||
|
||||
(defn throw-bad-escape-char [rdr ch]
|
||||
(reader-error rdr "Unsupported escape character: \\" ch "."))
|
||||
|
||||
(defn throw-single-colon [rdr]
|
||||
(reader-error rdr "A single colon is not a valid keyword."))
|
||||
|
||||
(defn throw-bad-metadata [rdr x]
|
||||
(reader-error
|
||||
rdr
|
||||
"Metadata cannot be "
|
||||
(i/inspect x)
|
||||
". Metadata must be a Symbol, Keyword, String or Map."))
|
||||
|
||||
(defn throw-bad-metadata-target [rdr target]
|
||||
(reader-error
|
||||
rdr
|
||||
"Metadata can not be applied to "
|
||||
(i/inspect target)
|
||||
". "
|
||||
"Metadata can only be applied to IMetas."))
|
||||
|
||||
(defn throw-feature-not-keyword [rdr feature]
|
||||
(reader-error
|
||||
rdr
|
||||
"Feature cannot be "
|
||||
(i/inspect feature)
|
||||
". Features must be keywords."))
|
||||
|
||||
(defn throw-ns-map-no-map [rdr ns-name]
|
||||
(reader-error rdr "Namespaced map with namespace " ns-name " does not specify a map."))
|
||||
|
||||
(defn throw-bad-ns [rdr ns-name]
|
||||
(reader-error rdr "Invalid value used as namespace in namespaced map: " ns-name "."))
|
||||
|
||||
(defn throw-bad-reader-tag [rdr tag]
|
||||
(reader-error
|
||||
rdr
|
||||
"Invalid reader tag: "
|
||||
(i/inspect tag)
|
||||
". Reader tags must be symbols."))
|
||||
|
||||
(defn throw-unknown-reader-tag [rdr tag]
|
||||
(reader-error
|
||||
rdr
|
||||
"No reader function for tag "
|
||||
(i/inspect tag)
|
||||
"."))
|
||||
|
||||
(defn- duplicate-keys-error [msg coll]
|
||||
(letfn [(duplicates [seq]
|
||||
(for [[id freq] (frequencies seq)
|
||||
:when (> freq 1)]
|
||||
id))]
|
||||
(let [dups (duplicates coll)]
|
||||
(apply str msg
|
||||
(when (> (count dups) 1) "s")
|
||||
": " (interpose ", " dups)))))
|
||||
|
||||
(defn throw-dup-keys [rdr kind ks]
|
||||
(reader-error
|
||||
rdr
|
||||
(duplicate-keys-error
|
||||
(str (s/capitalize (name kind)) " literal contains duplicate key")
|
||||
ks)))
|
||||
|
||||
(defn throw-eof-error [rdr line]
|
||||
(if line
|
||||
(eof-error rdr "EOF while reading, starting at line " line ".")
|
||||
(eof-error rdr "EOF while reading.")))
|
||||
Executable
+416
@@ -0,0 +1,416 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.tools.reader.impl.errors');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.tools.reader.reader_types');
|
||||
goog.require('clojure.string');
|
||||
goog.require('cljs.tools.reader.impl.inspect');
|
||||
cljs.tools.reader.impl.errors.ex_details = (function cljs$tools$reader$impl$errors$ex_details(rdr,ex_type){
|
||||
var details = new cljs.core.PersistentArrayMap(null, 2, [cljs.core.cst$kw$type,cljs.core.cst$kw$reader_DASH_exception,cljs.core.cst$kw$ex_DASH_kind,ex_type], null);
|
||||
if(cljs.tools.reader.reader_types.indexing_reader_QMARK_(rdr)){
|
||||
return cljs.core.assoc.cljs$core$IFn$_invoke$arity$variadic(details,cljs.core.cst$kw$file,cljs.tools.reader.reader_types.get_file_name(rdr),cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.cst$kw$line,cljs.tools.reader.reader_types.get_line_number(rdr),cljs.core.cst$kw$col,cljs.tools.reader.reader_types.get_column_number(rdr)], 0));
|
||||
} else {
|
||||
return details;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Throw an ex-info error.
|
||||
*/
|
||||
cljs.tools.reader.impl.errors.throw_ex = (function cljs$tools$reader$impl$errors$throw_ex(var_args){
|
||||
var args__5775__auto__ = [];
|
||||
var len__5769__auto___5303 = arguments.length;
|
||||
var i__5770__auto___5304 = (0);
|
||||
while(true){
|
||||
if((i__5770__auto___5304 < len__5769__auto___5303)){
|
||||
args__5775__auto__.push((arguments[i__5770__auto___5304]));
|
||||
|
||||
var G__5305 = (i__5770__auto___5304 + (1));
|
||||
i__5770__auto___5304 = G__5305;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var argseq__5776__auto__ = ((((2) < args__5775__auto__.length))?(new cljs.core.IndexedSeq(args__5775__auto__.slice((2)),(0),null)):null);
|
||||
return cljs.tools.reader.impl.errors.throw_ex.cljs$core$IFn$_invoke$arity$variadic((arguments[(0)]),(arguments[(1)]),argseq__5776__auto__);
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_ex.cljs$core$IFn$_invoke$arity$variadic = (function (rdr,ex_type,msg){
|
||||
var details = cljs.tools.reader.impl.errors.ex_details(rdr,ex_type);
|
||||
var file = cljs.core.cst$kw$file.cljs$core$IFn$_invoke$arity$1(details);
|
||||
var line = cljs.core.cst$kw$line.cljs$core$IFn$_invoke$arity$1(details);
|
||||
var col = cljs.core.cst$kw$col.cljs$core$IFn$_invoke$arity$1(details);
|
||||
var msg1 = (cljs.core.truth_(file)?[cljs.core.str.cljs$core$IFn$_invoke$arity$1(file)," "].join(''):null);
|
||||
var msg2 = (cljs.core.truth_(line)?["[line ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(line),", col ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(col),"]"].join(''):null);
|
||||
var msg3 = (cljs.core.truth_((function (){var or__5045__auto__ = msg1;
|
||||
if(cljs.core.truth_(or__5045__auto__)){
|
||||
return or__5045__auto__;
|
||||
} else {
|
||||
return msg2;
|
||||
}
|
||||
})())?" ":null);
|
||||
var full_msg = cljs.core.apply.cljs$core$IFn$_invoke$arity$5(cljs.core.str,msg1,msg2,msg3,msg);
|
||||
throw cljs.core.ex_info.cljs$core$IFn$_invoke$arity$2(full_msg,details);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_ex.cljs$lang$maxFixedArity = (2));
|
||||
|
||||
/** @this {Function} */
|
||||
(cljs.tools.reader.impl.errors.throw_ex.cljs$lang$applyTo = (function (seq5300){
|
||||
var G__5301 = cljs.core.first(seq5300);
|
||||
var seq5300__$1 = cljs.core.next(seq5300);
|
||||
var G__5302 = cljs.core.first(seq5300__$1);
|
||||
var seq5300__$2 = cljs.core.next(seq5300__$1);
|
||||
var self__5754__auto__ = this;
|
||||
return self__5754__auto__.cljs$core$IFn$_invoke$arity$variadic(G__5301,G__5302,seq5300__$2);
|
||||
}));
|
||||
|
||||
/**
|
||||
* Throws an ExceptionInfo with the given message.
|
||||
* If rdr is an IndexingReader, additional information about column and line number is provided
|
||||
*/
|
||||
cljs.tools.reader.impl.errors.reader_error = (function cljs$tools$reader$impl$errors$reader_error(var_args){
|
||||
var args__5775__auto__ = [];
|
||||
var len__5769__auto___5308 = arguments.length;
|
||||
var i__5770__auto___5309 = (0);
|
||||
while(true){
|
||||
if((i__5770__auto___5309 < len__5769__auto___5308)){
|
||||
args__5775__auto__.push((arguments[i__5770__auto___5309]));
|
||||
|
||||
var G__5310 = (i__5770__auto___5309 + (1));
|
||||
i__5770__auto___5309 = G__5310;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var argseq__5776__auto__ = ((((1) < args__5775__auto__.length))?(new cljs.core.IndexedSeq(args__5775__auto__.slice((1)),(0),null)):null);
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic((arguments[(0)]),argseq__5776__auto__);
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic = (function (rdr,msgs){
|
||||
return cljs.tools.reader.impl.errors.throw_ex.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.cst$kw$reader_DASH_error,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.str,msgs)], 0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.reader_error.cljs$lang$maxFixedArity = (1));
|
||||
|
||||
/** @this {Function} */
|
||||
(cljs.tools.reader.impl.errors.reader_error.cljs$lang$applyTo = (function (seq5306){
|
||||
var G__5307 = cljs.core.first(seq5306);
|
||||
var seq5306__$1 = cljs.core.next(seq5306);
|
||||
var self__5754__auto__ = this;
|
||||
return self__5754__auto__.cljs$core$IFn$_invoke$arity$variadic(G__5307,seq5306__$1);
|
||||
}));
|
||||
|
||||
/**
|
||||
* Throws an ExceptionInfo with the given message.
|
||||
* If rdr is an IndexingReader, additional information about column and line number is provided
|
||||
*/
|
||||
cljs.tools.reader.impl.errors.illegal_arg_error = (function cljs$tools$reader$impl$errors$illegal_arg_error(var_args){
|
||||
var args__5775__auto__ = [];
|
||||
var len__5769__auto___5313 = arguments.length;
|
||||
var i__5770__auto___5314 = (0);
|
||||
while(true){
|
||||
if((i__5770__auto___5314 < len__5769__auto___5313)){
|
||||
args__5775__auto__.push((arguments[i__5770__auto___5314]));
|
||||
|
||||
var G__5315 = (i__5770__auto___5314 + (1));
|
||||
i__5770__auto___5314 = G__5315;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var argseq__5776__auto__ = ((((1) < args__5775__auto__.length))?(new cljs.core.IndexedSeq(args__5775__auto__.slice((1)),(0),null)):null);
|
||||
return cljs.tools.reader.impl.errors.illegal_arg_error.cljs$core$IFn$_invoke$arity$variadic((arguments[(0)]),argseq__5776__auto__);
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.errors.illegal_arg_error.cljs$core$IFn$_invoke$arity$variadic = (function (rdr,msgs){
|
||||
return cljs.tools.reader.impl.errors.throw_ex.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.cst$kw$illegal_DASH_argument,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.str,msgs)], 0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.illegal_arg_error.cljs$lang$maxFixedArity = (1));
|
||||
|
||||
/** @this {Function} */
|
||||
(cljs.tools.reader.impl.errors.illegal_arg_error.cljs$lang$applyTo = (function (seq5311){
|
||||
var G__5312 = cljs.core.first(seq5311);
|
||||
var seq5311__$1 = cljs.core.next(seq5311);
|
||||
var self__5754__auto__ = this;
|
||||
return self__5754__auto__.cljs$core$IFn$_invoke$arity$variadic(G__5312,seq5311__$1);
|
||||
}));
|
||||
|
||||
/**
|
||||
* Throws an ExceptionInfo with the given message.
|
||||
* If rdr is an IndexingReader, additional information about column and line number is provided
|
||||
*/
|
||||
cljs.tools.reader.impl.errors.eof_error = (function cljs$tools$reader$impl$errors$eof_error(var_args){
|
||||
var args__5775__auto__ = [];
|
||||
var len__5769__auto___5318 = arguments.length;
|
||||
var i__5770__auto___5319 = (0);
|
||||
while(true){
|
||||
if((i__5770__auto___5319 < len__5769__auto___5318)){
|
||||
args__5775__auto__.push((arguments[i__5770__auto___5319]));
|
||||
|
||||
var G__5320 = (i__5770__auto___5319 + (1));
|
||||
i__5770__auto___5319 = G__5320;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var argseq__5776__auto__ = ((((1) < args__5775__auto__.length))?(new cljs.core.IndexedSeq(args__5775__auto__.slice((1)),(0),null)):null);
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic((arguments[(0)]),argseq__5776__auto__);
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic = (function (rdr,msgs){
|
||||
return cljs.tools.reader.impl.errors.throw_ex.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.cst$kw$eof,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.str,msgs)], 0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.eof_error.cljs$lang$maxFixedArity = (1));
|
||||
|
||||
/** @this {Function} */
|
||||
(cljs.tools.reader.impl.errors.eof_error.cljs$lang$applyTo = (function (seq5316){
|
||||
var G__5317 = cljs.core.first(seq5316);
|
||||
var seq5316__$1 = cljs.core.next(seq5316);
|
||||
var self__5754__auto__ = this;
|
||||
return self__5754__auto__.cljs$core$IFn$_invoke$arity$variadic(G__5317,seq5316__$1);
|
||||
}));
|
||||
|
||||
cljs.tools.reader.impl.errors.throw_eof_delimited = (function cljs$tools$reader$impl$errors$throw_eof_delimited(var_args){
|
||||
var G__5322 = arguments.length;
|
||||
switch (G__5322) {
|
||||
case 4:
|
||||
return cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$core$IFn$_invoke$arity$4((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]));
|
||||
|
||||
break;
|
||||
case 5:
|
||||
return cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$core$IFn$_invoke$arity$5((arguments[(0)]),(arguments[(1)]),(arguments[(2)]),(arguments[(3)]),(arguments[(4)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$core$IFn$_invoke$arity$4 = (function (rdr,kind,column,line){
|
||||
return cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$core$IFn$_invoke$arity$5(rdr,kind,line,column,null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$core$IFn$_invoke$arity$5 = (function (rdr,kind,line,column,n){
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unexpected EOF while reading ",(cljs.core.truth_(n)?["item ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(n)," of "].join(''):null),cljs.core.name(kind),(cljs.core.truth_(line)?[", starting at line ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(line)," and column ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(column)].join(''):null),"."], 0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_eof_delimited.cljs$lang$maxFixedArity = 5);
|
||||
|
||||
cljs.tools.reader.impl.errors.throw_odd_map = (function cljs$tools$reader$impl$errors$throw_odd_map(rdr,line,col,elements){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["The map literal starting with ",cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1(cljs.core.first(elements)),(cljs.core.truth_(line)?[" on line ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(line)," column ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(col)].join(''):null)," contains ",cljs.core.count(elements)," form(s). Map literals must contain an even number of forms."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_number = (function cljs$tools$reader$impl$errors$throw_invalid_number(rdr,token){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid number: ",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_literal = (function cljs$tools$reader$impl$errors$throw_invalid_unicode_literal(rdr,token){
|
||||
throw cljs.tools.reader.impl.errors.illegal_arg_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid unicode literal: \\",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_escape = (function cljs$tools$reader$impl$errors$throw_invalid_unicode_escape(rdr,ch){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid unicode escape: \\u",ch,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid = (function cljs$tools$reader$impl$errors$throw_invalid(rdr,kind,token){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid ",cljs.core.name(kind),": ",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_eof_at_start = (function cljs$tools$reader$impl$errors$throw_eof_at_start(rdr,kind){
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unexpected EOF while reading start of ",cljs.core.name(kind),"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_char = (function cljs$tools$reader$impl$errors$throw_bad_char(rdr,kind,ch){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid character: ",ch," found while reading ",cljs.core.name(kind),"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_eof_at_dispatch = (function cljs$tools$reader$impl$errors$throw_eof_at_dispatch(rdr){
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unexpected EOF while reading dispatch character."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_unmatch_delimiter = (function cljs$tools$reader$impl$errors$throw_unmatch_delimiter(rdr,ch){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unmatched delimiter ",ch,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_eof_reading = (function cljs$tools$reader$impl$errors$throw_eof_reading(var_args){
|
||||
var args__5775__auto__ = [];
|
||||
var len__5769__auto___5328 = arguments.length;
|
||||
var i__5770__auto___5329 = (0);
|
||||
while(true){
|
||||
if((i__5770__auto___5329 < len__5769__auto___5328)){
|
||||
args__5775__auto__.push((arguments[i__5770__auto___5329]));
|
||||
|
||||
var G__5330 = (i__5770__auto___5329 + (1));
|
||||
i__5770__auto___5329 = G__5330;
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var argseq__5776__auto__ = ((((2) < args__5775__auto__.length))?(new cljs.core.IndexedSeq(args__5775__auto__.slice((2)),(0),null)):null);
|
||||
return cljs.tools.reader.impl.errors.throw_eof_reading.cljs$core$IFn$_invoke$arity$variadic((arguments[(0)]),(arguments[(1)]),argseq__5776__auto__);
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_eof_reading.cljs$core$IFn$_invoke$arity$variadic = (function (rdr,kind,start){
|
||||
var init = (function (){var G__5327 = kind;
|
||||
var G__5327__$1 = (((G__5327 instanceof cljs.core.Keyword))?G__5327.fqn:null);
|
||||
switch (G__5327__$1) {
|
||||
case "regex":
|
||||
return "#\"";
|
||||
|
||||
break;
|
||||
case "string":
|
||||
return "\"";
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["No matching clause: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(G__5327__$1)].join('')));
|
||||
|
||||
}
|
||||
})();
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unexpected EOF reading ",cljs.core.name(kind)," starting ",cljs.core.apply.cljs$core$IFn$_invoke$arity$3(cljs.core.str,init,start),"."], 0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.errors.throw_eof_reading.cljs$lang$maxFixedArity = (2));
|
||||
|
||||
/** @this {Function} */
|
||||
(cljs.tools.reader.impl.errors.throw_eof_reading.cljs$lang$applyTo = (function (seq5324){
|
||||
var G__5325 = cljs.core.first(seq5324);
|
||||
var seq5324__$1 = cljs.core.next(seq5324);
|
||||
var G__5326 = cljs.core.first(seq5324__$1);
|
||||
var seq5324__$2 = cljs.core.next(seq5324__$1);
|
||||
var self__5754__auto__ = this;
|
||||
return self__5754__auto__.cljs$core$IFn$_invoke$arity$variadic(G__5325,G__5326,seq5324__$2);
|
||||
}));
|
||||
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_char = (function cljs$tools$reader$impl$errors$throw_invalid_unicode_char(rdr,token){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid unicode character \\",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_digit_in_token = (function cljs$tools$reader$impl$errors$throw_invalid_unicode_digit_in_token(rdr,ch,token){
|
||||
return cljs.tools.reader.impl.errors.illegal_arg_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid digit ",ch," in unicode character \\",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_digit = (function cljs$tools$reader$impl$errors$throw_invalid_unicode_digit(rdr,ch){
|
||||
return cljs.tools.reader.impl.errors.illegal_arg_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid digit ",ch," in unicode character."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_unicode_len = (function cljs$tools$reader$impl$errors$throw_invalid_unicode_len(rdr,actual,expected){
|
||||
return cljs.tools.reader.impl.errors.illegal_arg_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid unicode literal. Unicode literals should be ",expected,"characters long. ","Value supplied is ",actual," characters long."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_character_literal = (function cljs$tools$reader$impl$errors$throw_invalid_character_literal(rdr,token){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid character literal \\u",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_invalid_octal_len = (function cljs$tools$reader$impl$errors$throw_invalid_octal_len(rdr,token){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid octal escape sequence in a character literal: ",token,". Octal escape sequences must be 3 or fewer digits."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_octal_number = (function cljs$tools$reader$impl$errors$throw_bad_octal_number(rdr){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Octal escape sequence must be in range [0, 377]."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_unsupported_character = (function cljs$tools$reader$impl$errors$throw_unsupported_character(rdr,token){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unsupported character: ",token,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_eof_in_character = (function cljs$tools$reader$impl$errors$throw_eof_in_character(rdr){
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unexpected EOF while reading character."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_escape_char = (function cljs$tools$reader$impl$errors$throw_bad_escape_char(rdr,ch){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Unsupported escape character: \\",ch,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_single_colon = (function cljs$tools$reader$impl$errors$throw_single_colon(rdr){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["A single colon is not a valid keyword."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_metadata = (function cljs$tools$reader$impl$errors$throw_bad_metadata(rdr,x){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Metadata cannot be ",cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1(x),". Metadata must be a Symbol, Keyword, String or Map."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_metadata_target = (function cljs$tools$reader$impl$errors$throw_bad_metadata_target(rdr,target){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Metadata can not be applied to ",cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1(target),". ","Metadata can only be applied to IMetas."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_feature_not_keyword = (function cljs$tools$reader$impl$errors$throw_feature_not_keyword(rdr,feature){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Feature cannot be ",cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1(feature),". Features must be keywords."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_ns_map_no_map = (function cljs$tools$reader$impl$errors$throw_ns_map_no_map(rdr,ns_name){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Namespaced map with namespace ",ns_name," does not specify a map."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_ns = (function cljs$tools$reader$impl$errors$throw_bad_ns(rdr,ns_name){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid value used as namespace in namespaced map: ",ns_name,"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_bad_reader_tag = (function cljs$tools$reader$impl$errors$throw_bad_reader_tag(rdr,tag){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["Invalid reader tag: ",cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1(tag),". Reader tags must be symbols."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_unknown_reader_tag = (function cljs$tools$reader$impl$errors$throw_unknown_reader_tag(rdr,tag){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["No reader function for tag ",cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1(tag),"."], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.duplicate_keys_error = (function cljs$tools$reader$impl$errors$duplicate_keys_error(msg,coll){
|
||||
var duplicates = (function cljs$tools$reader$impl$errors$duplicate_keys_error_$_duplicates(seq){
|
||||
var iter__5523__auto__ = (function cljs$tools$reader$impl$errors$duplicate_keys_error_$_duplicates_$_iter__5342(s__5343){
|
||||
return (new cljs.core.LazySeq(null,(function (){
|
||||
var s__5343__$1 = s__5343;
|
||||
while(true){
|
||||
var temp__4657__auto__ = cljs.core.seq(s__5343__$1);
|
||||
if(temp__4657__auto__){
|
||||
var s__5343__$2 = temp__4657__auto__;
|
||||
if(cljs.core.chunked_seq_QMARK_(s__5343__$2)){
|
||||
var c__5521__auto__ = cljs.core.chunk_first(s__5343__$2);
|
||||
var size__5522__auto__ = cljs.core.count(c__5521__auto__);
|
||||
var b__5345 = cljs.core.chunk_buffer(size__5522__auto__);
|
||||
if((function (){var i__5344 = (0);
|
||||
while(true){
|
||||
if((i__5344 < size__5522__auto__)){
|
||||
var vec__5346 = cljs.core._nth.cljs$core$IFn$_invoke$arity$2(c__5521__auto__,i__5344);
|
||||
var id = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5346,(0),null);
|
||||
var freq = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5346,(1),null);
|
||||
if((freq > (1))){
|
||||
cljs.core.chunk_append(b__5345,id);
|
||||
|
||||
var G__5352 = (i__5344 + (1));
|
||||
i__5344 = G__5352;
|
||||
continue;
|
||||
} else {
|
||||
var G__5353 = (i__5344 + (1));
|
||||
i__5344 = G__5353;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})()){
|
||||
return cljs.core.chunk_cons(cljs.core.chunk(b__5345),cljs$tools$reader$impl$errors$duplicate_keys_error_$_duplicates_$_iter__5342(cljs.core.chunk_rest(s__5343__$2)));
|
||||
} else {
|
||||
return cljs.core.chunk_cons(cljs.core.chunk(b__5345),null);
|
||||
}
|
||||
} else {
|
||||
var vec__5349 = cljs.core.first(s__5343__$2);
|
||||
var id = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5349,(0),null);
|
||||
var freq = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5349,(1),null);
|
||||
if((freq > (1))){
|
||||
return cljs.core.cons(id,cljs$tools$reader$impl$errors$duplicate_keys_error_$_duplicates_$_iter__5342(cljs.core.rest(s__5343__$2)));
|
||||
} else {
|
||||
var G__5354 = cljs.core.rest(s__5343__$2);
|
||||
s__5343__$1 = G__5354;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}),null,null));
|
||||
});
|
||||
return iter__5523__auto__(cljs.core.frequencies(seq));
|
||||
});
|
||||
var dups = duplicates(coll);
|
||||
return cljs.core.apply.cljs$core$IFn$_invoke$arity$5(cljs.core.str,msg,(((cljs.core.count(dups) > (1)))?"s":null),": ",cljs.core.interpose.cljs$core$IFn$_invoke$arity$2(", ",dups));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_dup_keys = (function cljs$tools$reader$impl$errors$throw_dup_keys(rdr,kind,ks){
|
||||
return cljs.tools.reader.impl.errors.reader_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.tools.reader.impl.errors.duplicate_keys_error([clojure.string.capitalize(cljs.core.name(kind))," literal contains duplicate key"].join(''),ks)], 0));
|
||||
});
|
||||
cljs.tools.reader.impl.errors.throw_eof_error = (function cljs$tools$reader$impl$errors$throw_eof_error(rdr,line){
|
||||
if(cljs.core.truth_(line)){
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["EOF while reading, starting at line ",line,"."], 0));
|
||||
} else {
|
||||
return cljs.tools.reader.impl.errors.eof_error.cljs$core$IFn$_invoke$arity$variadic(rdr,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2(["EOF while reading."], 0));
|
||||
}
|
||||
});
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
;; Copyright (c) Russ Olsen, Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.tools.reader.impl.inspect)
|
||||
|
||||
(declare inspect*)
|
||||
|
||||
(defn- inspect*-col [truncate col start end]
|
||||
(let [n (count col)
|
||||
l (if truncate 0 (min 10 n))
|
||||
elements (map (partial inspect* true) (take l col))
|
||||
content (apply str (interpose " " elements))
|
||||
suffix (if (< l n) "...")]
|
||||
(str start content suffix end)))
|
||||
|
||||
(defn- dispatch-inspect
|
||||
[_ x]
|
||||
(cond
|
||||
(nil? x) :nil
|
||||
(string? x) :string
|
||||
(keyword? x) :strable
|
||||
(number? x) :strable
|
||||
(symbol? x) :strable
|
||||
(vector? x) :vector
|
||||
(list? x) :list
|
||||
(map? x) :map
|
||||
(set? x) :set
|
||||
(= x true) :strable
|
||||
(= x false) :strable
|
||||
:default (type x)))
|
||||
|
||||
(defmulti inspect* dispatch-inspect)
|
||||
|
||||
(defmethod inspect* :string [truncate ^String x]
|
||||
(let [n (if truncate 5 20)
|
||||
suffix (if (> (.-length x) n) "...\"" "\"")]
|
||||
(str
|
||||
\"
|
||||
(.substring ^String x 0 (min n (.-length x)))
|
||||
suffix)))
|
||||
|
||||
(defmethod inspect* :strable [truncate x] (str x))
|
||||
|
||||
(defmethod inspect* cljs.core/IndexedSeq [truncate x]
|
||||
"<indexed seq>")
|
||||
|
||||
(defmethod inspect* cljs.core/PersistentArrayMapSeq [truncate x]
|
||||
"<map seq>")
|
||||
|
||||
(defmethod inspect* cljs.core/NodeSeq [truncate x]
|
||||
"<map seq>")
|
||||
|
||||
(defmethod inspect* cljs.core/Cons [truncate x] "<cons>")
|
||||
|
||||
(defmethod inspect* cljs.core/LazySeq [truncate x] "<lazy seq>")
|
||||
|
||||
(defmethod inspect* :nil [_ _] "nil")
|
||||
|
||||
(defmethod inspect* :list [truncate col]
|
||||
(inspect*-col truncate col \( \)))
|
||||
|
||||
(defmethod inspect* :map [truncate m]
|
||||
(let [len (count m)
|
||||
n-shown (if truncate 0 len)
|
||||
contents (apply concat (take n-shown m))
|
||||
suffix (if (> len n-shown) "...}" \})]
|
||||
(inspect*-col truncate contents \{ suffix)))
|
||||
|
||||
(defmethod inspect* :set [truncate col]
|
||||
(inspect*-col truncate col "#{" \}))
|
||||
|
||||
(defmethod inspect* :vector [truncate col]
|
||||
(inspect*-col truncate col \[ \]))
|
||||
|
||||
(defmethod inspect* :default [truncate x]
|
||||
(pr-str (type x)))
|
||||
|
||||
(defn inspect
|
||||
"Return a string description of the value supplied.
|
||||
May be the a string version of the value itself (e.g. \"true\")
|
||||
or it may be a description (e.g. \"an instance of Foo\").
|
||||
If truncate is true then return a very terse version of
|
||||
the inspection."
|
||||
([x] (inspect* false x))
|
||||
([truncate x] (inspect* truncate x)))
|
||||
Executable
+157
@@ -0,0 +1,157 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.tools.reader.impl.inspect');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR__col = (function cljs$tools$reader$impl$inspect$inspect_STAR__col(truncate,col,start,end){
|
||||
var n = cljs.core.count(col);
|
||||
var l = (cljs.core.truth_(truncate)?(0):(function (){var x__5133__auto__ = (10);
|
||||
var y__5134__auto__ = n;
|
||||
return ((x__5133__auto__ < y__5134__auto__) ? x__5133__auto__ : y__5134__auto__);
|
||||
})());
|
||||
var elements = cljs.core.map.cljs$core$IFn$_invoke$arity$2(cljs.core.partial.cljs$core$IFn$_invoke$arity$2(cljs.tools.reader.impl.inspect.inspect_STAR_,true),cljs.core.take.cljs$core$IFn$_invoke$arity$2(l,col));
|
||||
var content = cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.str,cljs.core.interpose.cljs$core$IFn$_invoke$arity$2(" ",elements));
|
||||
var suffix = (((l < n))?"...":null);
|
||||
return [cljs.core.str.cljs$core$IFn$_invoke$arity$1(start),cljs.core.str.cljs$core$IFn$_invoke$arity$1(content),suffix,cljs.core.str.cljs$core$IFn$_invoke$arity$1(end)].join('');
|
||||
});
|
||||
cljs.tools.reader.impl.inspect.dispatch_inspect = (function cljs$tools$reader$impl$inspect$dispatch_inspect(_,x){
|
||||
if((x == null)){
|
||||
return cljs.core.cst$kw$nil;
|
||||
} else {
|
||||
if(typeof x === 'string'){
|
||||
return cljs.core.cst$kw$string;
|
||||
} else {
|
||||
if((x instanceof cljs.core.Keyword)){
|
||||
return cljs.core.cst$kw$strable;
|
||||
} else {
|
||||
if(typeof x === 'number'){
|
||||
return cljs.core.cst$kw$strable;
|
||||
} else {
|
||||
if((x instanceof cljs.core.Symbol)){
|
||||
return cljs.core.cst$kw$strable;
|
||||
} else {
|
||||
if(cljs.core.vector_QMARK_(x)){
|
||||
return cljs.core.cst$kw$vector;
|
||||
} else {
|
||||
if(cljs.core.list_QMARK_(x)){
|
||||
return cljs.core.cst$kw$list;
|
||||
} else {
|
||||
if(cljs.core.map_QMARK_(x)){
|
||||
return cljs.core.cst$kw$map;
|
||||
} else {
|
||||
if(cljs.core.set_QMARK_(x)){
|
||||
return cljs.core.cst$kw$set;
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(x,true)){
|
||||
return cljs.core.cst$kw$strable;
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(x,false)){
|
||||
return cljs.core.cst$kw$strable;
|
||||
} else {
|
||||
return cljs.core.type(x);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if((typeof cljs !== 'undefined') && (typeof cljs.tools !== 'undefined') && (typeof cljs.tools.reader !== 'undefined') && (typeof cljs.tools.reader.impl !== 'undefined') && (typeof cljs.tools.reader.impl.inspect !== 'undefined') && (typeof cljs.tools.reader.impl.inspect.inspect_STAR_ !== 'undefined')){
|
||||
} else {
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_ = (function (){var method_table__5642__auto__ = cljs.core.atom.cljs$core$IFn$_invoke$arity$1(cljs.core.PersistentArrayMap.EMPTY);
|
||||
var prefer_table__5643__auto__ = cljs.core.atom.cljs$core$IFn$_invoke$arity$1(cljs.core.PersistentArrayMap.EMPTY);
|
||||
var method_cache__5644__auto__ = cljs.core.atom.cljs$core$IFn$_invoke$arity$1(cljs.core.PersistentArrayMap.EMPTY);
|
||||
var cached_hierarchy__5645__auto__ = cljs.core.atom.cljs$core$IFn$_invoke$arity$1(cljs.core.PersistentArrayMap.EMPTY);
|
||||
var hierarchy__5646__auto__ = cljs.core.get.cljs$core$IFn$_invoke$arity$3(cljs.core.PersistentArrayMap.EMPTY,cljs.core.cst$kw$hierarchy,(function (){var fexpr__5294 = cljs.core.get_global_hierarchy;
|
||||
return (fexpr__5294.cljs$core$IFn$_invoke$arity$0 ? fexpr__5294.cljs$core$IFn$_invoke$arity$0() : fexpr__5294.call(null));
|
||||
})());
|
||||
return (new cljs.core.MultiFn(cljs.core.symbol.cljs$core$IFn$_invoke$arity$2("cljs.tools.reader.impl.inspect","inspect*"),cljs.tools.reader.impl.inspect.dispatch_inspect,cljs.core.cst$kw$default,hierarchy__5646__auto__,method_table__5642__auto__,prefer_table__5643__auto__,method_cache__5644__auto__,cached_hierarchy__5645__auto__));
|
||||
})();
|
||||
}
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$string,(function (truncate,x){
|
||||
var n = (cljs.core.truth_(truncate)?(5):(20));
|
||||
var suffix = (((x.length > n))?"...\"":"\"");
|
||||
return ["\"",cljs.core.str.cljs$core$IFn$_invoke$arity$1(x.substring((0),(function (){var x__5133__auto__ = n;
|
||||
var y__5134__auto__ = x.length;
|
||||
return ((x__5133__auto__ < y__5134__auto__) ? x__5133__auto__ : y__5134__auto__);
|
||||
})())),suffix].join('');
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$strable,(function (truncate,x){
|
||||
return cljs.core.str.cljs$core$IFn$_invoke$arity$1(x);
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.IndexedSeq,(function (truncate,x){
|
||||
return "<indexed seq>";
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.PersistentArrayMapSeq,(function (truncate,x){
|
||||
return "<map seq>";
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.NodeSeq,(function (truncate,x){
|
||||
return "<map seq>";
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.Cons,(function (truncate,x){
|
||||
return "<cons>";
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.LazySeq,(function (truncate,x){
|
||||
return "<lazy seq>";
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$nil,(function (_,___$1){
|
||||
return "nil";
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$list,(function (truncate,col){
|
||||
return cljs.tools.reader.impl.inspect.inspect_STAR__col(truncate,col,"(",")");
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$map,(function (truncate,m){
|
||||
var len = cljs.core.count(m);
|
||||
var n_shown = (cljs.core.truth_(truncate)?(0):len);
|
||||
var contents = cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.concat,cljs.core.take.cljs$core$IFn$_invoke$arity$2(n_shown,m));
|
||||
var suffix = (((len > n_shown))?"...}":"}");
|
||||
return cljs.tools.reader.impl.inspect.inspect_STAR__col(truncate,contents,"{",suffix);
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$set,(function (truncate,col){
|
||||
return cljs.tools.reader.impl.inspect.inspect_STAR__col(truncate,col,"#{","}");
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$vector,(function (truncate,col){
|
||||
return cljs.tools.reader.impl.inspect.inspect_STAR__col(truncate,col,"[","]");
|
||||
}));
|
||||
cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IMultiFn$_add_method$arity$3(null,cljs.core.cst$kw$default,(function (truncate,x){
|
||||
return cljs.core.pr_str.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.type(x)], 0));
|
||||
}));
|
||||
/**
|
||||
* Return a string description of the value supplied.
|
||||
* May be the a string version of the value itself (e.g. "true")
|
||||
* or it may be a description (e.g. "an instance of Foo").
|
||||
* If truncate is true then return a very terse version of
|
||||
* the inspection.
|
||||
*/
|
||||
cljs.tools.reader.impl.inspect.inspect = (function cljs$tools$reader$impl$inspect$inspect(var_args){
|
||||
var G__5296 = arguments.length;
|
||||
switch (G__5296) {
|
||||
case 1:
|
||||
return cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$1 = (function (x){
|
||||
return (cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IFn$_invoke$arity$2 ? cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IFn$_invoke$arity$2(false,x) : cljs.tools.reader.impl.inspect.inspect_STAR_.call(null,false,x));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.inspect.inspect.cljs$core$IFn$_invoke$arity$2 = (function (truncate,x){
|
||||
return (cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IFn$_invoke$arity$2 ? cljs.tools.reader.impl.inspect.inspect_STAR_.cljs$core$IFn$_invoke$arity$2(truncate,x) : cljs.tools.reader.impl.inspect.inspect_STAR_.call(null,truncate,x));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.inspect.inspect.cljs$lang$maxFixedArity = 2);
|
||||
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
;; Copyright (c) Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns cljs.tools.reader.impl.utils
|
||||
(:refer-clojure :exclude [char])
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[goog.string :as gstring]))
|
||||
|
||||
(defn char [x]
|
||||
(when-not (nil? x)
|
||||
(cljs.core/char x)))
|
||||
|
||||
(defn ^boolean ex-info? [ex]
|
||||
(instance? cljs.core.ExceptionInfo ex))
|
||||
|
||||
(defrecord ReaderConditional [splicing? form])
|
||||
|
||||
(defn ^boolean reader-conditional?
|
||||
"Return true if the value is the data representation of a reader conditional"
|
||||
[value]
|
||||
(instance? ReaderConditional value))
|
||||
|
||||
(defn reader-conditional
|
||||
"Construct a data representation of a reader conditional.
|
||||
If true, splicing? indicates read-cond-splicing."
|
||||
[form splicing?]
|
||||
(ReaderConditional. splicing? form))
|
||||
|
||||
(extend-protocol IPrintWithWriter
|
||||
ReaderConditional
|
||||
(-pr-writer [coll writer opts]
|
||||
(-write writer (str "#?" (when (:splicing? coll) "@")))
|
||||
(pr-writer (:form coll) writer opts)))
|
||||
|
||||
(def ws-rx #"[\s]")
|
||||
|
||||
(defn ^boolean whitespace?
|
||||
"Checks whether a given character is whitespace"
|
||||
[ch]
|
||||
(when-not (nil? ch)
|
||||
(if (identical? ch \,)
|
||||
true
|
||||
(.test ws-rx ch))))
|
||||
|
||||
(defn ^boolean numeric?
|
||||
"Checks whether a given character is numeric"
|
||||
[ch]
|
||||
(when-not (nil? ch)
|
||||
(gstring/isNumeric ch)))
|
||||
|
||||
(defn ^boolean newline?
|
||||
"Checks whether the character is a newline"
|
||||
[c]
|
||||
(or (identical? \newline c)
|
||||
(identical? "\n" c)
|
||||
(nil? c)))
|
||||
|
||||
(defn desugar-meta
|
||||
"Resolves syntactical sugar in metadata" ;; could be combined with some other desugar?
|
||||
[f]
|
||||
(cond
|
||||
(keyword? f) {f true}
|
||||
(symbol? f) {:tag f}
|
||||
(string? f) {:tag f}
|
||||
:else f))
|
||||
|
||||
(def last-id (atom 0))
|
||||
|
||||
(defn next-id
|
||||
[]
|
||||
(swap! last-id inc))
|
||||
|
||||
(defn namespace-keys [ns keys]
|
||||
(for [key keys]
|
||||
(if (or (symbol? key)
|
||||
(keyword? key))
|
||||
(let [[key-ns key-name] ((juxt namespace name) key)
|
||||
->key (if (symbol? key) symbol keyword)]
|
||||
(cond
|
||||
(nil? key-ns)
|
||||
(->key ns key-name)
|
||||
|
||||
(= "_" key-ns)
|
||||
(->key key-name)
|
||||
|
||||
:else
|
||||
key))
|
||||
key)))
|
||||
|
||||
(defn second' [[a b]]
|
||||
(when-not a b))
|
||||
|
||||
(defn char-code [ch base]
|
||||
(let [code (js/parseInt ch base)]
|
||||
(if (js/isNaN code)
|
||||
-1
|
||||
code)))
|
||||
Executable
+413
@@ -0,0 +1,413 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.tools.reader.impl.utils');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('clojure.string');
|
||||
goog.require('goog.string');
|
||||
cljs.tools.reader.impl.utils.char$ = (function cljs$tools$reader$impl$utils$char(x){
|
||||
if((x == null)){
|
||||
return null;
|
||||
} else {
|
||||
return cljs.core.char$(x);
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.impl.utils.ex_info_QMARK_ = (function cljs$tools$reader$impl$utils$ex_info_QMARK_(ex){
|
||||
return (ex instanceof cljs.core.ExceptionInfo);
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.core.IRecord}
|
||||
* @implements {cljs.core.IKVReduce}
|
||||
* @implements {cljs.core.IEquiv}
|
||||
* @implements {cljs.core.IHash}
|
||||
* @implements {cljs.core.ICollection}
|
||||
* @implements {cljs.core.ICounted}
|
||||
* @implements {cljs.core.ISeqable}
|
||||
* @implements {cljs.core.IMeta}
|
||||
* @implements {cljs.core.ICloneable}
|
||||
* @implements {cljs.core.IPrintWithWriter}
|
||||
* @implements {cljs.core.IIterable}
|
||||
* @implements {cljs.core.IWithMeta}
|
||||
* @implements {cljs.core.IAssociative}
|
||||
* @implements {cljs.core.IMap}
|
||||
* @implements {cljs.core.ILookup}
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.ReaderConditional = (function (splicing_QMARK_,form,__meta,__extmap,__hash){
|
||||
this.splicing_QMARK_ = splicing_QMARK_;
|
||||
this.form = form;
|
||||
this.__meta = __meta;
|
||||
this.__extmap = __extmap;
|
||||
this.__hash = __hash;
|
||||
this.cljs$lang$protocol_mask$partition0$ = 2230716170;
|
||||
this.cljs$lang$protocol_mask$partition1$ = 139264;
|
||||
});
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$ILookup$_lookup$arity$2 = (function (this__5343__auto__,k__5344__auto__){
|
||||
var self__ = this;
|
||||
var this__5343__auto____$1 = this;
|
||||
return this__5343__auto____$1.cljs$core$ILookup$_lookup$arity$3(null,k__5344__auto__,null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$ILookup$_lookup$arity$3 = (function (this__5345__auto__,k5233,else__5346__auto__){
|
||||
var self__ = this;
|
||||
var this__5345__auto____$1 = this;
|
||||
var G__5237 = k5233;
|
||||
var G__5237__$1 = (((G__5237 instanceof cljs.core.Keyword))?G__5237.fqn:null);
|
||||
switch (G__5237__$1) {
|
||||
case "splicing?":
|
||||
return self__.splicing_QMARK_;
|
||||
|
||||
break;
|
||||
case "form":
|
||||
return self__.form;
|
||||
|
||||
break;
|
||||
default:
|
||||
return cljs.core.get.cljs$core$IFn$_invoke$arity$3(self__.__extmap,k5233,else__5346__auto__);
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IKVReduce$_kv_reduce$arity$3 = (function (this__5363__auto__,f__5364__auto__,init__5365__auto__){
|
||||
var self__ = this;
|
||||
var this__5363__auto____$1 = this;
|
||||
return cljs.core.reduce.cljs$core$IFn$_invoke$arity$3((function (ret__5366__auto__,p__5238){
|
||||
var vec__5239 = p__5238;
|
||||
var k__5367__auto__ = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5239,(0),null);
|
||||
var v__5368__auto__ = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5239,(1),null);
|
||||
return (f__5364__auto__.cljs$core$IFn$_invoke$arity$3 ? f__5364__auto__.cljs$core$IFn$_invoke$arity$3(ret__5366__auto__,k__5367__auto__,v__5368__auto__) : f__5364__auto__.call(null,ret__5366__auto__,k__5367__auto__,v__5368__auto__));
|
||||
}),init__5365__auto__,this__5363__auto____$1);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IPrintWithWriter$_pr_writer$arity$3 = (function (this__5358__auto__,writer__5359__auto__,opts__5360__auto__){
|
||||
var self__ = this;
|
||||
var this__5358__auto____$1 = this;
|
||||
var pr_pair__5361__auto__ = (function (keyval__5362__auto__){
|
||||
return cljs.core.pr_sequential_writer(writer__5359__auto__,cljs.core.pr_writer,""," ","",opts__5360__auto__,keyval__5362__auto__);
|
||||
});
|
||||
return cljs.core.pr_sequential_writer(writer__5359__auto__,pr_pair__5361__auto__,"#cljs.tools.reader.impl.utils.ReaderConditional{",", ","}",opts__5360__auto__,cljs.core.concat.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$splicing_QMARK_,self__.splicing_QMARK_],null)),(new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,[cljs.core.cst$kw$form,self__.form],null))], null),self__.__extmap));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IIterable$_iterator$arity$1 = (function (G__5232){
|
||||
var self__ = this;
|
||||
var G__5232__$1 = this;
|
||||
return (new cljs.core.RecordIter((0),G__5232__$1,2,new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$kw$splicing_QMARK_,cljs.core.cst$kw$form], null),(cljs.core.truth_(self__.__extmap)?cljs.core._iterator(self__.__extmap):cljs.core.nil_iter())));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IMeta$_meta$arity$1 = (function (this__5341__auto__){
|
||||
var self__ = this;
|
||||
var this__5341__auto____$1 = this;
|
||||
return self__.__meta;
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$ICloneable$_clone$arity$1 = (function (this__5338__auto__){
|
||||
var self__ = this;
|
||||
var this__5338__auto____$1 = this;
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(self__.splicing_QMARK_,self__.form,self__.__meta,self__.__extmap,self__.__hash));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$ICounted$_count$arity$1 = (function (this__5347__auto__){
|
||||
var self__ = this;
|
||||
var this__5347__auto____$1 = this;
|
||||
return (2 + cljs.core.count(self__.__extmap));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IHash$_hash$arity$1 = (function (this__5339__auto__){
|
||||
var self__ = this;
|
||||
var this__5339__auto____$1 = this;
|
||||
var h__5154__auto__ = self__.__hash;
|
||||
if((!((h__5154__auto__ == null)))){
|
||||
return h__5154__auto__;
|
||||
} else {
|
||||
var h__5154__auto____$1 = (function (){var fexpr__5242 = (function (coll__5340__auto__){
|
||||
return (-209062840 ^ cljs.core.hash_unordered_coll(coll__5340__auto__));
|
||||
});
|
||||
return fexpr__5242(this__5339__auto____$1);
|
||||
})();
|
||||
(self__.__hash = h__5154__auto____$1);
|
||||
|
||||
return h__5154__auto____$1;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IEquiv$_equiv$arity$2 = (function (this5234,other5235){
|
||||
var self__ = this;
|
||||
var this5234__$1 = this;
|
||||
return (((!((other5235 == null)))) && ((((this5234__$1.constructor === other5235.constructor)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this5234__$1.splicing_QMARK_,other5235.splicing_QMARK_)) && (((cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this5234__$1.form,other5235.form)) && (cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(this5234__$1.__extmap,other5235.__extmap)))))))));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IMap$_dissoc$arity$2 = (function (this__5353__auto__,k__5354__auto__){
|
||||
var self__ = this;
|
||||
var this__5353__auto____$1 = this;
|
||||
if(cljs.core.contains_QMARK_(new cljs.core.PersistentHashSet(null, new cljs.core.PersistentArrayMap(null, 2, [cljs.core.cst$kw$splicing_QMARK_,null,cljs.core.cst$kw$form,null], null), null),k__5354__auto__)){
|
||||
return cljs.core.dissoc.cljs$core$IFn$_invoke$arity$2(cljs.core._with_meta(cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,this__5353__auto____$1),self__.__meta),k__5354__auto__);
|
||||
} else {
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(self__.splicing_QMARK_,self__.form,self__.__meta,cljs.core.not_empty(cljs.core.dissoc.cljs$core$IFn$_invoke$arity$2(self__.__extmap,k__5354__auto__)),null));
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IAssociative$_contains_key_QMARK_$arity$2 = (function (this__5350__auto__,k5233){
|
||||
var self__ = this;
|
||||
var this__5350__auto____$1 = this;
|
||||
var G__5243 = k5233;
|
||||
var G__5243__$1 = (((G__5243 instanceof cljs.core.Keyword))?G__5243.fqn:null);
|
||||
switch (G__5243__$1) {
|
||||
case "splicing?":
|
||||
case "form":
|
||||
return true;
|
||||
|
||||
break;
|
||||
default:
|
||||
return cljs.core.contains_QMARK_(self__.__extmap,k5233);
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IAssociative$_assoc$arity$3 = (function (this__5351__auto__,k__5352__auto__,G__5232){
|
||||
var self__ = this;
|
||||
var this__5351__auto____$1 = this;
|
||||
var pred__5244 = cljs.core.keyword_identical_QMARK_;
|
||||
var expr__5245 = k__5352__auto__;
|
||||
if(cljs.core.truth_((function (){var G__5247 = cljs.core.cst$kw$splicing_QMARK_;
|
||||
var G__5248 = expr__5245;
|
||||
return (pred__5244.cljs$core$IFn$_invoke$arity$2 ? pred__5244.cljs$core$IFn$_invoke$arity$2(G__5247,G__5248) : pred__5244.call(null,G__5247,G__5248));
|
||||
})())){
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(G__5232,self__.form,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
if(cljs.core.truth_((function (){var G__5249 = cljs.core.cst$kw$form;
|
||||
var G__5250 = expr__5245;
|
||||
return (pred__5244.cljs$core$IFn$_invoke$arity$2 ? pred__5244.cljs$core$IFn$_invoke$arity$2(G__5249,G__5250) : pred__5244.call(null,G__5249,G__5250));
|
||||
})())){
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(self__.splicing_QMARK_,G__5232,self__.__meta,self__.__extmap,null));
|
||||
} else {
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(self__.splicing_QMARK_,self__.form,self__.__meta,cljs.core.assoc.cljs$core$IFn$_invoke$arity$3(self__.__extmap,k__5352__auto__,G__5232),null));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$ISeqable$_seq$arity$1 = (function (this__5356__auto__){
|
||||
var self__ = this;
|
||||
var this__5356__auto____$1 = this;
|
||||
return cljs.core.seq(cljs.core.concat.cljs$core$IFn$_invoke$arity$2(new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [(new cljs.core.MapEntry(cljs.core.cst$kw$splicing_QMARK_,self__.splicing_QMARK_,null)),(new cljs.core.MapEntry(cljs.core.cst$kw$form,self__.form,null))], null),self__.__extmap));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IWithMeta$_with_meta$arity$2 = (function (this__5342__auto__,G__5232){
|
||||
var self__ = this;
|
||||
var this__5342__auto____$1 = this;
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(self__.splicing_QMARK_,self__.form,G__5232,self__.__extmap,self__.__hash));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$ICollection$_conj$arity$2 = (function (this__5348__auto__,entry__5349__auto__){
|
||||
var self__ = this;
|
||||
var this__5348__auto____$1 = this;
|
||||
if(cljs.core.vector_QMARK_(entry__5349__auto__)){
|
||||
return this__5348__auto____$1.cljs$core$IAssociative$_assoc$arity$3(null,cljs.core._nth.cljs$core$IFn$_invoke$arity$2(entry__5349__auto__,(0)),cljs.core._nth.cljs$core$IFn$_invoke$arity$2(entry__5349__auto__,(1)));
|
||||
} else {
|
||||
return cljs.core.reduce.cljs$core$IFn$_invoke$arity$3(cljs.core._conj,this__5348__auto____$1,entry__5349__auto__);
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$splicing_QMARK_,cljs.core.cst$sym$form], null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.cljs$lang$type = true);
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.cljs$lang$ctorPrSeq = (function (this__5389__auto__){
|
||||
return (new cljs.core.List(null,"cljs.tools.reader.impl.utils/ReaderConditional",null,(1),null));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.cljs$lang$ctorPrWriter = (function (this__5389__auto__,writer__5390__auto__){
|
||||
return cljs.core._write(writer__5390__auto__,"cljs.tools.reader.impl.utils/ReaderConditional");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.tools.reader.impl.utils/ReaderConditional.
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.__GT_ReaderConditional = (function cljs$tools$reader$impl$utils$__GT_ReaderConditional(splicing_QMARK_,form){
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(splicing_QMARK_,form,null,null,null));
|
||||
});
|
||||
|
||||
/**
|
||||
* Factory function for cljs.tools.reader.impl.utils/ReaderConditional, taking a map of keywords to field values.
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.map__GT_ReaderConditional = (function cljs$tools$reader$impl$utils$map__GT_ReaderConditional(G__5236){
|
||||
var extmap__5385__auto__ = (function (){var G__5251 = cljs.core.dissoc.cljs$core$IFn$_invoke$arity$variadic(G__5236,cljs.core.cst$kw$splicing_QMARK_,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([cljs.core.cst$kw$form], 0));
|
||||
if(cljs.core.record_QMARK_(G__5236)){
|
||||
return cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,G__5251);
|
||||
} else {
|
||||
return G__5251;
|
||||
}
|
||||
})();
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(cljs.core.cst$kw$splicing_QMARK_.cljs$core$IFn$_invoke$arity$1(G__5236),cljs.core.cst$kw$form.cljs$core$IFn$_invoke$arity$1(G__5236),null,cljs.core.not_empty(extmap__5385__auto__),null));
|
||||
});
|
||||
|
||||
/**
|
||||
* Return true if the value is the data representation of a reader conditional
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.reader_conditional_QMARK_ = (function cljs$tools$reader$impl$utils$reader_conditional_QMARK_(value){
|
||||
return (value instanceof cljs.tools.reader.impl.utils.ReaderConditional);
|
||||
});
|
||||
/**
|
||||
* Construct a data representation of a reader conditional.
|
||||
* If true, splicing? indicates read-cond-splicing.
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.reader_conditional = (function cljs$tools$reader$impl$utils$reader_conditional(form,splicing_QMARK_){
|
||||
return (new cljs.tools.reader.impl.utils.ReaderConditional(splicing_QMARK_,form,null,null,null));
|
||||
});
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IPrintWithWriter$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.impl.utils.ReaderConditional.prototype.cljs$core$IPrintWithWriter$_pr_writer$arity$3 = (function (coll,writer,opts){
|
||||
var coll__$1 = this;
|
||||
cljs.core._write(writer,["#?",(cljs.core.truth_(coll__$1.splicing_QMARK_)?"@":null)].join(''));
|
||||
|
||||
return cljs.core.pr_writer(coll__$1.form,writer,opts);
|
||||
}));
|
||||
cljs.tools.reader.impl.utils.ws_rx = /[\s]/;
|
||||
/**
|
||||
* Checks whether a given character is whitespace
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.whitespace_QMARK_ = (function cljs$tools$reader$impl$utils$whitespace_QMARK_(ch){
|
||||
if((ch == null)){
|
||||
return null;
|
||||
} else {
|
||||
if((ch === ",")){
|
||||
return true;
|
||||
} else {
|
||||
return cljs.tools.reader.impl.utils.ws_rx.test(ch);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Checks whether a given character is numeric
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.numeric_QMARK_ = (function cljs$tools$reader$impl$utils$numeric_QMARK_(ch){
|
||||
if((ch == null)){
|
||||
return null;
|
||||
} else {
|
||||
return goog.string.isNumeric(ch);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Checks whether the character is a newline
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.newline_QMARK_ = (function cljs$tools$reader$impl$utils$newline_QMARK_(c){
|
||||
return ((("\n" === c)) || (((("\n" === c)) || ((c == null)))));
|
||||
});
|
||||
/**
|
||||
* Resolves syntactical sugar in metadata
|
||||
*/
|
||||
cljs.tools.reader.impl.utils.desugar_meta = (function cljs$tools$reader$impl$utils$desugar_meta(f){
|
||||
if((f instanceof cljs.core.Keyword)){
|
||||
return cljs.core.PersistentArrayMap.createAsIfByAssoc([f,true]);
|
||||
} else {
|
||||
if((f instanceof cljs.core.Symbol)){
|
||||
return new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,f], null);
|
||||
} else {
|
||||
if(typeof f === 'string'){
|
||||
return new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,f], null);
|
||||
} else {
|
||||
return f;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.impl.utils.last_id = cljs.core.atom.cljs$core$IFn$_invoke$arity$1((0));
|
||||
cljs.tools.reader.impl.utils.next_id = (function cljs$tools$reader$impl$utils$next_id(){
|
||||
return cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$2(cljs.tools.reader.impl.utils.last_id,cljs.core.inc);
|
||||
});
|
||||
cljs.tools.reader.impl.utils.namespace_keys = (function cljs$tools$reader$impl$utils$namespace_keys(ns,keys){
|
||||
var iter__5523__auto__ = (function cljs$tools$reader$impl$utils$namespace_keys_$_iter__5254(s__5255){
|
||||
return (new cljs.core.LazySeq(null,(function (){
|
||||
var s__5255__$1 = s__5255;
|
||||
while(true){
|
||||
var temp__4657__auto__ = cljs.core.seq(s__5255__$1);
|
||||
if(temp__4657__auto__){
|
||||
var s__5255__$2 = temp__4657__auto__;
|
||||
if(cljs.core.chunked_seq_QMARK_(s__5255__$2)){
|
||||
var c__5521__auto__ = cljs.core.chunk_first(s__5255__$2);
|
||||
var size__5522__auto__ = cljs.core.count(c__5521__auto__);
|
||||
var b__5257 = cljs.core.chunk_buffer(size__5522__auto__);
|
||||
if((function (){var i__5256 = (0);
|
||||
while(true){
|
||||
if((i__5256 < size__5522__auto__)){
|
||||
var key = cljs.core._nth.cljs$core$IFn$_invoke$arity$2(c__5521__auto__,i__5256);
|
||||
cljs.core.chunk_append(b__5257,(((((key instanceof cljs.core.Symbol)) || ((key instanceof cljs.core.Keyword))))?(function (){var vec__5258 = (function (){var fexpr__5261 = cljs.core.juxt.cljs$core$IFn$_invoke$arity$2(cljs.core.namespace,cljs.core.name);
|
||||
return (fexpr__5261.cljs$core$IFn$_invoke$arity$1 ? fexpr__5261.cljs$core$IFn$_invoke$arity$1(key) : fexpr__5261.call(null,key));
|
||||
})();
|
||||
var key_ns = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5258,(0),null);
|
||||
var key_name = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5258,(1),null);
|
||||
var __GT_key = (((key instanceof cljs.core.Symbol))?cljs.core.symbol:cljs.core.keyword);
|
||||
if((key_ns == null)){
|
||||
return (__GT_key.cljs$core$IFn$_invoke$arity$2 ? __GT_key.cljs$core$IFn$_invoke$arity$2(ns,key_name) : __GT_key.call(null,ns,key_name));
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2("_",key_ns)){
|
||||
return (__GT_key.cljs$core$IFn$_invoke$arity$1 ? __GT_key.cljs$core$IFn$_invoke$arity$1(key_name) : __GT_key.call(null,key_name));
|
||||
} else {
|
||||
return key;
|
||||
|
||||
}
|
||||
}
|
||||
})():key));
|
||||
|
||||
var G__5266 = (i__5256 + (1));
|
||||
i__5256 = G__5266;
|
||||
continue;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})()){
|
||||
return cljs.core.chunk_cons(cljs.core.chunk(b__5257),cljs$tools$reader$impl$utils$namespace_keys_$_iter__5254(cljs.core.chunk_rest(s__5255__$2)));
|
||||
} else {
|
||||
return cljs.core.chunk_cons(cljs.core.chunk(b__5257),null);
|
||||
}
|
||||
} else {
|
||||
var key = cljs.core.first(s__5255__$2);
|
||||
return cljs.core.cons((((((key instanceof cljs.core.Symbol)) || ((key instanceof cljs.core.Keyword))))?(function (){var vec__5262 = (function (){var fexpr__5265 = cljs.core.juxt.cljs$core$IFn$_invoke$arity$2(cljs.core.namespace,cljs.core.name);
|
||||
return (fexpr__5265.cljs$core$IFn$_invoke$arity$1 ? fexpr__5265.cljs$core$IFn$_invoke$arity$1(key) : fexpr__5265.call(null,key));
|
||||
})();
|
||||
var key_ns = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5262,(0),null);
|
||||
var key_name = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5262,(1),null);
|
||||
var __GT_key = (((key instanceof cljs.core.Symbol))?cljs.core.symbol:cljs.core.keyword);
|
||||
if((key_ns == null)){
|
||||
return (__GT_key.cljs$core$IFn$_invoke$arity$2 ? __GT_key.cljs$core$IFn$_invoke$arity$2(ns,key_name) : __GT_key.call(null,ns,key_name));
|
||||
} else {
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2("_",key_ns)){
|
||||
return (__GT_key.cljs$core$IFn$_invoke$arity$1 ? __GT_key.cljs$core$IFn$_invoke$arity$1(key_name) : __GT_key.call(null,key_name));
|
||||
} else {
|
||||
return key;
|
||||
|
||||
}
|
||||
}
|
||||
})():key),cljs$tools$reader$impl$utils$namespace_keys_$_iter__5254(cljs.core.rest(s__5255__$2)));
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}),null,null));
|
||||
});
|
||||
return iter__5523__auto__(keys);
|
||||
});
|
||||
cljs.tools.reader.impl.utils.second_SINGLEQUOTE_ = (function cljs$tools$reader$impl$utils$second_SINGLEQUOTE_(p__5267){
|
||||
var vec__5268 = p__5267;
|
||||
var a = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5268,(0),null);
|
||||
var b = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__5268,(1),null);
|
||||
if(cljs.core.truth_(a)){
|
||||
return null;
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.impl.utils.char_code = (function cljs$tools$reader$impl$utils$char_code(ch,base){
|
||||
var code = parseInt(ch,base);
|
||||
if(cljs.core.truth_(isNaN(code))){
|
||||
return (-1);
|
||||
} else {
|
||||
return code;
|
||||
}
|
||||
});
|
||||
Executable
+283
@@ -0,0 +1,283 @@
|
||||
;; Copyright (c) Nicola Mometto, Rich Hickey & contributors.
|
||||
;; The use and distribution terms for this software are covered by the
|
||||
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
;; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
;; By using this software in any fashion, you are agreeing to be bound by
|
||||
;; the terms of this license.
|
||||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns ^{:doc "Protocols and default Reader types implementation"
|
||||
:author "Bronsa"}
|
||||
cljs.tools.reader.reader-types
|
||||
(:refer-clojure :exclude [char read-line])
|
||||
(:require [cljs.tools.reader.impl.utils :refer [char whitespace? newline?]]
|
||||
[goog.string])
|
||||
(:import goog.string.StringBuffer))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; reader protocols
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defprotocol Reader
|
||||
(read-char [reader]
|
||||
"Returns the next char from the Reader, nil if the end of stream has been reached")
|
||||
(peek-char [reader]
|
||||
"Returns the next char from the Reader without removing it from the reader stream"))
|
||||
|
||||
(defprotocol IPushbackReader
|
||||
(unread [reader ch]
|
||||
"Pushes back a single character on to the stream"))
|
||||
|
||||
(defprotocol IndexingReader
|
||||
(get-line-number [reader]
|
||||
"Returns the line number of the next character to be read from the stream")
|
||||
(get-column-number [reader]
|
||||
"Returns the column number of the next character to be read from the stream")
|
||||
(get-file-name [reader]
|
||||
"Returns the file name the reader is reading from, or nil"))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; reader deftypes
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(deftype StringReader
|
||||
[s s-len ^:mutable s-pos]
|
||||
Reader
|
||||
(read-char [reader]
|
||||
(when (> s-len s-pos)
|
||||
(let [r (.charAt s s-pos)]
|
||||
(set! s-pos (inc s-pos))
|
||||
r)))
|
||||
(peek-char [reader]
|
||||
(when (> s-len s-pos)
|
||||
(.charAt s s-pos))))
|
||||
|
||||
(deftype NodeReadableReader [readable ^:mutable buf]
|
||||
Reader
|
||||
(read-char [reader]
|
||||
(if buf
|
||||
(let [c (aget buf 0)]
|
||||
(set! buf nil)
|
||||
(char c))
|
||||
(let [c (str (.read readable 1))]
|
||||
(when c
|
||||
(char c)))))
|
||||
(peek-char [reader]
|
||||
(when-not buf
|
||||
(set! buf (str (.read readable 1))))
|
||||
(when buf
|
||||
(char (aget buf 0)))))
|
||||
|
||||
(deftype PushbackReader
|
||||
[^not-native rdr buf buf-len ^:mutable buf-pos]
|
||||
Reader
|
||||
(read-char [reader]
|
||||
(let [c (if (< buf-pos buf-len)
|
||||
(aget buf buf-pos)
|
||||
(read-char rdr))]
|
||||
(when (< buf-pos buf-len)
|
||||
(set! buf-pos (inc buf-pos)))
|
||||
(char c)))
|
||||
(peek-char [reader]
|
||||
(let [c (if (< buf-pos buf-len)
|
||||
(aget buf buf-pos)
|
||||
(peek-char rdr))]
|
||||
(char c)))
|
||||
IPushbackReader
|
||||
(unread [reader ch]
|
||||
(when ch
|
||||
(if (zero? buf-pos) (throw (js/Error. "Pushback buffer is full")))
|
||||
(set! buf-pos (dec buf-pos))
|
||||
(aset buf buf-pos ch))))
|
||||
|
||||
(defn- normalize-newline [^not-native rdr ch]
|
||||
(if (identical? \return ch)
|
||||
(let [c (peek-char rdr)]
|
||||
(when (or (identical? \formfeed c)
|
||||
(identical? \newline c))
|
||||
(read-char rdr))
|
||||
\newline)
|
||||
ch))
|
||||
|
||||
(deftype IndexingPushbackReader
|
||||
[^not-native rdr ^:mutable line ^:mutable column
|
||||
^:mutable line-start? ^:mutable prev
|
||||
^:mutable prev-column file-name]
|
||||
Reader
|
||||
(read-char [reader]
|
||||
(when-let [ch (read-char rdr)]
|
||||
(let [ch (normalize-newline rdr ch)]
|
||||
(set! prev line-start?)
|
||||
(set! line-start? (newline? ch))
|
||||
(when line-start?
|
||||
(set! prev-column column)
|
||||
(set! column 0)
|
||||
(set! line (inc line)))
|
||||
(set! column (inc column))
|
||||
ch)))
|
||||
|
||||
(peek-char [reader]
|
||||
(peek-char rdr))
|
||||
|
||||
IPushbackReader
|
||||
(unread [reader ch]
|
||||
(if line-start?
|
||||
(do (set! line (dec line))
|
||||
(set! column prev-column))
|
||||
(set! column (dec column)))
|
||||
(set! line-start? prev)
|
||||
(unread rdr ch))
|
||||
|
||||
IndexingReader
|
||||
(get-line-number [reader] (int line))
|
||||
(get-column-number [reader] (int column))
|
||||
(get-file-name [reader] file-name))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Source Logging support
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defn merge-meta
|
||||
"Returns an object of the same type and value as `obj`, with its
|
||||
metadata merged over `m`."
|
||||
[obj m]
|
||||
(let [orig-meta (meta obj)]
|
||||
(with-meta obj (merge m (dissoc orig-meta :source)))))
|
||||
|
||||
(defn- peek-source-log
|
||||
"Returns a string containing the contents of the top most source
|
||||
logging frame."
|
||||
[frames]
|
||||
(subs (str (:buffer frames)) (first (:offset frames))))
|
||||
|
||||
(defn- log-source-char
|
||||
"Logs `char` to all currently active source logging frames."
|
||||
[frames char]
|
||||
(when-let [buffer (:buffer frames)]
|
||||
(.append buffer char)))
|
||||
|
||||
(defn- drop-last-logged-char
|
||||
"Removes the last logged character from all currently active source
|
||||
logging frames. Called when pushing a character back."
|
||||
[frames]
|
||||
(when-let [buffer (:buffer frames)]
|
||||
(.set buffer (subs (str buffer) 0 (dec (.getLength buffer))))))
|
||||
|
||||
(deftype SourceLoggingPushbackReader
|
||||
[^not-native rdr ^:mutable line ^:mutable column
|
||||
^:mutable line-start? ^:mutable prev
|
||||
^:mutable prev-column file-name frames]
|
||||
Reader
|
||||
(read-char [reader]
|
||||
(when-let [ch (read-char rdr)]
|
||||
(let [ch (normalize-newline rdr ch)]
|
||||
(set! prev line-start?)
|
||||
(set! line-start? (newline? ch))
|
||||
(when line-start?
|
||||
(set! prev-column column)
|
||||
(set! column 0)
|
||||
(set! line (inc line)))
|
||||
(set! column (inc column))
|
||||
(log-source-char @frames ch)
|
||||
ch)))
|
||||
|
||||
(peek-char [reader]
|
||||
(peek-char rdr))
|
||||
|
||||
IPushbackReader
|
||||
(unread [reader ch]
|
||||
(if line-start?
|
||||
(do (set! line (dec line))
|
||||
(set! column prev-column))
|
||||
(set! column (dec column)))
|
||||
(set! line-start? prev)
|
||||
(when ch
|
||||
(drop-last-logged-char @frames))
|
||||
(unread rdr ch))
|
||||
|
||||
IndexingReader
|
||||
(get-line-number [reader] (int line))
|
||||
(get-column-number [reader] (int column))
|
||||
(get-file-name [reader] file-name))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Public API
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; fast check for provided implementations
|
||||
(defn indexing-reader?
|
||||
"Returns true if the reader satisfies IndexingReader"
|
||||
[rdr]
|
||||
(implements? IndexingReader rdr))
|
||||
|
||||
(defn string-reader
|
||||
"Creates a StringReader from a given string"
|
||||
([s]
|
||||
(StringReader. s (count s) 0)))
|
||||
|
||||
(defn string-push-back-reader
|
||||
"Creates a PushbackReader from a given string"
|
||||
([s]
|
||||
(string-push-back-reader s 1))
|
||||
([s buf-len]
|
||||
(PushbackReader. (string-reader s) (object-array buf-len) buf-len buf-len)))
|
||||
|
||||
(defn node-readable-push-back-reader [readable]
|
||||
(PushbackReader. (NodeReadableReader. readable nil) (object-array 1) 1 1))
|
||||
|
||||
(defn indexing-push-back-reader
|
||||
"Creates an IndexingPushbackReader from a given string or PushbackReader"
|
||||
([s-or-rdr]
|
||||
(indexing-push-back-reader s-or-rdr 1))
|
||||
([s-or-rdr buf-len]
|
||||
(indexing-push-back-reader s-or-rdr buf-len nil))
|
||||
([s-or-rdr buf-len file-name]
|
||||
(IndexingPushbackReader.
|
||||
(if (string? s-or-rdr) (string-push-back-reader s-or-rdr buf-len) s-or-rdr) 1 1 true nil 0 file-name)))
|
||||
|
||||
(defn source-logging-push-back-reader
|
||||
"Creates a SourceLoggingPushbackReader from a given string or PushbackReader"
|
||||
([s-or-rdr]
|
||||
(source-logging-push-back-reader s-or-rdr 1))
|
||||
([s-or-rdr buf-len]
|
||||
(source-logging-push-back-reader s-or-rdr buf-len nil))
|
||||
([s-or-rdr buf-len file-name]
|
||||
(SourceLoggingPushbackReader.
|
||||
(if (string? s-or-rdr) (string-push-back-reader s-or-rdr buf-len) s-or-rdr)
|
||||
1
|
||||
1
|
||||
true
|
||||
nil
|
||||
0
|
||||
file-name
|
||||
(atom {:buffer (StringBuffer.) :offset '(0)}))))
|
||||
|
||||
(defn read-line
|
||||
"Reads a line from the reader or from *in* if no reader is specified"
|
||||
([^not-native rdr]
|
||||
(loop [c (read-char rdr) s (StringBuffer.)]
|
||||
(if (newline? c)
|
||||
(str s)
|
||||
(recur (read-char rdr) (.append s c))))))
|
||||
|
||||
(defn ^boolean source-logging-reader?
|
||||
[rdr]
|
||||
(instance? SourceLoggingPushbackReader rdr))
|
||||
|
||||
(defn ^boolean line-start?
|
||||
"Returns true if rdr is an IndexingReader and the current char starts a new line"
|
||||
[^not-native rdr]
|
||||
(when (indexing-reader? rdr)
|
||||
(== 1 (get-column-number rdr))))
|
||||
|
||||
(defn log-source*
|
||||
[reader f]
|
||||
(let [buffer (:buffer @(.-frames reader))]
|
||||
(try
|
||||
(swap! (.-frames reader) update-in [:offset] conj (.getLength buffer))
|
||||
(let [ret (f)]
|
||||
(if (implements? IMeta ret)
|
||||
(merge-meta ret {:source (peek-source-log @ (.-frames reader))})
|
||||
ret))
|
||||
(finally
|
||||
(swap! (.-frames reader) update-in [:offset] rest)))))
|
||||
|
||||
Executable
+815
@@ -0,0 +1,815 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('cljs.tools.reader.reader_types');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('cljs.tools.reader.impl.utils');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.string.StringBuffer');
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.tools.reader.reader_types.Reader = function(){};
|
||||
|
||||
var cljs$tools$reader$reader_types$Reader$read_char$dyn_5273 = (function (reader){
|
||||
var x__5393__auto__ = (((reader == null))?null:reader);
|
||||
var m__5394__auto__ = (cljs.tools.reader.reader_types.read_char[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5394__auto__.call(null,reader));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.tools.reader.reader_types.read_char["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5392__auto__.call(null,reader));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Reader.read-char",reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Returns the next char from the Reader, nil if the end of stream has been reached
|
||||
*/
|
||||
cljs.tools.reader.reader_types.read_char = (function cljs$tools$reader$reader_types$read_char(reader){
|
||||
if((((!((reader == null)))) && ((!((reader.cljs$tools$reader$reader_types$Reader$read_char$arity$1 == null)))))){
|
||||
return reader.cljs$tools$reader$reader_types$Reader$read_char$arity$1(reader);
|
||||
} else {
|
||||
return cljs$tools$reader$reader_types$Reader$read_char$dyn_5273(reader);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$tools$reader$reader_types$Reader$peek_char$dyn_5274 = (function (reader){
|
||||
var x__5393__auto__ = (((reader == null))?null:reader);
|
||||
var m__5394__auto__ = (cljs.tools.reader.reader_types.peek_char[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5394__auto__.call(null,reader));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.tools.reader.reader_types.peek_char["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5392__auto__.call(null,reader));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("Reader.peek-char",reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Returns the next char from the Reader without removing it from the reader stream
|
||||
*/
|
||||
cljs.tools.reader.reader_types.peek_char = (function cljs$tools$reader$reader_types$peek_char(reader){
|
||||
if((((!((reader == null)))) && ((!((reader.cljs$tools$reader$reader_types$Reader$peek_char$arity$1 == null)))))){
|
||||
return reader.cljs$tools$reader$reader_types$Reader$peek_char$arity$1(reader);
|
||||
} else {
|
||||
return cljs$tools$reader$reader_types$Reader$peek_char$dyn_5274(reader);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.tools.reader.reader_types.IPushbackReader = function(){};
|
||||
|
||||
var cljs$tools$reader$reader_types$IPushbackReader$unread$dyn_5275 = (function (reader,ch){
|
||||
var x__5393__auto__ = (((reader == null))?null:reader);
|
||||
var m__5394__auto__ = (cljs.tools.reader.reader_types.unread[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$2 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$2(reader,ch) : m__5394__auto__.call(null,reader,ch));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.tools.reader.reader_types.unread["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$2 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$2(reader,ch) : m__5392__auto__.call(null,reader,ch));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("IPushbackReader.unread",reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Pushes back a single character on to the stream
|
||||
*/
|
||||
cljs.tools.reader.reader_types.unread = (function cljs$tools$reader$reader_types$unread(reader,ch){
|
||||
if((((!((reader == null)))) && ((!((reader.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2 == null)))))){
|
||||
return reader.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2(reader,ch);
|
||||
} else {
|
||||
return cljs$tools$reader$reader_types$IPushbackReader$unread$dyn_5275(reader,ch);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
cljs.tools.reader.reader_types.IndexingReader = function(){};
|
||||
|
||||
var cljs$tools$reader$reader_types$IndexingReader$get_line_number$dyn_5276 = (function (reader){
|
||||
var x__5393__auto__ = (((reader == null))?null:reader);
|
||||
var m__5394__auto__ = (cljs.tools.reader.reader_types.get_line_number[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5394__auto__.call(null,reader));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.tools.reader.reader_types.get_line_number["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5392__auto__.call(null,reader));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("IndexingReader.get-line-number",reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Returns the line number of the next character to be read from the stream
|
||||
*/
|
||||
cljs.tools.reader.reader_types.get_line_number = (function cljs$tools$reader$reader_types$get_line_number(reader){
|
||||
if((((!((reader == null)))) && ((!((reader.cljs$tools$reader$reader_types$IndexingReader$get_line_number$arity$1 == null)))))){
|
||||
return reader.cljs$tools$reader$reader_types$IndexingReader$get_line_number$arity$1(reader);
|
||||
} else {
|
||||
return cljs$tools$reader$reader_types$IndexingReader$get_line_number$dyn_5276(reader);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$tools$reader$reader_types$IndexingReader$get_column_number$dyn_5277 = (function (reader){
|
||||
var x__5393__auto__ = (((reader == null))?null:reader);
|
||||
var m__5394__auto__ = (cljs.tools.reader.reader_types.get_column_number[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5394__auto__.call(null,reader));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.tools.reader.reader_types.get_column_number["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5392__auto__.call(null,reader));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("IndexingReader.get-column-number",reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Returns the column number of the next character to be read from the stream
|
||||
*/
|
||||
cljs.tools.reader.reader_types.get_column_number = (function cljs$tools$reader$reader_types$get_column_number(reader){
|
||||
if((((!((reader == null)))) && ((!((reader.cljs$tools$reader$reader_types$IndexingReader$get_column_number$arity$1 == null)))))){
|
||||
return reader.cljs$tools$reader$reader_types$IndexingReader$get_column_number$arity$1(reader);
|
||||
} else {
|
||||
return cljs$tools$reader$reader_types$IndexingReader$get_column_number$dyn_5277(reader);
|
||||
}
|
||||
});
|
||||
|
||||
var cljs$tools$reader$reader_types$IndexingReader$get_file_name$dyn_5278 = (function (reader){
|
||||
var x__5393__auto__ = (((reader == null))?null:reader);
|
||||
var m__5394__auto__ = (cljs.tools.reader.reader_types.get_file_name[goog.typeOf(x__5393__auto__)]);
|
||||
if((!((m__5394__auto__ == null)))){
|
||||
return (m__5394__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5394__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5394__auto__.call(null,reader));
|
||||
} else {
|
||||
var m__5392__auto__ = (cljs.tools.reader.reader_types.get_file_name["_"]);
|
||||
if((!((m__5392__auto__ == null)))){
|
||||
return (m__5392__auto__.cljs$core$IFn$_invoke$arity$1 ? m__5392__auto__.cljs$core$IFn$_invoke$arity$1(reader) : m__5392__auto__.call(null,reader));
|
||||
} else {
|
||||
throw cljs.core.missing_protocol("IndexingReader.get-file-name",reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Returns the file name the reader is reading from, or nil
|
||||
*/
|
||||
cljs.tools.reader.reader_types.get_file_name = (function cljs$tools$reader$reader_types$get_file_name(reader){
|
||||
if((((!((reader == null)))) && ((!((reader.cljs$tools$reader$reader_types$IndexingReader$get_file_name$arity$1 == null)))))){
|
||||
return reader.cljs$tools$reader$reader_types$IndexingReader$get_file_name$arity$1(reader);
|
||||
} else {
|
||||
return cljs$tools$reader$reader_types$IndexingReader$get_file_name$dyn_5278(reader);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.tools.reader.reader_types.Reader}
|
||||
*/
|
||||
cljs.tools.reader.reader_types.StringReader = (function (s,s_len,s_pos){
|
||||
this.s = s;
|
||||
this.s_len = s_len;
|
||||
this.s_pos = s_pos;
|
||||
});
|
||||
(cljs.tools.reader.reader_types.StringReader.prototype.cljs$tools$reader$reader_types$Reader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.StringReader.prototype.cljs$tools$reader$reader_types$Reader$read_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if((self__.s_len > self__.s_pos)){
|
||||
var r = self__.s.charAt(self__.s_pos);
|
||||
(self__.s_pos = (self__.s_pos + (1)));
|
||||
|
||||
return r;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.StringReader.prototype.cljs$tools$reader$reader_types$Reader$peek_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if((self__.s_len > self__.s_pos)){
|
||||
return self__.s.charAt(self__.s_pos);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.StringReader.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 3, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$s,cljs.core.cst$sym$s_DASH_len,cljs.core.with_meta(cljs.core.cst$sym$s_DASH_pos,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null))], null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.StringReader.cljs$lang$type = true);
|
||||
|
||||
(cljs.tools.reader.reader_types.StringReader.cljs$lang$ctorStr = "cljs.tools.reader.reader-types/StringReader");
|
||||
|
||||
(cljs.tools.reader.reader_types.StringReader.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.tools.reader.reader-types/StringReader");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.tools.reader.reader-types/StringReader.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.__GT_StringReader = (function cljs$tools$reader$reader_types$__GT_StringReader(s,s_len,s_pos){
|
||||
return (new cljs.tools.reader.reader_types.StringReader(s,s_len,s_pos));
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.tools.reader.reader_types.Reader}
|
||||
*/
|
||||
cljs.tools.reader.reader_types.NodeReadableReader = (function (readable,buf){
|
||||
this.readable = readable;
|
||||
this.buf = buf;
|
||||
});
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.prototype.cljs$tools$reader$reader_types$Reader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.prototype.cljs$tools$reader$reader_types$Reader$read_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if(cljs.core.truth_(self__.buf)){
|
||||
var c = (self__.buf[(0)]);
|
||||
(self__.buf = null);
|
||||
|
||||
return cljs.tools.reader.impl.utils.char$(c);
|
||||
} else {
|
||||
var c = cljs.core.str.cljs$core$IFn$_invoke$arity$1(self__.readable.read((1)));
|
||||
if(cljs.core.truth_(c)){
|
||||
return cljs.tools.reader.impl.utils.char$(c);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.prototype.cljs$tools$reader$reader_types$Reader$peek_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if(cljs.core.truth_(self__.buf)){
|
||||
} else {
|
||||
(self__.buf = cljs.core.str.cljs$core$IFn$_invoke$arity$1(self__.readable.read((1))));
|
||||
}
|
||||
|
||||
if(cljs.core.truth_(self__.buf)){
|
||||
return cljs.tools.reader.impl.utils.char$((self__.buf[(0)]));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$sym$readable,cljs.core.with_meta(cljs.core.cst$sym$buf,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null))], null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.cljs$lang$type = true);
|
||||
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.cljs$lang$ctorStr = "cljs.tools.reader.reader-types/NodeReadableReader");
|
||||
|
||||
(cljs.tools.reader.reader_types.NodeReadableReader.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.tools.reader.reader-types/NodeReadableReader");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.tools.reader.reader-types/NodeReadableReader.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.__GT_NodeReadableReader = (function cljs$tools$reader$reader_types$__GT_NodeReadableReader(readable,buf){
|
||||
return (new cljs.tools.reader.reader_types.NodeReadableReader(readable,buf));
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.tools.reader.reader_types.Reader}
|
||||
* @implements {cljs.tools.reader.reader_types.IPushbackReader}
|
||||
*/
|
||||
cljs.tools.reader.reader_types.PushbackReader = (function (rdr,buf,buf_len,buf_pos){
|
||||
this.rdr = rdr;
|
||||
this.buf = buf;
|
||||
this.buf_len = buf_len;
|
||||
this.buf_pos = buf_pos;
|
||||
});
|
||||
(cljs.tools.reader.reader_types.PushbackReader.prototype.cljs$tools$reader$reader_types$Reader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.prototype.cljs$tools$reader$reader_types$Reader$read_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
var c = (((self__.buf_pos < self__.buf_len))?(self__.buf[self__.buf_pos]):self__.rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null));
|
||||
if((self__.buf_pos < self__.buf_len)){
|
||||
(self__.buf_pos = (self__.buf_pos + (1)));
|
||||
} else {
|
||||
}
|
||||
|
||||
return cljs.tools.reader.impl.utils.char$(c);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.prototype.cljs$tools$reader$reader_types$Reader$peek_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
var c = (((self__.buf_pos < self__.buf_len))?(self__.buf[self__.buf_pos]):self__.rdr.cljs$tools$reader$reader_types$Reader$peek_char$arity$1(null));
|
||||
return cljs.tools.reader.impl.utils.char$(c);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.prototype.cljs$tools$reader$reader_types$IPushbackReader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.prototype.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2 = (function (reader,ch){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if(cljs.core.truth_(ch)){
|
||||
if((self__.buf_pos === (0))){
|
||||
throw (new Error("Pushback buffer is full"));
|
||||
} else {
|
||||
}
|
||||
|
||||
(self__.buf_pos = (self__.buf_pos - (1)));
|
||||
|
||||
return (self__.buf[self__.buf_pos] = ch);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 4, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.with_meta(cljs.core.cst$sym$rdr,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,cljs.core.cst$sym$not_DASH_native], null)),cljs.core.cst$sym$buf,cljs.core.cst$sym$buf_DASH_len,cljs.core.with_meta(cljs.core.cst$sym$buf_DASH_pos,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null))], null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.cljs$lang$type = true);
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.cljs$lang$ctorStr = "cljs.tools.reader.reader-types/PushbackReader");
|
||||
|
||||
(cljs.tools.reader.reader_types.PushbackReader.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.tools.reader.reader-types/PushbackReader");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.tools.reader.reader-types/PushbackReader.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.__GT_PushbackReader = (function cljs$tools$reader$reader_types$__GT_PushbackReader(rdr,buf,buf_len,buf_pos){
|
||||
return (new cljs.tools.reader.reader_types.PushbackReader(rdr,buf,buf_len,buf_pos));
|
||||
});
|
||||
|
||||
cljs.tools.reader.reader_types.normalize_newline = (function cljs$tools$reader$reader_types$normalize_newline(rdr,ch){
|
||||
if(("\r" === ch)){
|
||||
var c = rdr.cljs$tools$reader$reader_types$Reader$peek_char$arity$1(null);
|
||||
if(((("\f" === c)) || (("\n" === c)))){
|
||||
rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
} else {
|
||||
}
|
||||
|
||||
return "\n";
|
||||
} else {
|
||||
return ch;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.tools.reader.reader_types.IndexingReader}
|
||||
* @implements {cljs.tools.reader.reader_types.Reader}
|
||||
* @implements {cljs.tools.reader.reader_types.IPushbackReader}
|
||||
*/
|
||||
cljs.tools.reader.reader_types.IndexingPushbackReader = (function (rdr,line,column,line_start_QMARK_,prev,prev_column,file_name){
|
||||
this.rdr = rdr;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.line_start_QMARK_ = line_start_QMARK_;
|
||||
this.prev = prev;
|
||||
this.prev_column = prev_column;
|
||||
this.file_name = file_name;
|
||||
});
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$Reader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$Reader$read_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
var temp__4657__auto__ = self__.rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
if(cljs.core.truth_(temp__4657__auto__)){
|
||||
var ch = temp__4657__auto__;
|
||||
var ch__$1 = cljs.tools.reader.reader_types.normalize_newline(self__.rdr,ch);
|
||||
(self__.prev = self__.line_start_QMARK_);
|
||||
|
||||
(self__.line_start_QMARK_ = cljs.tools.reader.impl.utils.newline_QMARK_(ch__$1));
|
||||
|
||||
if(cljs.core.truth_(self__.line_start_QMARK_)){
|
||||
(self__.prev_column = self__.column);
|
||||
|
||||
(self__.column = (0));
|
||||
|
||||
(self__.line = (self__.line + (1)));
|
||||
} else {
|
||||
}
|
||||
|
||||
(self__.column = (self__.column + (1)));
|
||||
|
||||
return ch__$1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$Reader$peek_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return self__.rdr.cljs$tools$reader$reader_types$Reader$peek_char$arity$1(null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$IPushbackReader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2 = (function (reader,ch){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if(cljs.core.truth_(self__.line_start_QMARK_)){
|
||||
(self__.line = (self__.line - (1)));
|
||||
|
||||
(self__.column = self__.prev_column);
|
||||
} else {
|
||||
(self__.column = (self__.column - (1)));
|
||||
}
|
||||
|
||||
(self__.line_start_QMARK_ = self__.prev);
|
||||
|
||||
return self__.rdr.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2(null,ch);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$get_line_number$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return (self__.line | (0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$get_column_number$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return (self__.column | (0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$get_file_name$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return self__.file_name;
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 7, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.with_meta(cljs.core.cst$sym$rdr,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,cljs.core.cst$sym$not_DASH_native], null)),cljs.core.with_meta(cljs.core.cst$sym$line,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$column,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$line_DASH_start_QMARK_,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$prev,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$prev_DASH_column,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.cst$sym$file_DASH_name], null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.cljs$lang$type = true);
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.cljs$lang$ctorStr = "cljs.tools.reader.reader-types/IndexingPushbackReader");
|
||||
|
||||
(cljs.tools.reader.reader_types.IndexingPushbackReader.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.tools.reader.reader-types/IndexingPushbackReader");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.tools.reader.reader-types/IndexingPushbackReader.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.__GT_IndexingPushbackReader = (function cljs$tools$reader$reader_types$__GT_IndexingPushbackReader(rdr,line,column,line_start_QMARK_,prev,prev_column,file_name){
|
||||
return (new cljs.tools.reader.reader_types.IndexingPushbackReader(rdr,line,column,line_start_QMARK_,prev,prev_column,file_name));
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns an object of the same type and value as `obj`, with its
|
||||
* metadata merged over `m`.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.merge_meta = (function cljs$tools$reader$reader_types$merge_meta(obj,m){
|
||||
var orig_meta = cljs.core.meta(obj);
|
||||
return cljs.core.with_meta(obj,cljs.core.merge.cljs$core$IFn$_invoke$arity$variadic(cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([m,cljs.core.dissoc.cljs$core$IFn$_invoke$arity$2(orig_meta,cljs.core.cst$kw$source)], 0)));
|
||||
});
|
||||
/**
|
||||
* Returns a string containing the contents of the top most source
|
||||
* logging frame.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.peek_source_log = (function cljs$tools$reader$reader_types$peek_source_log(frames){
|
||||
return cljs.core.subs.cljs$core$IFn$_invoke$arity$2(cljs.core.str.cljs$core$IFn$_invoke$arity$1(cljs.core.cst$kw$buffer.cljs$core$IFn$_invoke$arity$1(frames)),cljs.core.first(cljs.core.cst$kw$offset.cljs$core$IFn$_invoke$arity$1(frames)));
|
||||
});
|
||||
/**
|
||||
* Logs `char` to all currently active source logging frames.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.log_source_char = (function cljs$tools$reader$reader_types$log_source_char(frames,char$){
|
||||
var temp__4657__auto__ = cljs.core.cst$kw$buffer.cljs$core$IFn$_invoke$arity$1(frames);
|
||||
if(cljs.core.truth_(temp__4657__auto__)){
|
||||
var buffer = temp__4657__auto__;
|
||||
return buffer.append(char$);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Removes the last logged character from all currently active source
|
||||
* logging frames. Called when pushing a character back.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.drop_last_logged_char = (function cljs$tools$reader$reader_types$drop_last_logged_char(frames){
|
||||
var temp__4657__auto__ = cljs.core.cst$kw$buffer.cljs$core$IFn$_invoke$arity$1(frames);
|
||||
if(cljs.core.truth_(temp__4657__auto__)){
|
||||
var buffer = temp__4657__auto__;
|
||||
return buffer.set(cljs.core.subs.cljs$core$IFn$_invoke$arity$3(cljs.core.str.cljs$core$IFn$_invoke$arity$1(buffer),(0),(buffer.getLength() - (1))));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {cljs.tools.reader.reader_types.IndexingReader}
|
||||
* @implements {cljs.tools.reader.reader_types.Reader}
|
||||
* @implements {cljs.tools.reader.reader_types.IPushbackReader}
|
||||
*/
|
||||
cljs.tools.reader.reader_types.SourceLoggingPushbackReader = (function (rdr,line,column,line_start_QMARK_,prev,prev_column,file_name,frames){
|
||||
this.rdr = rdr;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.line_start_QMARK_ = line_start_QMARK_;
|
||||
this.prev = prev;
|
||||
this.prev_column = prev_column;
|
||||
this.file_name = file_name;
|
||||
this.frames = frames;
|
||||
});
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$Reader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$Reader$read_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
var temp__4657__auto__ = self__.rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
if(cljs.core.truth_(temp__4657__auto__)){
|
||||
var ch = temp__4657__auto__;
|
||||
var ch__$1 = cljs.tools.reader.reader_types.normalize_newline(self__.rdr,ch);
|
||||
(self__.prev = self__.line_start_QMARK_);
|
||||
|
||||
(self__.line_start_QMARK_ = cljs.tools.reader.impl.utils.newline_QMARK_(ch__$1));
|
||||
|
||||
if(cljs.core.truth_(self__.line_start_QMARK_)){
|
||||
(self__.prev_column = self__.column);
|
||||
|
||||
(self__.column = (0));
|
||||
|
||||
(self__.line = (self__.line + (1)));
|
||||
} else {
|
||||
}
|
||||
|
||||
(self__.column = (self__.column + (1)));
|
||||
|
||||
cljs.tools.reader.reader_types.log_source_char(cljs.core.deref(self__.frames),ch__$1);
|
||||
|
||||
return ch__$1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$Reader$peek_char$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return self__.rdr.cljs$tools$reader$reader_types$Reader$peek_char$arity$1(null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$IPushbackReader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2 = (function (reader,ch){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
if(cljs.core.truth_(self__.line_start_QMARK_)){
|
||||
(self__.line = (self__.line - (1)));
|
||||
|
||||
(self__.column = self__.prev_column);
|
||||
} else {
|
||||
(self__.column = (self__.column - (1)));
|
||||
}
|
||||
|
||||
(self__.line_start_QMARK_ = self__.prev);
|
||||
|
||||
if(cljs.core.truth_(ch)){
|
||||
cljs.tools.reader.reader_types.drop_last_logged_char(cljs.core.deref(self__.frames));
|
||||
} else {
|
||||
}
|
||||
|
||||
return self__.rdr.cljs$tools$reader$reader_types$IPushbackReader$unread$arity$2(null,ch);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$ = cljs.core.PROTOCOL_SENTINEL);
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$get_line_number$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return (self__.line | (0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$get_column_number$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return (self__.column | (0));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.prototype.cljs$tools$reader$reader_types$IndexingReader$get_file_name$arity$1 = (function (reader){
|
||||
var self__ = this;
|
||||
var reader__$1 = this;
|
||||
return self__.file_name;
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.getBasis = (function (){
|
||||
return new cljs.core.PersistentVector(null, 8, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.with_meta(cljs.core.cst$sym$rdr,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$tag,cljs.core.cst$sym$not_DASH_native], null)),cljs.core.with_meta(cljs.core.cst$sym$line,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$column,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$line_DASH_start_QMARK_,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$prev,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.with_meta(cljs.core.cst$sym$prev_DASH_column,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$mutable,true], null)),cljs.core.cst$sym$file_DASH_name,cljs.core.cst$sym$frames], null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.cljs$lang$type = true);
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.cljs$lang$ctorStr = "cljs.tools.reader.reader-types/SourceLoggingPushbackReader");
|
||||
|
||||
(cljs.tools.reader.reader_types.SourceLoggingPushbackReader.cljs$lang$ctorPrWriter = (function (this__5330__auto__,writer__5331__auto__,opt__5332__auto__){
|
||||
return cljs.core._write(writer__5331__auto__,"cljs.tools.reader.reader-types/SourceLoggingPushbackReader");
|
||||
}));
|
||||
|
||||
/**
|
||||
* Positional factory function for cljs.tools.reader.reader-types/SourceLoggingPushbackReader.
|
||||
*/
|
||||
cljs.tools.reader.reader_types.__GT_SourceLoggingPushbackReader = (function cljs$tools$reader$reader_types$__GT_SourceLoggingPushbackReader(rdr,line,column,line_start_QMARK_,prev,prev_column,file_name,frames){
|
||||
return (new cljs.tools.reader.reader_types.SourceLoggingPushbackReader(rdr,line,column,line_start_QMARK_,prev,prev_column,file_name,frames));
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns true if the reader satisfies IndexingReader
|
||||
*/
|
||||
cljs.tools.reader.reader_types.indexing_reader_QMARK_ = (function cljs$tools$reader$reader_types$indexing_reader_QMARK_(rdr){
|
||||
if((!((rdr == null)))){
|
||||
if(((false) || ((cljs.core.PROTOCOL_SENTINEL === rdr.cljs$tools$reader$reader_types$IndexingReader$)))){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Creates a StringReader from a given string
|
||||
*/
|
||||
cljs.tools.reader.reader_types.string_reader = (function cljs$tools$reader$reader_types$string_reader(s){
|
||||
return (new cljs.tools.reader.reader_types.StringReader(s,cljs.core.count(s),(0)));
|
||||
});
|
||||
/**
|
||||
* Creates a PushbackReader from a given string
|
||||
*/
|
||||
cljs.tools.reader.reader_types.string_push_back_reader = (function cljs$tools$reader$reader_types$string_push_back_reader(var_args){
|
||||
var G__5281 = arguments.length;
|
||||
switch (G__5281) {
|
||||
case 1:
|
||||
return cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$1 = (function (s){
|
||||
return cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$2(s,(1));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$2 = (function (s,buf_len){
|
||||
return (new cljs.tools.reader.reader_types.PushbackReader(cljs.tools.reader.reader_types.string_reader(s),cljs.core.object_array.cljs$core$IFn$_invoke$arity$1(buf_len),buf_len,buf_len));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.string_push_back_reader.cljs$lang$maxFixedArity = 2);
|
||||
|
||||
cljs.tools.reader.reader_types.node_readable_push_back_reader = (function cljs$tools$reader$reader_types$node_readable_push_back_reader(readable){
|
||||
return (new cljs.tools.reader.reader_types.PushbackReader((new cljs.tools.reader.reader_types.NodeReadableReader(readable,null)),cljs.core.object_array.cljs$core$IFn$_invoke$arity$1((1)),(1),(1)));
|
||||
});
|
||||
/**
|
||||
* Creates an IndexingPushbackReader from a given string or PushbackReader
|
||||
*/
|
||||
cljs.tools.reader.reader_types.indexing_push_back_reader = (function cljs$tools$reader$reader_types$indexing_push_back_reader(var_args){
|
||||
var G__5284 = arguments.length;
|
||||
switch (G__5284) {
|
||||
case 1:
|
||||
return cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$1 = (function (s_or_rdr){
|
||||
return cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$2(s_or_rdr,(1));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$2 = (function (s_or_rdr,buf_len){
|
||||
return cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$3(s_or_rdr,buf_len,null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$core$IFn$_invoke$arity$3 = (function (s_or_rdr,buf_len,file_name){
|
||||
return (new cljs.tools.reader.reader_types.IndexingPushbackReader(((typeof s_or_rdr === 'string')?cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$2(s_or_rdr,buf_len):s_or_rdr),(1),(1),true,null,(0),file_name));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.indexing_push_back_reader.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
/**
|
||||
* Creates a SourceLoggingPushbackReader from a given string or PushbackReader
|
||||
*/
|
||||
cljs.tools.reader.reader_types.source_logging_push_back_reader = (function cljs$tools$reader$reader_types$source_logging_push_back_reader(var_args){
|
||||
var G__5287 = arguments.length;
|
||||
switch (G__5287) {
|
||||
case 1:
|
||||
return cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$1 = (function (s_or_rdr){
|
||||
return cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$2(s_or_rdr,(1));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$2 = (function (s_or_rdr,buf_len){
|
||||
return cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$3(s_or_rdr,buf_len,null);
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$core$IFn$_invoke$arity$3 = (function (s_or_rdr,buf_len,file_name){
|
||||
return (new cljs.tools.reader.reader_types.SourceLoggingPushbackReader(((typeof s_or_rdr === 'string')?cljs.tools.reader.reader_types.string_push_back_reader.cljs$core$IFn$_invoke$arity$2(s_or_rdr,buf_len):s_or_rdr),(1),(1),true,null,(0),file_name,cljs.core.atom.cljs$core$IFn$_invoke$arity$1(new cljs.core.PersistentArrayMap(null, 2, [cljs.core.cst$kw$buffer,(new goog.string.StringBuffer()),cljs.core.cst$kw$offset,cljs.core.list((0))], null))));
|
||||
}));
|
||||
|
||||
(cljs.tools.reader.reader_types.source_logging_push_back_reader.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
/**
|
||||
* Reads a line from the reader or from *in* if no reader is specified
|
||||
*/
|
||||
cljs.tools.reader.reader_types.read_line = (function cljs$tools$reader$reader_types$read_line(rdr){
|
||||
var c = rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
var s = (new goog.string.StringBuffer());
|
||||
while(true){
|
||||
if(cljs.tools.reader.impl.utils.newline_QMARK_(c)){
|
||||
return cljs.core.str.cljs$core$IFn$_invoke$arity$1(s);
|
||||
} else {
|
||||
var G__5289 = rdr.cljs$tools$reader$reader_types$Reader$read_char$arity$1(null);
|
||||
var G__5290 = s.append(c);
|
||||
c = G__5289;
|
||||
s = G__5290;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.reader_types.source_logging_reader_QMARK_ = (function cljs$tools$reader$reader_types$source_logging_reader_QMARK_(rdr){
|
||||
return (rdr instanceof cljs.tools.reader.reader_types.SourceLoggingPushbackReader);
|
||||
});
|
||||
/**
|
||||
* Returns true if rdr is an IndexingReader and the current char starts a new line
|
||||
*/
|
||||
cljs.tools.reader.reader_types.line_start_QMARK_ = (function cljs$tools$reader$reader_types$line_start_QMARK_(rdr){
|
||||
if(cljs.tools.reader.reader_types.indexing_reader_QMARK_(rdr)){
|
||||
return ((1) === rdr.cljs$tools$reader$reader_types$IndexingReader$get_column_number$arity$1(null));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
cljs.tools.reader.reader_types.log_source_STAR_ = (function cljs$tools$reader$reader_types$log_source_STAR_(reader,f){
|
||||
var buffer = cljs.core.cst$kw$buffer.cljs$core$IFn$_invoke$arity$1(cljs.core.deref(reader.frames));
|
||||
try{cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$variadic(reader.frames,cljs.core.update_in,new cljs.core.PersistentVector(null, 1, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$kw$offset], null),cljs.core.conj,cljs.core.prim_seq.cljs$core$IFn$_invoke$arity$2([buffer.getLength()], 0));
|
||||
|
||||
var ret = (f.cljs$core$IFn$_invoke$arity$0 ? f.cljs$core$IFn$_invoke$arity$0() : f.call(null));
|
||||
if((((!((ret == null))))?(((((ret.cljs$lang$protocol_mask$partition0$ & (131072))) || ((cljs.core.PROTOCOL_SENTINEL === ret.cljs$core$IMeta$))))?true:false):false)){
|
||||
return cljs.tools.reader.reader_types.merge_meta(ret,new cljs.core.PersistentArrayMap(null, 1, [cljs.core.cst$kw$source,cljs.tools.reader.reader_types.peek_source_log(cljs.core.deref(reader.frames))], null));
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}finally {cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$4(reader.frames,cljs.core.update_in,new cljs.core.PersistentVector(null, 1, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.cst$kw$offset], null),cljs.core.rest);
|
||||
}});
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
{:output-dir "build/js", :externs ["closure-js/externs"], :optimizations :advanced, :output-to "build/js/app.js", :output-wrapper true, :source-map "build/js/app.js.map", :libs ["closure-js/libs"], :pseudo-names true, :main "omgnata.prod", :pretty-print false}
|
||||
Executable
+19602
File diff suppressed because it is too large
Load Diff
Executable
+290
@@ -0,0 +1,290 @@
|
||||
; Copyright (c) Rich Hickey. All rights reserved.
|
||||
; The use and distribution terms for this software are covered by the
|
||||
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
; By using this software in any fashion, you are agreeing to be bound by
|
||||
; the terms of this license.
|
||||
; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns clojure.string
|
||||
(:refer-clojure :exclude [replace reverse])
|
||||
(:require [goog.string :as gstring])
|
||||
(:import [goog.string StringBuffer]))
|
||||
|
||||
(defn- seq-reverse
|
||||
[coll]
|
||||
(reduce conj () coll))
|
||||
|
||||
(def ^:private re-surrogate-pair
|
||||
(js/RegExp. "([\\uD800-\\uDBFF])([\\uDC00-\\uDFFF])" "g"))
|
||||
|
||||
(defn ^string reverse
|
||||
"Returns s with its characters reversed."
|
||||
[s]
|
||||
(-> (.replace s re-surrogate-pair "$2$1")
|
||||
(.. (split "") (reverse) (join ""))))
|
||||
|
||||
(defn- replace-all
|
||||
[s re replacement]
|
||||
(let [r (js/RegExp. (.-source re)
|
||||
(cond-> "g"
|
||||
(.-ignoreCase re) (str "i")
|
||||
(.-multiline re) (str "m")
|
||||
(.-unicode re) (str "u")))]
|
||||
(.replace s r replacement)))
|
||||
|
||||
(defn- replace-with
|
||||
[f]
|
||||
(fn [& args]
|
||||
(let [matches (drop-last 2 args)]
|
||||
(if (= (count matches) 1)
|
||||
(f (first matches))
|
||||
(f (vec matches))))))
|
||||
|
||||
(defn ^string replace
|
||||
"Replaces all instance of match with replacement in s.
|
||||
|
||||
match/replacement can be:
|
||||
|
||||
string / string
|
||||
pattern / (string or function of match).
|
||||
|
||||
See also replace-first.
|
||||
|
||||
The replacement is literal (i.e. none of its characters are treated
|
||||
specially) for all cases above except pattern / string.
|
||||
|
||||
For pattern / string, $1, $2, etc. in the replacement string are
|
||||
substituted with the string that matched the corresponding
|
||||
parenthesized group in the pattern.
|
||||
|
||||
Example:
|
||||
(clojure.string/replace \"Almost Pig Latin\" #\"\\b(\\w)(\\w+)\\b\" \"$2$1ay\")
|
||||
-> \"lmostAay igPay atinLay\""
|
||||
[s match replacement]
|
||||
(cond
|
||||
(string? match)
|
||||
(.replace s (js/RegExp. (gstring/regExpEscape match) "g") replacement)
|
||||
|
||||
(instance? js/RegExp match)
|
||||
(if (string? replacement)
|
||||
(replace-all s match replacement)
|
||||
(replace-all s match (replace-with replacement)))
|
||||
|
||||
:else (throw (str "Invalid match arg: " match))))
|
||||
|
||||
(defn ^string replace-first
|
||||
"Replaces the first instance of match with replacement in s.
|
||||
|
||||
match/replacement can be:
|
||||
|
||||
string / string
|
||||
pattern / (string or function of match).
|
||||
|
||||
See also replace.
|
||||
|
||||
The replacement is literal (i.e. none of its characters are treated
|
||||
specially) for all cases above except pattern / string.
|
||||
|
||||
For pattern / string, $1, $2, etc. in the replacement string are
|
||||
substituted with the string that matched the corresponding
|
||||
parenthesized group in the pattern.
|
||||
|
||||
Example:
|
||||
(clojure.string/replace-first \"swap first two words\"
|
||||
#\"(\\w+)(\\s+)(\\w+)\" \"$3$2$1\")
|
||||
-> \"first swap two words\""
|
||||
[s match replacement]
|
||||
(.replace s match replacement))
|
||||
|
||||
(defn join
|
||||
"Returns a string of all elements in coll, as returned by (seq coll),
|
||||
separated by an optional separator."
|
||||
([coll]
|
||||
(loop [sb (StringBuffer.) coll (seq coll)]
|
||||
(if-not (nil? coll)
|
||||
(recur (. sb (append (str (first coll)))) (next coll))
|
||||
^string (.toString sb))))
|
||||
([separator coll]
|
||||
(loop [sb (StringBuffer.) coll (seq coll)]
|
||||
(if-not (nil? coll)
|
||||
(do
|
||||
(. sb (append (str (first coll))))
|
||||
(let [coll (next coll)]
|
||||
(when-not (nil? coll)
|
||||
(. sb (append separator)))
|
||||
(recur sb coll)))
|
||||
^string (.toString sb)))))
|
||||
|
||||
(defn ^string upper-case
|
||||
"Converts string to all upper-case."
|
||||
[s]
|
||||
(.toUpperCase s))
|
||||
|
||||
(defn ^string lower-case
|
||||
"Converts string to all lower-case."
|
||||
[s]
|
||||
(.toLowerCase s))
|
||||
|
||||
(defn ^string capitalize
|
||||
"Converts first character of the string to upper-case, all other
|
||||
characters to lower-case."
|
||||
[s]
|
||||
(gstring/capitalize s))
|
||||
|
||||
;; The JavaScript split function takes a limit argument but the return
|
||||
;; value is not the same as the Java split function.
|
||||
;;
|
||||
;; Java: (.split "a-b-c" #"-" 2) => ["a" "b-c"]
|
||||
;; JavaScript: (.split "a-b-c" #"-" 2) => ["a" "b"]
|
||||
;;
|
||||
;; For consistency, the three arg version has been implemented to
|
||||
;; mimic Java's behavior.
|
||||
|
||||
(defn- pop-last-while-empty
|
||||
[v]
|
||||
(loop [v v]
|
||||
(if (identical? "" (peek v))
|
||||
(recur (pop v))
|
||||
v)))
|
||||
|
||||
(defn- discard-trailing-if-needed
|
||||
[limit v]
|
||||
(if (and (== 0 limit) (< 1 (count v)))
|
||||
(pop-last-while-empty v)
|
||||
v))
|
||||
|
||||
(defn- split-with-empty-regex
|
||||
[s limit]
|
||||
(if (or (<= limit 0) (>= limit (+ 2 (count s))))
|
||||
(conj (vec (cons "" (map str (seq s)))) "")
|
||||
(condp == limit
|
||||
1 (vector s)
|
||||
2 (vector "" s)
|
||||
(let [c (- limit 2)]
|
||||
(conj (vec (cons "" (subvec (vec (map str (seq s))) 0 c))) (subs s c))))))
|
||||
|
||||
(defn split
|
||||
"Splits string on a regular expression. Optional argument limit is
|
||||
the maximum number of parts. Not lazy. Returns vector of the parts.
|
||||
Trailing empty strings are not returned - pass limit of -1 to return all."
|
||||
([s re]
|
||||
(split s re 0))
|
||||
([s re limit]
|
||||
(discard-trailing-if-needed limit
|
||||
(if (identical? "/(?:)/" (str re))
|
||||
(split-with-empty-regex s limit)
|
||||
(if (< limit 1)
|
||||
(vec (.split (str s) re))
|
||||
(loop [s s
|
||||
limit limit
|
||||
parts []]
|
||||
(if (== 1 limit)
|
||||
(conj parts s)
|
||||
(let [m (re-find re s)]
|
||||
(if-not (nil? m)
|
||||
(let [index (.indexOf s m)]
|
||||
(recur (.substring s (+ index (count m)))
|
||||
(dec limit)
|
||||
(conj parts (.substring s 0 index))))
|
||||
(conj parts s))))))))))
|
||||
|
||||
(defn split-lines
|
||||
"Splits s on \\n or \\r\\n. Trailing empty lines are not returned."
|
||||
[s]
|
||||
(split s #"\n|\r\n"))
|
||||
|
||||
(defn ^string trim
|
||||
"Removes whitespace from both ends of string."
|
||||
[s]
|
||||
(gstring/trim s))
|
||||
|
||||
(defn ^string triml
|
||||
"Removes whitespace from the left side of string."
|
||||
[s]
|
||||
(gstring/trimLeft s))
|
||||
|
||||
(defn ^string trimr
|
||||
"Removes whitespace from the right side of string."
|
||||
[s]
|
||||
(gstring/trimRight s))
|
||||
|
||||
(defn ^string trim-newline
|
||||
"Removes all trailing newline \\n or return \\r characters from
|
||||
string. Similar to Perl's chomp."
|
||||
[s]
|
||||
(loop [index (.-length s)]
|
||||
(if (zero? index)
|
||||
""
|
||||
(let [ch (get s (dec index))]
|
||||
(if (or (identical? \newline ch)
|
||||
(identical? \return ch))
|
||||
(recur (dec index))
|
||||
(.substring s 0 index))))))
|
||||
|
||||
(defn ^boolean blank?
|
||||
"True is s is nil, empty, or contains only whitespace."
|
||||
[s]
|
||||
(gstring/isEmptyOrWhitespace (gstring/makeSafe s)))
|
||||
|
||||
(defn ^string escape
|
||||
"Return a new string, using cmap to escape each character ch
|
||||
from s as follows:
|
||||
|
||||
If (cmap ch) is nil, append ch to the new string.
|
||||
If (cmap ch) is non-nil, append (str (cmap ch)) instead."
|
||||
[s cmap]
|
||||
(let [buffer (StringBuffer.)
|
||||
length (.-length s)]
|
||||
(loop [index 0]
|
||||
(if (== length index)
|
||||
(. buffer (toString))
|
||||
(let [ch (.charAt s index)
|
||||
replacement (get cmap ch)]
|
||||
(if-not (nil? replacement)
|
||||
(.append buffer (str replacement))
|
||||
(.append buffer ch))
|
||||
(recur (inc index)))))))
|
||||
|
||||
(defn index-of
|
||||
"Return index of value (string or char) in s, optionally searching
|
||||
forward from from-index or nil if not found."
|
||||
([s value]
|
||||
(let [result (.indexOf s value)]
|
||||
(if (neg? result)
|
||||
nil
|
||||
result)))
|
||||
([s value from-index]
|
||||
(let [result (.indexOf s value from-index)]
|
||||
(if (neg? result)
|
||||
nil
|
||||
result))))
|
||||
|
||||
(defn last-index-of
|
||||
"Return last index of value (string or char) in s, optionally
|
||||
searching backward from from-index or nil if not found."
|
||||
([s value]
|
||||
(let [result (.lastIndexOf s value)]
|
||||
(if (neg? result)
|
||||
nil
|
||||
result)))
|
||||
([s value from-index]
|
||||
(let [result (.lastIndexOf s value from-index)]
|
||||
(if (neg? result)
|
||||
nil
|
||||
result))))
|
||||
|
||||
(defn ^boolean starts-with?
|
||||
"True if s starts with substr."
|
||||
[s substr]
|
||||
(gstring/startsWith s substr))
|
||||
|
||||
(defn ^boolean ends-with?
|
||||
"True if s ends with substr."
|
||||
[s substr]
|
||||
(gstring/endsWith s substr))
|
||||
|
||||
(defn ^boolean includes?
|
||||
"True if s includes substr."
|
||||
[s substr]
|
||||
(gstring/contains s substr))
|
||||
Executable
+479
@@ -0,0 +1,479 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('clojure.string');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.string.StringBuffer');
|
||||
clojure.string.seq_reverse = (function clojure$string$seq_reverse(coll){
|
||||
return cljs.core.reduce.cljs$core$IFn$_invoke$arity$3(cljs.core.conj,cljs.core.List.EMPTY,coll);
|
||||
});
|
||||
clojure.string.re_surrogate_pair = (new RegExp("([\\uD800-\\uDBFF])([\\uDC00-\\uDFFF])","g"));
|
||||
/**
|
||||
* Returns s with its characters reversed.
|
||||
*/
|
||||
clojure.string.reverse = (function clojure$string$reverse(s){
|
||||
return s.replace(clojure.string.re_surrogate_pair,"$2$1").split("").reverse().join("");
|
||||
});
|
||||
clojure.string.replace_all = (function clojure$string$replace_all(s,re,replacement){
|
||||
var r = (new RegExp(re.source,(function (){var G__5199 = "g";
|
||||
var G__5199__$1 = (cljs.core.truth_(re.ignoreCase)?[G__5199,"i"].join(''):G__5199);
|
||||
var G__5199__$2 = (cljs.core.truth_(re.multiline)?[G__5199__$1,"m"].join(''):G__5199__$1);
|
||||
if(cljs.core.truth_(re.unicode)){
|
||||
return [G__5199__$2,"u"].join('');
|
||||
} else {
|
||||
return G__5199__$2;
|
||||
}
|
||||
})()));
|
||||
return s.replace(r,replacement);
|
||||
});
|
||||
clojure.string.replace_with = (function clojure$string$replace_with(f){
|
||||
return (function() {
|
||||
var G__5202__delegate = function (args){
|
||||
var matches = cljs.core.drop_last.cljs$core$IFn$_invoke$arity$2((2),args);
|
||||
if(cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(cljs.core.count(matches),(1))){
|
||||
var G__5200 = cljs.core.first(matches);
|
||||
return (f.cljs$core$IFn$_invoke$arity$1 ? f.cljs$core$IFn$_invoke$arity$1(G__5200) : f.call(null,G__5200));
|
||||
} else {
|
||||
var G__5201 = cljs.core.vec(matches);
|
||||
return (f.cljs$core$IFn$_invoke$arity$1 ? f.cljs$core$IFn$_invoke$arity$1(G__5201) : f.call(null,G__5201));
|
||||
}
|
||||
};
|
||||
var G__5202 = function (var_args){
|
||||
var args = null;
|
||||
if (arguments.length > 0) {
|
||||
var G__5203__i = 0, G__5203__a = new Array(arguments.length - 0);
|
||||
while (G__5203__i < G__5203__a.length) {G__5203__a[G__5203__i] = arguments[G__5203__i + 0]; ++G__5203__i;}
|
||||
args = new cljs.core.IndexedSeq(G__5203__a,0,null);
|
||||
}
|
||||
return G__5202__delegate.call(this,args);};
|
||||
G__5202.cljs$lang$maxFixedArity = 0;
|
||||
G__5202.cljs$lang$applyTo = (function (arglist__5204){
|
||||
var args = cljs.core.seq(arglist__5204);
|
||||
return G__5202__delegate(args);
|
||||
});
|
||||
G__5202.cljs$core$IFn$_invoke$arity$variadic = G__5202__delegate;
|
||||
return G__5202;
|
||||
})()
|
||||
;
|
||||
});
|
||||
/**
|
||||
* Replaces all instance of match with replacement in s.
|
||||
*
|
||||
* match/replacement can be:
|
||||
*
|
||||
* string / string
|
||||
* pattern / (string or function of match).
|
||||
*
|
||||
* See also replace-first.
|
||||
*
|
||||
* The replacement is literal (i.e. none of its characters are treated
|
||||
* specially) for all cases above except pattern / string.
|
||||
*
|
||||
* For pattern / string, $1, $2, etc. in the replacement string are
|
||||
* substituted with the string that matched the corresponding
|
||||
* parenthesized group in the pattern.
|
||||
*
|
||||
* Example:
|
||||
* (clojure.string/replace "Almost Pig Latin" #"\b(\w)(\w+)\b" "$2$1ay")
|
||||
* -> "lmostAay igPay atinLay"
|
||||
*/
|
||||
clojure.string.replace = (function clojure$string$replace(s,match,replacement){
|
||||
if(typeof match === 'string'){
|
||||
return s.replace((new RegExp(goog.string.regExpEscape(match),"g")),replacement);
|
||||
} else {
|
||||
if((match instanceof RegExp)){
|
||||
if(typeof replacement === 'string'){
|
||||
return clojure.string.replace_all(s,match,replacement);
|
||||
} else {
|
||||
return clojure.string.replace_all(s,match,clojure.string.replace_with(replacement));
|
||||
}
|
||||
} else {
|
||||
throw ["Invalid match arg: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(match)].join('');
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Replaces the first instance of match with replacement in s.
|
||||
*
|
||||
* match/replacement can be:
|
||||
*
|
||||
* string / string
|
||||
* pattern / (string or function of match).
|
||||
*
|
||||
* See also replace.
|
||||
*
|
||||
* The replacement is literal (i.e. none of its characters are treated
|
||||
* specially) for all cases above except pattern / string.
|
||||
*
|
||||
* For pattern / string, $1, $2, etc. in the replacement string are
|
||||
* substituted with the string that matched the corresponding
|
||||
* parenthesized group in the pattern.
|
||||
*
|
||||
* Example:
|
||||
* (clojure.string/replace-first "swap first two words"
|
||||
* #"(\w+)(\s+)(\w+)" "$3$2$1")
|
||||
* -> "first swap two words"
|
||||
*/
|
||||
clojure.string.replace_first = (function clojure$string$replace_first(s,match,replacement){
|
||||
return s.replace(match,replacement);
|
||||
});
|
||||
/**
|
||||
* Returns a string of all elements in coll, as returned by (seq coll),
|
||||
* separated by an optional separator.
|
||||
*/
|
||||
clojure.string.join = (function clojure$string$join(var_args){
|
||||
var G__5206 = arguments.length;
|
||||
switch (G__5206) {
|
||||
case 1:
|
||||
return clojure.string.join.cljs$core$IFn$_invoke$arity$1((arguments[(0)]));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
return clojure.string.join.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(clojure.string.join.cljs$core$IFn$_invoke$arity$1 = (function (coll){
|
||||
var sb = (new goog.string.StringBuffer());
|
||||
var coll__$1 = cljs.core.seq(coll);
|
||||
while(true){
|
||||
if((!((coll__$1 == null)))){
|
||||
var G__5208 = sb.append(cljs.core.str.cljs$core$IFn$_invoke$arity$1(cljs.core.first(coll__$1)));
|
||||
var G__5209 = cljs.core.next(coll__$1);
|
||||
sb = G__5208;
|
||||
coll__$1 = G__5209;
|
||||
continue;
|
||||
} else {
|
||||
return sb.toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(clojure.string.join.cljs$core$IFn$_invoke$arity$2 = (function (separator,coll){
|
||||
var sb = (new goog.string.StringBuffer());
|
||||
var coll__$1 = cljs.core.seq(coll);
|
||||
while(true){
|
||||
if((!((coll__$1 == null)))){
|
||||
sb.append(cljs.core.str.cljs$core$IFn$_invoke$arity$1(cljs.core.first(coll__$1)));
|
||||
|
||||
var coll__$2 = cljs.core.next(coll__$1);
|
||||
if((coll__$2 == null)){
|
||||
} else {
|
||||
sb.append(separator);
|
||||
}
|
||||
|
||||
var G__5210 = sb;
|
||||
var G__5211 = coll__$2;
|
||||
sb = G__5210;
|
||||
coll__$1 = G__5211;
|
||||
continue;
|
||||
} else {
|
||||
return sb.toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
(clojure.string.join.cljs$lang$maxFixedArity = 2);
|
||||
|
||||
/**
|
||||
* Converts string to all upper-case.
|
||||
*/
|
||||
clojure.string.upper_case = (function clojure$string$upper_case(s){
|
||||
return s.toUpperCase();
|
||||
});
|
||||
/**
|
||||
* Converts string to all lower-case.
|
||||
*/
|
||||
clojure.string.lower_case = (function clojure$string$lower_case(s){
|
||||
return s.toLowerCase();
|
||||
});
|
||||
/**
|
||||
* Converts first character of the string to upper-case, all other
|
||||
* characters to lower-case.
|
||||
*/
|
||||
clojure.string.capitalize = (function clojure$string$capitalize(s){
|
||||
return goog.string.capitalize(s);
|
||||
});
|
||||
clojure.string.pop_last_while_empty = (function clojure$string$pop_last_while_empty(v){
|
||||
var v__$1 = v;
|
||||
while(true){
|
||||
if(("" === cljs.core.peek(v__$1))){
|
||||
var G__5212 = cljs.core.pop(v__$1);
|
||||
v__$1 = G__5212;
|
||||
continue;
|
||||
} else {
|
||||
return v__$1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
clojure.string.discard_trailing_if_needed = (function clojure$string$discard_trailing_if_needed(limit,v){
|
||||
if(((((0) === limit)) && (((1) < cljs.core.count(v))))){
|
||||
return clojure.string.pop_last_while_empty(v);
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
});
|
||||
clojure.string.split_with_empty_regex = (function clojure$string$split_with_empty_regex(s,limit){
|
||||
if((((limit <= (0))) || ((limit >= ((2) + cljs.core.count(s)))))){
|
||||
return cljs.core.conj.cljs$core$IFn$_invoke$arity$2(cljs.core.vec(cljs.core.cons("",cljs.core.map.cljs$core$IFn$_invoke$arity$2(cljs.core.str,cljs.core.seq(s)))),"");
|
||||
} else {
|
||||
var pred__5213 = cljs.core._EQ__EQ_;
|
||||
var expr__5214 = limit;
|
||||
if(cljs.core.truth_((pred__5213.cljs$core$IFn$_invoke$arity$2 ? pred__5213.cljs$core$IFn$_invoke$arity$2((1),expr__5214) : pred__5213.call(null,(1),expr__5214)))){
|
||||
return (new cljs.core.PersistentVector(null,1,(5),cljs.core.PersistentVector.EMPTY_NODE,[s],null));
|
||||
} else {
|
||||
if(cljs.core.truth_((pred__5213.cljs$core$IFn$_invoke$arity$2 ? pred__5213.cljs$core$IFn$_invoke$arity$2((2),expr__5214) : pred__5213.call(null,(2),expr__5214)))){
|
||||
return (new cljs.core.PersistentVector(null,2,(5),cljs.core.PersistentVector.EMPTY_NODE,["",s],null));
|
||||
} else {
|
||||
var c = (limit - (2));
|
||||
return cljs.core.conj.cljs$core$IFn$_invoke$arity$2(cljs.core.vec(cljs.core.cons("",cljs.core.subvec.cljs$core$IFn$_invoke$arity$3(cljs.core.vec(cljs.core.map.cljs$core$IFn$_invoke$arity$2(cljs.core.str,cljs.core.seq(s))),(0),c))),cljs.core.subs.cljs$core$IFn$_invoke$arity$2(s,c));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Splits string on a regular expression. Optional argument limit is
|
||||
* the maximum number of parts. Not lazy. Returns vector of the parts.
|
||||
* Trailing empty strings are not returned - pass limit of -1 to return all.
|
||||
*/
|
||||
clojure.string.split = (function clojure$string$split(var_args){
|
||||
var G__5217 = arguments.length;
|
||||
switch (G__5217) {
|
||||
case 2:
|
||||
return clojure.string.split.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return clojure.string.split.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(clojure.string.split.cljs$core$IFn$_invoke$arity$2 = (function (s,re){
|
||||
return clojure.string.split.cljs$core$IFn$_invoke$arity$3(s,re,(0));
|
||||
}));
|
||||
|
||||
(clojure.string.split.cljs$core$IFn$_invoke$arity$3 = (function (s,re,limit){
|
||||
return clojure.string.discard_trailing_if_needed(limit,((("/(?:)/" === cljs.core.str.cljs$core$IFn$_invoke$arity$1(re)))?clojure.string.split_with_empty_regex(s,limit):(((limit < (1)))?cljs.core.vec(cljs.core.str.cljs$core$IFn$_invoke$arity$1(s).split(re)):(function (){var s__$1 = s;
|
||||
var limit__$1 = limit;
|
||||
var parts = cljs.core.PersistentVector.EMPTY;
|
||||
while(true){
|
||||
if(((1) === limit__$1)){
|
||||
return cljs.core.conj.cljs$core$IFn$_invoke$arity$2(parts,s__$1);
|
||||
} else {
|
||||
var m = cljs.core.re_find(re,s__$1);
|
||||
if((!((m == null)))){
|
||||
var index = s__$1.indexOf(m);
|
||||
var G__5219 = s__$1.substring((index + cljs.core.count(m)));
|
||||
var G__5220 = (limit__$1 - (1));
|
||||
var G__5221 = cljs.core.conj.cljs$core$IFn$_invoke$arity$2(parts,s__$1.substring((0),index));
|
||||
s__$1 = G__5219;
|
||||
limit__$1 = G__5220;
|
||||
parts = G__5221;
|
||||
continue;
|
||||
} else {
|
||||
return cljs.core.conj.cljs$core$IFn$_invoke$arity$2(parts,s__$1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
})())));
|
||||
}));
|
||||
|
||||
(clojure.string.split.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
/**
|
||||
* Splits s on \n or \r\n. Trailing empty lines are not returned.
|
||||
*/
|
||||
clojure.string.split_lines = (function clojure$string$split_lines(s){
|
||||
return clojure.string.split.cljs$core$IFn$_invoke$arity$2(s,/\n|\r\n/);
|
||||
});
|
||||
/**
|
||||
* Removes whitespace from both ends of string.
|
||||
*/
|
||||
clojure.string.trim = (function clojure$string$trim(s){
|
||||
return goog.string.trim(s);
|
||||
});
|
||||
/**
|
||||
* Removes whitespace from the left side of string.
|
||||
*/
|
||||
clojure.string.triml = (function clojure$string$triml(s){
|
||||
return goog.string.trimLeft(s);
|
||||
});
|
||||
/**
|
||||
* Removes whitespace from the right side of string.
|
||||
*/
|
||||
clojure.string.trimr = (function clojure$string$trimr(s){
|
||||
return goog.string.trimRight(s);
|
||||
});
|
||||
/**
|
||||
* Removes all trailing newline \n or return \r characters from
|
||||
* string. Similar to Perl's chomp.
|
||||
*/
|
||||
clojure.string.trim_newline = (function clojure$string$trim_newline(s){
|
||||
var index = s.length;
|
||||
while(true){
|
||||
if((index === (0))){
|
||||
return "";
|
||||
} else {
|
||||
var ch = cljs.core.get.cljs$core$IFn$_invoke$arity$2(s,(index - (1)));
|
||||
if(((("\n" === ch)) || (("\r" === ch)))){
|
||||
var G__5222 = (index - (1));
|
||||
index = G__5222;
|
||||
continue;
|
||||
} else {
|
||||
return s.substring((0),index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* True is s is nil, empty, or contains only whitespace.
|
||||
*/
|
||||
clojure.string.blank_QMARK_ = (function clojure$string$blank_QMARK_(s){
|
||||
return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(s));
|
||||
});
|
||||
/**
|
||||
* Return a new string, using cmap to escape each character ch
|
||||
* from s as follows:
|
||||
*
|
||||
* If (cmap ch) is nil, append ch to the new string.
|
||||
* If (cmap ch) is non-nil, append (str (cmap ch)) instead.
|
||||
*/
|
||||
clojure.string.escape = (function clojure$string$escape(s,cmap){
|
||||
var buffer = (new goog.string.StringBuffer());
|
||||
var length = s.length;
|
||||
var index = (0);
|
||||
while(true){
|
||||
if((length === index)){
|
||||
return buffer.toString();
|
||||
} else {
|
||||
var ch = s.charAt(index);
|
||||
var replacement = cljs.core.get.cljs$core$IFn$_invoke$arity$2(cmap,ch);
|
||||
if((!((replacement == null)))){
|
||||
buffer.append(cljs.core.str.cljs$core$IFn$_invoke$arity$1(replacement));
|
||||
} else {
|
||||
buffer.append(ch);
|
||||
}
|
||||
|
||||
var G__5223 = (index + (1));
|
||||
index = G__5223;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Return index of value (string or char) in s, optionally searching
|
||||
* forward from from-index or nil if not found.
|
||||
*/
|
||||
clojure.string.index_of = (function clojure$string$index_of(var_args){
|
||||
var G__5225 = arguments.length;
|
||||
switch (G__5225) {
|
||||
case 2:
|
||||
return clojure.string.index_of.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return clojure.string.index_of.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(clojure.string.index_of.cljs$core$IFn$_invoke$arity$2 = (function (s,value){
|
||||
var result = s.indexOf(value);
|
||||
if((result < (0))){
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}));
|
||||
|
||||
(clojure.string.index_of.cljs$core$IFn$_invoke$arity$3 = (function (s,value,from_index){
|
||||
var result = s.indexOf(value,from_index);
|
||||
if((result < (0))){
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}));
|
||||
|
||||
(clojure.string.index_of.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
/**
|
||||
* Return last index of value (string or char) in s, optionally
|
||||
* searching backward from from-index or nil if not found.
|
||||
*/
|
||||
clojure.string.last_index_of = (function clojure$string$last_index_of(var_args){
|
||||
var G__5228 = arguments.length;
|
||||
switch (G__5228) {
|
||||
case 2:
|
||||
return clojure.string.last_index_of.cljs$core$IFn$_invoke$arity$2((arguments[(0)]),(arguments[(1)]));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
return clojure.string.last_index_of.cljs$core$IFn$_invoke$arity$3((arguments[(0)]),(arguments[(1)]),(arguments[(2)]));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw (new Error(["Invalid arity: ",cljs.core.str.cljs$core$IFn$_invoke$arity$1(arguments.length)].join('')));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
(clojure.string.last_index_of.cljs$core$IFn$_invoke$arity$2 = (function (s,value){
|
||||
var result = s.lastIndexOf(value);
|
||||
if((result < (0))){
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}));
|
||||
|
||||
(clojure.string.last_index_of.cljs$core$IFn$_invoke$arity$3 = (function (s,value,from_index){
|
||||
var result = s.lastIndexOf(value,from_index);
|
||||
if((result < (0))){
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}));
|
||||
|
||||
(clojure.string.last_index_of.cljs$lang$maxFixedArity = 3);
|
||||
|
||||
/**
|
||||
* True if s starts with substr.
|
||||
*/
|
||||
clojure.string.starts_with_QMARK_ = (function clojure$string$starts_with_QMARK_(s,substr){
|
||||
return goog.string.startsWith(s,substr);
|
||||
});
|
||||
/**
|
||||
* True if s ends with substr.
|
||||
*/
|
||||
clojure.string.ends_with_QMARK_ = (function clojure$string$ends_with_QMARK_(s,substr){
|
||||
return goog.string.endsWith(s,substr);
|
||||
});
|
||||
/**
|
||||
* True if s includes substr.
|
||||
*/
|
||||
clojure.string.includes_QMARK_ = (function clojure$string$includes_QMARK_(s,substr){
|
||||
return goog.string.contains(s,substr);
|
||||
});
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
; Copyright (c) Rich Hickey. All rights reserved.
|
||||
; The use and distribution terms for this software are covered by the
|
||||
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
||||
; which can be found in the file epl-v10.html at the root of this distribution.
|
||||
; By using this software in any fashion, you are agreeing to be bound by
|
||||
; the terms of this license.
|
||||
; You must not remove this notice, or any other, from this software.
|
||||
|
||||
;;; walk.cljs - generic tree walker with replacement
|
||||
|
||||
;; by Stuart Sierra
|
||||
;; Jul5 17, 2011
|
||||
|
||||
;; CHANGE LOG:
|
||||
;;
|
||||
;; * July 17, 2011: Port to ClojureScript
|
||||
;;
|
||||
;; * December 15, 2008: replaced 'walk' with 'prewalk' & 'postwalk'
|
||||
;;
|
||||
;; * December 9, 2008: first version
|
||||
|
||||
|
||||
(ns
|
||||
^{:author "Stuart Sierra",
|
||||
:doc "This file defines a generic tree walker for Clojure data
|
||||
structures. It takes any data structure (list, vector, map, set,
|
||||
seq), calls a function on every element, and uses the return value
|
||||
of the function in place of the original. This makes it fairly
|
||||
easy to write recursive search-and-replace functions, as shown in
|
||||
the examples.
|
||||
|
||||
Note: \"walk\" supports all Clojure data structures EXCEPT maps
|
||||
created with sorted-map-by. There is no (obvious) way to retrieve
|
||||
the sorting function."}
|
||||
clojure.walk)
|
||||
|
||||
(defn walk
|
||||
"Traverses form, an arbitrary data structure. inner and outer are
|
||||
functions. Applies inner to each element of form, building up a
|
||||
data structure of the same type, then applies outer to the result.
|
||||
Recognizes all Clojure data structures. Consumes seqs as with doall."
|
||||
|
||||
{:added "1.1"}
|
||||
[inner outer form]
|
||||
(cond
|
||||
(list? form) (outer (apply list (map inner form)))
|
||||
(map-entry? form)
|
||||
(outer (MapEntry. (inner (key form)) (inner (val form)) nil))
|
||||
(seq? form) (outer (doall (map inner form)))
|
||||
(record? form) (outer (reduce (fn [r x] (conj r (inner x))) form form))
|
||||
(coll? form) (outer (into (empty form) (map inner form)))
|
||||
:else (outer form)))
|
||||
|
||||
(defn postwalk
|
||||
"Performs a depth-first, post-order traversal of form. Calls f on
|
||||
each sub-form, uses f's return value in place of the original.
|
||||
Recognizes all Clojure data structures. Consumes seqs as with doall."
|
||||
{:added "1.1"}
|
||||
[f form]
|
||||
(walk (partial postwalk f) f form))
|
||||
|
||||
(defn prewalk
|
||||
"Like postwalk, but does pre-order traversal."
|
||||
{:added "1.1"}
|
||||
[f form]
|
||||
(walk (partial prewalk f) identity (f form)))
|
||||
|
||||
(defn keywordize-keys
|
||||
"Recursively transforms all map keys from strings to keywords."
|
||||
{:added "1.1"}
|
||||
[m]
|
||||
(let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))]
|
||||
;; only apply to maps
|
||||
(postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))
|
||||
|
||||
(defn stringify-keys
|
||||
"Recursively transforms all map keys from keywords to strings."
|
||||
{:added "1.1"}
|
||||
[m]
|
||||
(let [f (fn [[k v]] (if (keyword? k) [(name k) v] [k v]))]
|
||||
;; only apply to maps
|
||||
(postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))
|
||||
|
||||
(defn prewalk-replace
|
||||
"Recursively transforms form by replacing keys in smap with their
|
||||
values. Like clojure/replace but works on any data structure. Does
|
||||
replacement at the root of the tree first."
|
||||
{:added "1.1"}
|
||||
[smap form]
|
||||
(prewalk (fn [x] (if (contains? smap x) (smap x) x)) form))
|
||||
|
||||
(defn postwalk-replace
|
||||
"Recursively transforms form by replacing keys in smap with their
|
||||
values. Like clojure/replace but works on any data structure. Does
|
||||
replacement at the leaves of the tree first."
|
||||
{:added "1.1"}
|
||||
[smap form]
|
||||
(postwalk (fn [x] (if (contains? smap x) (smap x) x)) form))
|
||||
Executable
+131
@@ -0,0 +1,131 @@
|
||||
// Compiled by ClojureScript 1.11.60 {:static-fns true, :optimize-constants true, :optimizations :advanced}
|
||||
goog.provide('clojure.walk');
|
||||
goog.require('cljs.core');
|
||||
goog.require('cljs.core.constants');
|
||||
/**
|
||||
* Traverses form, an arbitrary data structure. inner and outer are
|
||||
* functions. Applies inner to each element of form, building up a
|
||||
* data structure of the same type, then applies outer to the result.
|
||||
* Recognizes all Clojure data structures. Consumes seqs as with doall.
|
||||
*/
|
||||
clojure.walk.walk = (function clojure$walk$walk(inner,outer,form){
|
||||
if(cljs.core.list_QMARK_(form)){
|
||||
var G__10713 = cljs.core.apply.cljs$core$IFn$_invoke$arity$2(cljs.core.list,cljs.core.map.cljs$core$IFn$_invoke$arity$2(inner,form));
|
||||
return (outer.cljs$core$IFn$_invoke$arity$1 ? outer.cljs$core$IFn$_invoke$arity$1(G__10713) : outer.call(null,G__10713));
|
||||
} else {
|
||||
if(cljs.core.map_entry_QMARK_(form)){
|
||||
var G__10714 = (new cljs.core.MapEntry((function (){var G__10715 = cljs.core.key(form);
|
||||
return (inner.cljs$core$IFn$_invoke$arity$1 ? inner.cljs$core$IFn$_invoke$arity$1(G__10715) : inner.call(null,G__10715));
|
||||
})(),(function (){var G__10716 = cljs.core.val(form);
|
||||
return (inner.cljs$core$IFn$_invoke$arity$1 ? inner.cljs$core$IFn$_invoke$arity$1(G__10716) : inner.call(null,G__10716));
|
||||
})(),null));
|
||||
return (outer.cljs$core$IFn$_invoke$arity$1 ? outer.cljs$core$IFn$_invoke$arity$1(G__10714) : outer.call(null,G__10714));
|
||||
} else {
|
||||
if(cljs.core.seq_QMARK_(form)){
|
||||
var G__10717 = cljs.core.doall.cljs$core$IFn$_invoke$arity$1(cljs.core.map.cljs$core$IFn$_invoke$arity$2(inner,form));
|
||||
return (outer.cljs$core$IFn$_invoke$arity$1 ? outer.cljs$core$IFn$_invoke$arity$1(G__10717) : outer.call(null,G__10717));
|
||||
} else {
|
||||
if(cljs.core.record_QMARK_(form)){
|
||||
var G__10718 = cljs.core.reduce.cljs$core$IFn$_invoke$arity$3((function (r,x){
|
||||
return cljs.core.conj.cljs$core$IFn$_invoke$arity$2(r,(inner.cljs$core$IFn$_invoke$arity$1 ? inner.cljs$core$IFn$_invoke$arity$1(x) : inner.call(null,x)));
|
||||
}),form,form);
|
||||
return (outer.cljs$core$IFn$_invoke$arity$1 ? outer.cljs$core$IFn$_invoke$arity$1(G__10718) : outer.call(null,G__10718));
|
||||
} else {
|
||||
if(cljs.core.coll_QMARK_(form)){
|
||||
var G__10719 = cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.empty(form),cljs.core.map.cljs$core$IFn$_invoke$arity$2(inner,form));
|
||||
return (outer.cljs$core$IFn$_invoke$arity$1 ? outer.cljs$core$IFn$_invoke$arity$1(G__10719) : outer.call(null,G__10719));
|
||||
} else {
|
||||
return (outer.cljs$core$IFn$_invoke$arity$1 ? outer.cljs$core$IFn$_invoke$arity$1(form) : outer.call(null,form));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Performs a depth-first, post-order traversal of form. Calls f on
|
||||
* each sub-form, uses f's return value in place of the original.
|
||||
* Recognizes all Clojure data structures. Consumes seqs as with doall.
|
||||
*/
|
||||
clojure.walk.postwalk = (function clojure$walk$postwalk(f,form){
|
||||
return clojure.walk.walk(cljs.core.partial.cljs$core$IFn$_invoke$arity$2(clojure.walk.postwalk,f),f,form);
|
||||
});
|
||||
/**
|
||||
* Like postwalk, but does pre-order traversal.
|
||||
*/
|
||||
clojure.walk.prewalk = (function clojure$walk$prewalk(f,form){
|
||||
return clojure.walk.walk(cljs.core.partial.cljs$core$IFn$_invoke$arity$2(clojure.walk.prewalk,f),cljs.core.identity,(f.cljs$core$IFn$_invoke$arity$1 ? f.cljs$core$IFn$_invoke$arity$1(form) : f.call(null,form)));
|
||||
});
|
||||
/**
|
||||
* Recursively transforms all map keys from strings to keywords.
|
||||
*/
|
||||
clojure.walk.keywordize_keys = (function clojure$walk$keywordize_keys(m){
|
||||
var f = (function (p__10720){
|
||||
var vec__10721 = p__10720;
|
||||
var k = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__10721,(0),null);
|
||||
var v = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__10721,(1),null);
|
||||
if(typeof k === 'string'){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.keyword.cljs$core$IFn$_invoke$arity$1(k),v], null);
|
||||
} else {
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [k,v], null);
|
||||
}
|
||||
});
|
||||
return clojure.walk.postwalk((function (x){
|
||||
if(cljs.core.map_QMARK_(x)){
|
||||
return cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,cljs.core.map.cljs$core$IFn$_invoke$arity$2(f,x));
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}),m);
|
||||
});
|
||||
/**
|
||||
* Recursively transforms all map keys from keywords to strings.
|
||||
*/
|
||||
clojure.walk.stringify_keys = (function clojure$walk$stringify_keys(m){
|
||||
var f = (function (p__10724){
|
||||
var vec__10725 = p__10724;
|
||||
var k = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__10725,(0),null);
|
||||
var v = cljs.core.nth.cljs$core$IFn$_invoke$arity$3(vec__10725,(1),null);
|
||||
if((k instanceof cljs.core.Keyword)){
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [cljs.core.name(k),v], null);
|
||||
} else {
|
||||
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [k,v], null);
|
||||
}
|
||||
});
|
||||
return clojure.walk.postwalk((function (x){
|
||||
if(cljs.core.map_QMARK_(x)){
|
||||
return cljs.core.into.cljs$core$IFn$_invoke$arity$2(cljs.core.PersistentArrayMap.EMPTY,cljs.core.map.cljs$core$IFn$_invoke$arity$2(f,x));
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}),m);
|
||||
});
|
||||
/**
|
||||
* Recursively transforms form by replacing keys in smap with their
|
||||
* values. Like clojure/replace but works on any data structure. Does
|
||||
* replacement at the root of the tree first.
|
||||
*/
|
||||
clojure.walk.prewalk_replace = (function clojure$walk$prewalk_replace(smap,form){
|
||||
return clojure.walk.prewalk((function (x){
|
||||
if(cljs.core.contains_QMARK_(smap,x)){
|
||||
return (smap.cljs$core$IFn$_invoke$arity$1 ? smap.cljs$core$IFn$_invoke$arity$1(x) : smap.call(null,x));
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}),form);
|
||||
});
|
||||
/**
|
||||
* Recursively transforms form by replacing keys in smap with their
|
||||
* values. Like clojure/replace but works on any data structure. Does
|
||||
* replacement at the leaves of the tree first.
|
||||
*/
|
||||
clojure.walk.postwalk_replace = (function clojure$walk$postwalk_replace(smap,form){
|
||||
return clojure.walk.postwalk((function (x){
|
||||
if(cljs.core.contains_QMARK_(smap,x)){
|
||||
return (smap.cljs$core$IFn$_invoke$arity$1 ? smap.cljs$core$IFn$_invoke$arity$1(x) : smap.call(null,x));
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}),form);
|
||||
});
|
||||
Executable
+381
@@ -0,0 +1,381 @@
|
||||
;; Copyright 2014 Cognitect. All Rights Reserved.
|
||||
;;
|
||||
;; Licensed under the Apache License, Version 2.0 (the "License");
|
||||
;; you may not use this file except in compliance with the License.
|
||||
;; You may obtain a copy of the License at
|
||||
;;
|
||||
;; http://www.apache.org/licenses/LICENSE-2.0
|
||||
;;
|
||||
;; Unless required by applicable law or agreed to in writing, software
|
||||
;; distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
;; See the License for the specific language governing permissions and
|
||||
;; limitations under the License.
|
||||
|
||||
(ns cognitect.transit
|
||||
(:refer-clojure :exclude [integer? uuid])
|
||||
(:require [com.cognitect.transit :as t]
|
||||
[com.cognitect.transit.types :as ty]
|
||||
[com.cognitect.transit.eq :as eq])
|
||||
(:import [goog.math Long]))
|
||||
|
||||
;; patch cljs.core/UUID IEquiv
|
||||
|
||||
(extend-type UUID
|
||||
IEquiv
|
||||
(-equiv [this other]
|
||||
(cond
|
||||
(instance? UUID other)
|
||||
(identical? (.-uuid this) (.-uuid other))
|
||||
|
||||
(instance? ty/UUID other)
|
||||
(identical? (.-uuid this) (.toString other))
|
||||
|
||||
:else false)))
|
||||
|
||||
(extend-protocol IComparable
|
||||
UUID
|
||||
(-compare [this other]
|
||||
(if (or (instance? UUID other)
|
||||
(instance? ty/UUID other))
|
||||
(compare (.toString this) (.toString other))
|
||||
(throw (js/Error. (str "Cannot compare " this " to " other)))))
|
||||
ty/UUID
|
||||
(-compare [this other]
|
||||
(if (or (instance? UUID other)
|
||||
(instance? ty/UUID other))
|
||||
(compare (.toString this) (.toString other))
|
||||
(throw (js/Error. (str "Cannot compare " this " to " other))))))
|
||||
|
||||
(extend-protocol IEquiv
|
||||
Long
|
||||
(-equiv [this other]
|
||||
(.equiv this other))
|
||||
|
||||
ty/UUID
|
||||
(-equiv [this other]
|
||||
(if (instance? UUID other)
|
||||
(-equiv other this)
|
||||
(.equiv this other)))
|
||||
|
||||
ty/TaggedValue
|
||||
(-equiv [this other]
|
||||
(.equiv this other)))
|
||||
|
||||
(extend-protocol IHash
|
||||
Long
|
||||
(-hash [this]
|
||||
(eq/hashCode this))
|
||||
|
||||
ty/UUID
|
||||
(-hash [this]
|
||||
(eq/hashCode this))
|
||||
|
||||
ty/TaggedValue
|
||||
(-hash [this]
|
||||
(eq/hashCode this)))
|
||||
|
||||
(extend-type ty/UUID
|
||||
IPrintWithWriter
|
||||
(-pr-writer [uuid writer _]
|
||||
(-write writer (str "#uuid \"" (.toString uuid) "\""))))
|
||||
|
||||
(defn ^:no-doc opts-merge [a b]
|
||||
(doseq [k (js-keys b)]
|
||||
(let [v (aget b k)]
|
||||
(aset a k v)))
|
||||
a)
|
||||
|
||||
(deftype ^:no-doc MapBuilder []
|
||||
Object
|
||||
(init [_ node] (transient {}))
|
||||
(add [_ m k v node] (assoc! m k v))
|
||||
(finalize [_ m node] (persistent! m))
|
||||
(fromArray [_ arr node] (cljs.core/PersistentArrayMap.fromArray arr true true)))
|
||||
|
||||
(deftype ^:no-doc VectorBuilder []
|
||||
Object
|
||||
(init [_ node] (transient []))
|
||||
(add [_ v x node] (conj! v x))
|
||||
(finalize [_ v node] (persistent! v))
|
||||
(fromArray [_ arr node] (cljs.core/PersistentVector.fromArray arr true)))
|
||||
|
||||
(defn reader
|
||||
"Return a transit reader. type may be either :json or :json-verbose.
|
||||
opts may be a map optionally containing a :handlers entry. The value
|
||||
of :handlers should be map from tag to a decoder function which returns
|
||||
then in-memory representation of the semantic transit value."
|
||||
([type] (reader type nil))
|
||||
([type opts]
|
||||
(t/reader (name type)
|
||||
(opts-merge
|
||||
#js {:handlers
|
||||
(clj->js
|
||||
(merge
|
||||
{"$" (fn [v] (symbol v))
|
||||
":" (fn [v] (keyword v))
|
||||
"set" (fn [v] (into #{} v))
|
||||
"list" (fn [v] (into () (.reverse v)))
|
||||
"cmap" (fn [v]
|
||||
(loop [i 0 ret (transient {})]
|
||||
(if (< i (alength v))
|
||||
(recur (+ i 2)
|
||||
(assoc! ret (aget v i) (aget v (inc i))))
|
||||
(persistent! ret))))}
|
||||
(:handlers opts)))
|
||||
:mapBuilder (MapBuilder.)
|
||||
:arrayBuilder (VectorBuilder.)
|
||||
:prefersStrings false}
|
||||
(clj->js (dissoc opts :handlers))))))
|
||||
|
||||
(defn read
|
||||
"Read a transit encoded string into ClojureScript values given a
|
||||
transit reader."
|
||||
[r str]
|
||||
(.read r str))
|
||||
|
||||
(deftype ^:no-doc KeywordHandler []
|
||||
Object
|
||||
(tag [_ v] ":")
|
||||
(rep [_ v] (.-fqn v))
|
||||
(stringRep [_ v] (.-fqn v)))
|
||||
|
||||
(deftype ^:no-doc SymbolHandler []
|
||||
Object
|
||||
(tag [_ v] "$")
|
||||
(rep [_ v] (.-str v))
|
||||
(stringRep [_ v] (.-str v)))
|
||||
|
||||
(deftype ^:no-doc ListHandler []
|
||||
Object
|
||||
(tag [_ v] "list")
|
||||
(rep [_ v]
|
||||
(let [ret #js []]
|
||||
(doseq [x v] (.push ret x))
|
||||
(t/tagged "array" ret)))
|
||||
(stringRep [_ v] nil))
|
||||
|
||||
(deftype ^:no-doc MapHandler []
|
||||
Object
|
||||
(tag [_ v] "map")
|
||||
(rep [_ v] v)
|
||||
(stringRep [_ v] nil))
|
||||
|
||||
(deftype ^:no-doc SetHandler []
|
||||
Object
|
||||
(tag [_ v] "set")
|
||||
(rep [_ v]
|
||||
(let [ret #js []]
|
||||
(doseq [x v] (.push ret x))
|
||||
(t/tagged "array" ret)))
|
||||
(stringRep [v] nil))
|
||||
|
||||
(deftype ^:no-doc VectorHandler []
|
||||
Object
|
||||
(tag [_ v] "array")
|
||||
(rep [_ v]
|
||||
(let [ret #js []]
|
||||
(doseq [x v] (.push ret x))
|
||||
ret))
|
||||
(stringRep [_ v] nil))
|
||||
|
||||
(deftype ^:no-doc UUIDHandler []
|
||||
Object
|
||||
(tag [_ v] "u")
|
||||
(rep [_ v] (.-uuid v))
|
||||
(stringRep [this v] (.rep this v)))
|
||||
|
||||
(defn writer
|
||||
"Return a transit writer. type maybe either :json or :json-verbose.
|
||||
opts is a map containing a :handlers entry. :handlers is a map of
|
||||
type constructors to handler instances."
|
||||
([type] (writer type nil))
|
||||
([type opts]
|
||||
(let [keyword-handler (KeywordHandler.)
|
||||
symbol-handler (SymbolHandler.)
|
||||
list-handler (ListHandler.)
|
||||
map-handler (MapHandler.)
|
||||
set-handler (SetHandler.)
|
||||
vector-handler (VectorHandler.)
|
||||
uuid-handler (UUIDHandler.)
|
||||
handlers
|
||||
(merge
|
||||
{cljs.core/Keyword keyword-handler
|
||||
cljs.core/Symbol symbol-handler
|
||||
cljs.core/Range list-handler
|
||||
cljs.core/List list-handler
|
||||
cljs.core/Cons list-handler
|
||||
cljs.core/EmptyList list-handler
|
||||
cljs.core/LazySeq list-handler
|
||||
cljs.core/RSeq list-handler
|
||||
cljs.core/IndexedSeq list-handler
|
||||
cljs.core/ChunkedCons list-handler
|
||||
cljs.core/ChunkedSeq list-handler
|
||||
cljs.core/PersistentQueueSeq list-handler
|
||||
cljs.core/PersistentQueue list-handler
|
||||
cljs.core/PersistentArrayMapSeq list-handler
|
||||
cljs.core/PersistentTreeMapSeq list-handler
|
||||
cljs.core/NodeSeq list-handler
|
||||
cljs.core/ArrayNodeSeq list-handler
|
||||
cljs.core/KeySeq list-handler
|
||||
cljs.core/ValSeq list-handler
|
||||
cljs.core/PersistentArrayMap map-handler
|
||||
cljs.core/PersistentHashMap map-handler
|
||||
cljs.core/PersistentTreeMap map-handler
|
||||
cljs.core/PersistentHashSet set-handler
|
||||
cljs.core/PersistentTreeSet set-handler
|
||||
cljs.core/PersistentVector vector-handler
|
||||
cljs.core/Subvec vector-handler
|
||||
cljs.core/UUID uuid-handler}
|
||||
(:handlers opts))]
|
||||
(t/writer (name type)
|
||||
(opts-merge
|
||||
#js {:objectBuilder
|
||||
(fn [m kfn vfn]
|
||||
(reduce-kv
|
||||
(fn [obj k v]
|
||||
(doto obj (.push (kfn k) (vfn v))))
|
||||
#js ["^ "] m))
|
||||
:handlers
|
||||
(specify handlers
|
||||
Object
|
||||
(forEach
|
||||
([coll f]
|
||||
(doseq [[k v] coll]
|
||||
(f v k)))))
|
||||
:unpack
|
||||
(fn [x]
|
||||
(if (instance? cljs.core/PersistentArrayMap x)
|
||||
(.-arr x)
|
||||
false))}
|
||||
(clj->js (dissoc opts :handlers)))))))
|
||||
|
||||
(defn write
|
||||
"Encode an object into a transit string given a transit writer."
|
||||
[w o]
|
||||
(.write w o))
|
||||
|
||||
(defn read-handler
|
||||
"Construct a read handler. Implemented as identity, exists primarily
|
||||
for API compatiblity with transit-clj"
|
||||
[from-rep]
|
||||
from-rep)
|
||||
|
||||
(defn write-handler
|
||||
"Creates a transit write handler whose tag, rep,
|
||||
stringRep, and verboseWriteHandler methods
|
||||
invoke the provided fns."
|
||||
([tag-fn rep-fn]
|
||||
(write-handler tag-fn rep-fn nil nil))
|
||||
([tag-fn rep-fn str-rep-fn]
|
||||
(write-handler tag-fn rep-fn str-rep-fn nil))
|
||||
([tag-fn rep-fn str-rep-fn verbose-handler-fn]
|
||||
(reify
|
||||
Object
|
||||
(tag [_ o] (tag-fn o))
|
||||
(rep [_ o] (rep-fn o))
|
||||
(stringRep [_ o] (when str-rep-fn (str-rep-fn o)))
|
||||
(getVerboseHandler [_] (when verbose-handler-fn (verbose-handler-fn))))))
|
||||
|
||||
;; =============================================================================
|
||||
;; Constructors & Predicates
|
||||
|
||||
(defn tagged-value
|
||||
"Construct a tagged value. tag must be a string and rep can
|
||||
be any transit encodeable value."
|
||||
[tag rep]
|
||||
(ty/taggedValue tag rep))
|
||||
|
||||
(defn tagged-value?
|
||||
"Returns true if x is a transit tagged value, false otherwise."
|
||||
[x]
|
||||
(ty/isTaggedValue x))
|
||||
|
||||
(defn integer
|
||||
"Construct a transit integer value. Returns JavaScript number if
|
||||
in the 53bit integer range, a goog.math.Long instance if above. s
|
||||
may be a string or a JavaScript number."
|
||||
[s]
|
||||
(ty/intValue s))
|
||||
|
||||
(defn integer?
|
||||
"Returns true if x is an integer value between the 53bit and 64bit
|
||||
range, false otherwise."
|
||||
[x]
|
||||
(ty/isInteger x))
|
||||
|
||||
(defn bigint
|
||||
"Construct a big integer from a string."
|
||||
[s]
|
||||
(ty/bigInteger s))
|
||||
|
||||
(defn bigint?
|
||||
"Returns true if x is a transit big integer value, false otherwise."
|
||||
[x]
|
||||
(ty/isBigInteger x))
|
||||
|
||||
(defn bigdec
|
||||
"Construct a big decimal from a string."
|
||||
[s]
|
||||
(ty/bigDecimalValue s))
|
||||
|
||||
(defn bigdec?
|
||||
"Returns true if x is a transit big decimal value, false otherwise."
|
||||
[x]
|
||||
(ty/isBigDecimal x))
|
||||
|
||||
(defn uri
|
||||
"Construct a URI from a string."
|
||||
[s]
|
||||
(ty/uri s))
|
||||
|
||||
(defn uri?
|
||||
"Returns true if x is a transit URI value, false otherwise."
|
||||
[x]
|
||||
(ty/isURI x))
|
||||
|
||||
(defn uuid
|
||||
"Construct a UUID from a string."
|
||||
[s]
|
||||
(ty/uuid s))
|
||||
|
||||
(defn uuid?
|
||||
"Returns true if x is a transit UUID value, false otherwise."
|
||||
[x]
|
||||
(ty/isUUID x))
|
||||
|
||||
(defn binary
|
||||
"Construct a transit binary value. s should be base64 encoded
|
||||
string."
|
||||
[s]
|
||||
(ty/binary s))
|
||||
|
||||
(defn binary?
|
||||
"Returns true if x is a transit binary value, false otherwise."
|
||||
[x]
|
||||
(ty/isBinary x))
|
||||
|
||||
(defn quoted
|
||||
"Construct a quoted transit value. x should be a transit
|
||||
encodeable value."
|
||||
[x]
|
||||
(ty/quoted x))
|
||||
|
||||
(defn quoted?
|
||||
"Returns true if x is a transit quoted value, false otherwise."
|
||||
[x]
|
||||
(ty/isQuoted x))
|
||||
|
||||
(defn link
|
||||
"Construct a transit link value. x should be an IMap instance
|
||||
containing at a minimum the following keys: :href, :rel. It
|
||||
may optionall include :name, :render, and :prompt. :href must
|
||||
be a transit URI, all other values are strings, and :render must
|
||||
be either :image or :link."
|
||||
[x]
|
||||
(ty/link x))
|
||||
|
||||
(defn link?
|
||||
"Returns true if x a transit link value, false if otherwise."
|
||||
[x]
|
||||
(ty/isLink x))
|
||||
Executable
+1172
File diff suppressed because it is too large
Load Diff
Executable
+626
@@ -0,0 +1,626 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
"use strict";
|
||||
|
||||
goog.provide("com.cognitect.transit");
|
||||
goog.require("com.cognitect.transit.impl.reader");
|
||||
goog.require("com.cognitect.transit.impl.writer");
|
||||
goog.require("com.cognitect.transit.types");
|
||||
goog.require("com.cognitect.transit.eq");
|
||||
goog.require("com.cognitect.transit.impl.decoder");
|
||||
goog.require("com.cognitect.transit.caching");
|
||||
|
||||
/** @define {boolean} */
|
||||
var TRANSIT_DEV = true;
|
||||
|
||||
/** @define {boolean} */
|
||||
var TRANSIT_NODE_TARGET = false;
|
||||
|
||||
/** @define {boolean} */
|
||||
var TRANSIT_BROWSER_TARGET = false;
|
||||
|
||||
/** @define {boolean} */
|
||||
var TRANSIT_BROWSER_AMD_TARGET = false;
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
/**
|
||||
* @class transit
|
||||
*/
|
||||
var transit = com.cognitect.transit;
|
||||
|
||||
var reader = com.cognitect.transit.impl.reader,
|
||||
writer = com.cognitect.transit.impl.writer,
|
||||
decoder = com.cognitect.transit.impl.decoder,
|
||||
types = com.cognitect.transit.types,
|
||||
eq = com.cognitect.transit.eq,
|
||||
caching = com.cognitect.transit.caching;
|
||||
|
||||
/**
|
||||
* Create a transit reader instance.
|
||||
* @method transit.reader
|
||||
* @param {string|null} type type of reader to construct.
|
||||
* Default to "json". For verbose mode supply "json-verbose".
|
||||
* @param {Object|null} opts reader options. A JavaScript object to
|
||||
* customize the writer Valid entries include "defaultHandler",
|
||||
* and "handler". "defaultHandler" should be JavaScript function
|
||||
* taking two arguments, the first is the tag, the second the
|
||||
* value. "handlers" should be an object of tags to handle. The
|
||||
* values are functions that will receive the value of matched
|
||||
* tag. "preferBuffers" may be supplied to customize binary
|
||||
* decoding. If available binary data will read as Node.js Buffers,
|
||||
* If Buffer is not available or "prefersBuffers" is set to false
|
||||
* data will be read as Uint8Array. If neither Buffer nor Uint8Array is
|
||||
* available - defaults to tagged value that simply wraps the
|
||||
* base64 encoded string.
|
||||
* @return {transit.reader} A transit reader.
|
||||
* @example
|
||||
* var r = transit.reader("json", {
|
||||
* handlers: {
|
||||
* "point": function(v) { return new Point(v[0], v[1]); }
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
transit.reader = function(type, opts) {
|
||||
if(type === "json" || type === "json-verbose" || type == null) {
|
||||
type = "json";
|
||||
var unmarshaller = new reader.JSONUnmarshaller(opts);
|
||||
return new reader.Reader(unmarshaller, opts);
|
||||
} else {
|
||||
throw new Error("Cannot create reader of type " + type);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a transit writer instance.
|
||||
* @method transit.writer
|
||||
* @param {String|null} type type of writer to construct.
|
||||
* Defaults to "json". For verbose mode supply "json-verbose".
|
||||
* @param {Object|null} opts writer options. A JavaScript object to
|
||||
* customize the writer. "handlers" options, a transit.map of
|
||||
* JavaScript constructor and transit writer handler instance
|
||||
* entries. "handlerForForeign" option, for dealing with values
|
||||
* from other JavaScript contexts. This function will be passed
|
||||
* the unmatchable value and the installed handlers. The function
|
||||
* should return the correct handler. Note if this function is
|
||||
* provided, special handling for Objects will also be
|
||||
* auto-installed to catch plain Objects from the foreign context.
|
||||
* @return {transit.writer} A transit writer.
|
||||
* @example
|
||||
* var r = transit.writer("json", {
|
||||
* handlers: transit.map([
|
||||
* Point, PointHandler
|
||||
* ])
|
||||
* });
|
||||
*/
|
||||
transit.writer = function(type, opts) {
|
||||
if(type === "json" || type === "json-verbose" || type == null) {
|
||||
if(type === "json-verbose") {
|
||||
if(opts == null) opts = {};
|
||||
opts["verbose"] = true;
|
||||
}
|
||||
type = "json";
|
||||
var marshaller = new writer.JSONMarshaller(opts);
|
||||
return new writer.Writer(marshaller, opts);
|
||||
} else {
|
||||
var err = new Error("Type must be \"json\"");
|
||||
err.data = {type: type};
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a transit writer handler.
|
||||
* @method transit.makeWriteHandler
|
||||
* @param {Object} obj An object containing 3 functions, tag, rep and stringRep.
|
||||
* "tag" should return a string representing the tag to be written on the wire.
|
||||
* "rep" should return the representation on the wire. "stringRep" is should return
|
||||
* the string representation of the value. Optional "getVerboseHandler" should return a
|
||||
* handler for writing verbose output.
|
||||
* @return {transit.handler} A transit write handler.
|
||||
* @example
|
||||
* var PointHandler = transit.makeWriteHandler({
|
||||
* tag: "point",
|
||||
* rep: function(p) { return [p.x, p.y]; },
|
||||
* stringRep: function(p) { return null; }
|
||||
* });
|
||||
*/
|
||||
transit.makeWriteHandler = function(obj) {
|
||||
var Handler = function(){};
|
||||
Handler.prototype.tag = obj["tag"];
|
||||
Handler.prototype.rep = obj["rep"];
|
||||
Handler.prototype.stringRep = obj["stringRep"];
|
||||
Handler.prototype.getVerboseHandler = obj["getVerboseHandler"];
|
||||
return new Handler();
|
||||
};
|
||||
|
||||
transit.makeBuilder = function(obj) {
|
||||
var Builder = function(){};
|
||||
Builder.prototype.init = obj["init"];
|
||||
Builder.prototype.add = obj["add"];
|
||||
Builder.prototype.finalize = obj["finalize"];
|
||||
Builder.prototype.fromArray = obj["fromArray"];
|
||||
return new Builder();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a transit date.
|
||||
* @method transit.date
|
||||
* @param {Number|String} A number or string representing milliseconds since epoch.
|
||||
* @return {Date} A JavaScript Date.
|
||||
*/
|
||||
transit.date = types.date;
|
||||
|
||||
/**
|
||||
* Create an integer. If given a transit integer or a JavaScript
|
||||
* number will simply return that value. Given a string will
|
||||
* return a JavaScript number if the string represents an integer
|
||||
* value in the 53bit range and a transit integer otherwise.
|
||||
* @method transit.integer
|
||||
* @param {Number|String|integer} s A value representing an integer.
|
||||
* @return {transit.integer} A JavaScript number or transit integer.
|
||||
*/
|
||||
transit.integer = types.intValue;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit integer. Will return true if argument
|
||||
* is a 64 bit integer or a JavaScript number that has an interpretation as
|
||||
* an integer value, i.e. parseFloat(n) === parseInt(n)
|
||||
* @method transit.isInteger
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if the value is a transit integer, false otherwise.
|
||||
*/
|
||||
transit.isInteger = types.isInteger;
|
||||
|
||||
/**
|
||||
* Create transit UUID from high and low 64 bits. These integer values
|
||||
* can be constructed with transit.integer.
|
||||
* @method transit.uuid
|
||||
* @param {transit.integer} high The high 64 bits.
|
||||
* @param {transit.integer} low The low 64 bits.
|
||||
* @return {transit.uuid} A transit UUID.
|
||||
*/
|
||||
transit.uuid = types.uuid;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit UUID.
|
||||
* @method transit.isUUID
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if the vlaue is a transit UUID instance, false otherwise.
|
||||
*/
|
||||
transit.isUUID = types.isUUID;
|
||||
|
||||
/**
|
||||
* Create a transit big integer.
|
||||
* @method transit.bigInt
|
||||
* @param {String} s A string representing an arbitrary size integer value.
|
||||
* @return {transit.bigdec} A transit big integer.
|
||||
*/
|
||||
transit.bigInt = types.bigInteger;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit big integer.
|
||||
* @method transit.isBigInt
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit big integer, false otherwise.
|
||||
*/
|
||||
transit.isBigInt = types.isBigInteger;
|
||||
|
||||
/**
|
||||
* Create a transit big decimal.
|
||||
* @method transit.bigDec
|
||||
* @param {String} s A string representing an arbitrary precisions decimal value.
|
||||
* @return {transit.bigdec} A transit big decimal.
|
||||
*/
|
||||
transit.bigDec = types.bigDecimalValue;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit big decimal.
|
||||
* @method transit.isBigDec
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit big decimal, false otherwise.
|
||||
*/
|
||||
transit.isBigDec = types.isBigDecimal;
|
||||
|
||||
/**
|
||||
* Create transit keyword.
|
||||
* @method transit.keyword
|
||||
* @param {String} name A string.
|
||||
* @return {transit.keyword} A transit keyword.
|
||||
* @example
|
||||
* transit.keyword("foo");
|
||||
*/
|
||||
transit.keyword = types.keyword;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit keyword.
|
||||
* @method transit.isKeyword
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit keyword, false otherwise.
|
||||
*/
|
||||
transit.isKeyword = types.isKeyword;
|
||||
|
||||
/**
|
||||
* Create a transit symbol.
|
||||
* @method transit.symbol
|
||||
* @param {s} name A string.
|
||||
* @return {transit.symbol} A transit symbol instance.
|
||||
* @example
|
||||
* transit.symbol("foo");
|
||||
*/
|
||||
transit.symbol = types.symbol;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit symbol
|
||||
* @method transit.isSymbol
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit symbol, false otherwise.
|
||||
*/
|
||||
transit.isSymbol = types.isSymbol;
|
||||
|
||||
/**
|
||||
* Create transit binary blob.
|
||||
* @method transit.binary
|
||||
* @param {String} s A base64 encoded string.
|
||||
* @return {transit.binary} A transit binary blob instance.
|
||||
*/
|
||||
transit.binary = types.binary;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit binary blob.
|
||||
* @method transit.isBinary
|
||||
* @param {Object} x Any JavaScript value.
|
||||
*/
|
||||
transit.isBinary = types.isBinary;
|
||||
|
||||
/**
|
||||
* Create a transit URI.
|
||||
* @method transit.uri
|
||||
* @param {String} A string representing a valid URI.
|
||||
* @return {transit.uri} A transit URI.
|
||||
*/
|
||||
transit.uri = types.uri;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit URI.
|
||||
* @method transit.isURI
|
||||
* @param {Object} Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit symbol, false otherwise.
|
||||
*/
|
||||
transit.isURI = types.isURI;
|
||||
|
||||
/**
|
||||
* Create a transit hash map. Transit maps satisfy the current version
|
||||
* of the ECMAScript 6 Map specification.
|
||||
* @method transit.map
|
||||
* @param {Array} xs A JavaScript array of alternating key value pairs.
|
||||
* @return {transit.map} A transit map.
|
||||
* @example
|
||||
* transit.map([new Date(), "foo", [1,2], 3]);
|
||||
*/
|
||||
transit.map = types.map;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit map.
|
||||
* @method transit.isMap
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit map, false otherwise.
|
||||
*/
|
||||
transit.isMap = types.isMap;
|
||||
|
||||
/**
|
||||
* Create a transit set. Transit sets satisfy the current version of the
|
||||
* of the ECMAScript 6 Set specification.
|
||||
* @method transit.set
|
||||
* @param {Array} xs A JavaScript array of values.
|
||||
* @return {transit.set} A transit set.
|
||||
* @example
|
||||
* transit.set(["foo", [1,2], 3, {bar: "baz"}]);
|
||||
*/
|
||||
transit.set = types.set;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit set.
|
||||
* @method transit.isSet
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit set, false otherwise.
|
||||
*/
|
||||
transit.isSet = types.isSet;
|
||||
|
||||
/**
|
||||
* Create a transit list.
|
||||
* @method transit.list
|
||||
* @param {Array} A JavaScript array.
|
||||
* @return {transit.list} A transit list.
|
||||
*/
|
||||
transit.list = types.list;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit list.
|
||||
* @method transit.isList
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit list, false otherwise.
|
||||
*/
|
||||
transit.isList = types.isList;
|
||||
|
||||
/**
|
||||
* Create a transit quoted value.
|
||||
* @method transit.quoted
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {transit.quoted} A transit quoted value.
|
||||
*/
|
||||
transit.quoted = types.quoted;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit quoted value.
|
||||
* @method transit.isQuoted
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit value, false otherwise.
|
||||
*/
|
||||
transit.isQuoted = types.isQuoted;
|
||||
|
||||
/**
|
||||
* Create a transit tagged value.
|
||||
* @method transit.tagged
|
||||
* @param {String} tag A tag.
|
||||
* @param {Object} value A JavaScrpt array, object, or string.
|
||||
* @return {transit.tagged} A transit tagged value.
|
||||
* @example
|
||||
* transit.tagged("point", new Point(1,2));
|
||||
*/
|
||||
transit.tagged = types.taggedValue;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit tagged value.
|
||||
* @method transit.isTaggedValue
|
||||
* @param {Object} x Any JavaScript value.
|
||||
* @return {Boolean} true if x is a transit value, false otherwise.
|
||||
*/
|
||||
transit.isTaggedValue = types.isTaggedValue;
|
||||
|
||||
/**
|
||||
* Create a transit link.
|
||||
* @method transit.link
|
||||
* @param {transit.map} A transit map which must contain at a
|
||||
* minimum the following keys: href, rel. It may optionally include
|
||||
* name, render, and prompt. href must be a transit.uri, all other
|
||||
* values are strings, and render must be either "image" or "link".
|
||||
* @return {Object} A transit link.
|
||||
*/
|
||||
transit.link = types.link;
|
||||
|
||||
/**
|
||||
* Test if an object is a transit link.
|
||||
* @method transit.isLink
|
||||
* @param {Object} x Any JavaScript object.
|
||||
* @return {Boolean} true if x is a transit link, false otherwise.
|
||||
*/
|
||||
transit.isLink = types.isLink;
|
||||
|
||||
/**
|
||||
* Compute the hashCode for any JavaScript object that has been
|
||||
* extend to transit's equality and hashing protocol. JavaScript
|
||||
* primitives and transit value are already extended to this protocol.
|
||||
* Custom types may be extended to the protocol via transit.extenToEQ.
|
||||
* @method transit.hash
|
||||
* @param {Object} x Any JavaScript object that has been extended to
|
||||
* transit's equality and hashing protocol.
|
||||
* @return {Number} Returns JavaScript number - semantically a 32bit integer.
|
||||
*/
|
||||
transit.hash = eq.hashCode;
|
||||
|
||||
/**
|
||||
* Compute the hashCode for JavaScript map-like types - either a JavaScript
|
||||
* object or a JavaScript object that implements ES6 Map forEach.
|
||||
* @method transit.hashMapLike
|
||||
* @param {Object} x A plain JavaScript Object or Object that implements
|
||||
* ES6 Map forEach.
|
||||
* @return {Number} Returns JavaScript number - semantically a 32bit integer.
|
||||
*/
|
||||
transit.hashMapLike = eq.hashMapLike;
|
||||
|
||||
/**
|
||||
* Compute the hashCode for JavaScript array-like types - either a JavaScript
|
||||
* array or a JavaScript object that implements Array forEach.
|
||||
* @method transit.hashArrayLike
|
||||
* @param {Object} x A JavaScript Array or Object that implements
|
||||
* Array forEach.
|
||||
* @return {Number} Returns JavaScript number - semantically a 32bit integer.
|
||||
*/
|
||||
transit.hashMapLike = eq.hashArrayLike;
|
||||
|
||||
/**
|
||||
* Test whether two JavaScript objects represent equal values. The
|
||||
* objects to be tested should be extended to transit's equality
|
||||
* and hasing protocol. JavaScript natives and transit value have
|
||||
* already been extended to the protocol, including objects and
|
||||
* arrays. Also transit maps and JavaScript objects may be
|
||||
* compared for equality. Custom types may be extended via
|
||||
* transit.extendToEQ.
|
||||
* @param {Object} x A JavaScript object
|
||||
* @param {Object} y A JavaScript object
|
||||
* @return {Boolean} true if the x and y are equal, false otherwise.
|
||||
*/
|
||||
transit.equals = eq.equals;
|
||||
|
||||
/**
|
||||
* Extend an object to hashing and equality required by
|
||||
* transit maps and sets. Only required for custom
|
||||
* types, JavaScript primitive types and transit
|
||||
* types are handled.
|
||||
* @method transit.extendToEQ
|
||||
* @param {Object} x A JavaScript object, will be mutated.
|
||||
* @return {Object} x
|
||||
* @example
|
||||
* transit.extendToEq(Point.protototype, {
|
||||
* hashCode: function() {
|
||||
* var bits = (this.x | 0) ^ ((this.y | 0) * 31);
|
||||
* return bits ^ (bits >>> 32);
|
||||
* },
|
||||
* equals: function(other) {
|
||||
* return this.x == other.x && this.y == other.y;
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
transit.extendToEQ = eq.extendToEQ;
|
||||
|
||||
/**
|
||||
* Convert a transit map instance into a JavaScript Object.
|
||||
* Throws if the map has keys which have no string representation.
|
||||
* @method transit.mapToObject
|
||||
* @param {transit.map} m a transit map
|
||||
* @return {Object} a JavaScript Object
|
||||
*/
|
||||
transit.mapToObject = function(m) {
|
||||
var ret = {};
|
||||
m.forEach(function(v, k) {
|
||||
if(typeof k !== "string") {
|
||||
throw Error("Cannot convert map with non-string keys");
|
||||
} else {
|
||||
ret[k] = v;
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a Transit JSON decoder.
|
||||
* @method transit.decoder
|
||||
* @param {Object} options to the decoder. Can include map of
|
||||
* handlers.
|
||||
* @return {transit.decoder} a Transit JSON decoder
|
||||
* @example
|
||||
* var decoder = transit.decoder();
|
||||
* var x = decoder.decode(json, transit.readCache());
|
||||
*/
|
||||
transit.decoder = decoder.decoder;
|
||||
|
||||
/**
|
||||
* Construct a Transit read cache
|
||||
* @method transit.readCache
|
||||
* @return {transit.readCAche} a Transit read cache
|
||||
*/
|
||||
transit.readCache = caching.readCache;
|
||||
|
||||
/**
|
||||
* Construct a Transit write cache
|
||||
* @method transit.writeCache
|
||||
* @return {transit.writeCache} a Transit write cache
|
||||
*/
|
||||
transit.writeCache = caching.writeCache;
|
||||
|
||||
transit.UUIDfromString = types.UUIDfromString;
|
||||
transit.randomUUID = types.randomUUID;
|
||||
transit.stringableKeys = writer.stringableKeys;
|
||||
|
||||
if(TRANSIT_BROWSER_TARGET) {
|
||||
goog.exportSymbol("transit.reader", transit.reader);
|
||||
goog.exportSymbol("transit.writer", transit.writer);
|
||||
goog.exportSymbol("transit.makeBuilder", transit.makeBuilder);
|
||||
goog.exportSymbol("transit.makeWriteHandler", transit.makeWriteHandler);
|
||||
goog.exportSymbol("transit.date", types.date);
|
||||
goog.exportSymbol("transit.integer", types.intValue);
|
||||
goog.exportSymbol("transit.isInteger", types.isInteger);
|
||||
goog.exportSymbol("transit.uuid", types.uuid);
|
||||
goog.exportSymbol("transit.isUUID", types.isUUID);
|
||||
goog.exportSymbol("transit.bigInt", types.bigInteger);
|
||||
goog.exportSymbol("transit.isBigInt", types.isBigInteger);
|
||||
goog.exportSymbol("transit.bigDec", types.bigDecimalValue);
|
||||
goog.exportSymbol("transit.isBigDec", types.isBigDecimal);
|
||||
goog.exportSymbol("transit.keyword", types.keyword);
|
||||
goog.exportSymbol("transit.isKeyword", types.isKeyword);
|
||||
goog.exportSymbol("transit.symbol", types.symbol);
|
||||
goog.exportSymbol("transit.isSymbol", types.isSymbol);
|
||||
goog.exportSymbol("transit.binary", types.binary);
|
||||
goog.exportSymbol("transit.isBinary", types.isBinary);
|
||||
goog.exportSymbol("transit.uri", types.uri);
|
||||
goog.exportSymbol("transit.isURI", types.isURI);
|
||||
goog.exportSymbol("transit.map", types.map);
|
||||
goog.exportSymbol("transit.isMap", types.isMap);
|
||||
goog.exportSymbol("transit.set", types.set);
|
||||
goog.exportSymbol("transit.isSet", types.isSet);
|
||||
goog.exportSymbol("transit.list", types.list);
|
||||
goog.exportSymbol("transit.isList", types.isList);
|
||||
goog.exportSymbol("transit.quoted", types.quoted);
|
||||
goog.exportSymbol("transit.isQuoted", types.isQuoted);
|
||||
goog.exportSymbol("transit.tagged", types.taggedValue);
|
||||
goog.exportSymbol("transit.isTaggedValue", types.isTaggedValue);
|
||||
goog.exportSymbol("transit.link", types.link);
|
||||
goog.exportSymbol("transit.isLink", types.isLink);
|
||||
goog.exportSymbol("transit.hash", eq.hashCode);
|
||||
goog.exportSymbol("transit.hashMapLike", eq.hashMapLike);
|
||||
goog.exportSymbol("transit.hashArrayLike", eq.hashArrayLike);
|
||||
goog.exportSymbol("transit.equals", eq.equals);
|
||||
goog.exportSymbol("transit.extendToEQ", eq.extendToEQ);
|
||||
goog.exportSymbol("transit.mapToObject", transit.mapToObject);
|
||||
goog.exportSymbol("transit.decoder", decoder.decoder);
|
||||
goog.exportSymbol("transit.UUIDfromString", types.UUIDfromString);
|
||||
goog.exportSymbol("transit.randomUUID", types.randomUUID);
|
||||
goog.exportSymbol("transit.stringableKeys", writer.stringableKeys);
|
||||
goog.exportSymbol("transit.readCache", caching.readCache);
|
||||
goog.exportSymbol("transit.writeCache", caching.writeCache);
|
||||
}
|
||||
|
||||
if(TRANSIT_NODE_TARGET) {
|
||||
module.exports = {
|
||||
reader: transit.reader,
|
||||
writer: transit.writer,
|
||||
makeBuilder: transit.makeBuilder,
|
||||
makeWriteHandler: transit.makeWriteHandler,
|
||||
date: types.date,
|
||||
integer: types.intValue,
|
||||
isInteger: types.isInteger,
|
||||
uuid: types.uuid,
|
||||
isUUID: types.isUUID,
|
||||
bigInt: types.bigInteger,
|
||||
isBigInt: types.isBigInteger,
|
||||
bigDec: types.bigDecimalValue,
|
||||
isBigDec: types.isBigDecimal,
|
||||
keyword: types.keyword,
|
||||
isKeyword: types.isKeyword,
|
||||
symbol: types.symbol,
|
||||
isSymbol: types.isSymbol,
|
||||
binary: types.binary,
|
||||
isBinary: types.isBinary,
|
||||
uri: types.uri,
|
||||
isURI: types.isURI,
|
||||
map: types.map,
|
||||
isMap: types.isMap,
|
||||
set: types.set,
|
||||
isSet: types.isSet,
|
||||
list: types.list,
|
||||
isList: types.isList,
|
||||
quoted: types.quoted,
|
||||
isQuoted: types.isQuoted,
|
||||
tagged: types.taggedValue,
|
||||
isTaggedValue: types.isTaggedValue,
|
||||
link: types.link,
|
||||
isLink: types.isLink,
|
||||
hash: eq.hashCode,
|
||||
hashArrayLike: eq.hashArrayLike,
|
||||
hashMapLike: eq.hashMapLike,
|
||||
equals: eq.equals,
|
||||
extendToEQ: eq.extendToEQ,
|
||||
mapToObject: transit.mapToObject,
|
||||
decoder: decoder.decoder,
|
||||
UUIDfromString: types.UUIDfromString,
|
||||
randomUUID: types.randomUUID,
|
||||
stringableKeys: writer.stringableKeys,
|
||||
readCache: caching.readCache,
|
||||
writeCache: caching.writeCache
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
Executable
+177
@@ -0,0 +1,177 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.caching");
|
||||
goog.require("com.cognitect.transit.delimiters");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var caching = com.cognitect.transit.caching,
|
||||
d = com.cognitect.transit.delimiters;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
caching.MIN_SIZE_CACHEABLE = 3;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
caching.BASE_CHAR_IDX = 48;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
caching.CACHE_CODE_DIGITS = 44;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
caching.MAX_CACHE_ENTRIES = caching.CACHE_CODE_DIGITS*caching.CACHE_CODE_DIGITS;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
caching.MAX_CACHE_SIZE = 4096;
|
||||
|
||||
caching.isCacheable = function(string, asMapKey) {
|
||||
if(string.length > caching.MIN_SIZE_CACHEABLE) {
|
||||
if(asMapKey) {
|
||||
return true;
|
||||
} else {
|
||||
var c0 = string.charAt(0),
|
||||
c1 = string.charAt(1);
|
||||
if(c0 === d.ESC) {
|
||||
return c1 === ":" || c1 === "$" || c1 === "#";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// WriteCache
|
||||
|
||||
caching.idxToCode = function(idx) {
|
||||
var hi = Math.floor(idx / caching.CACHE_CODE_DIGITS),
|
||||
lo = idx % caching.CACHE_CODE_DIGITS,
|
||||
loc = String.fromCharCode(lo + caching.BASE_CHAR_IDX)
|
||||
if(hi === 0) {
|
||||
return d.SUB + loc;
|
||||
} else {
|
||||
return d.SUB + String.fromCharCode(hi + caching.BASE_CHAR_IDX) + loc;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
caching.WriteCache = function() {
|
||||
this.idx = 0;
|
||||
this.gen = 0;
|
||||
this.cacheSize = 0;
|
||||
this.cache = {};
|
||||
};
|
||||
|
||||
caching.WriteCache.prototype.write = function(string, asMapKey) {
|
||||
if(caching.isCacheable(string, asMapKey)) {
|
||||
if(this.cacheSize === caching.MAX_CACHE_SIZE) {
|
||||
this.clear();
|
||||
this.gen = 0;
|
||||
this.cache = {};
|
||||
} else if(this.idx === caching.MAX_CACHE_ENTRIES) {
|
||||
this.clear();
|
||||
}
|
||||
var entry = this.cache[string];
|
||||
if(entry == null) {
|
||||
this.cache[string] = [caching.idxToCode(this.idx), this.gen];
|
||||
this.idx++;
|
||||
return string;
|
||||
} else if(entry[1] != this.gen) {
|
||||
entry[1] = this.gen;
|
||||
entry[0] = caching.idxToCode(this.idx);
|
||||
this.idx++;
|
||||
return string;
|
||||
} else {
|
||||
return entry[0];
|
||||
}
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
caching.WriteCache.prototype.clear = function() {
|
||||
this.idx = 0;
|
||||
this.gen++;
|
||||
};
|
||||
|
||||
caching.writeCache = function() {
|
||||
return new caching.WriteCache();
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// ReadCache
|
||||
|
||||
caching.isCacheCode = function(string) {
|
||||
return (string.charAt(0) === d.SUB) && (string.charAt(1) !== " ");
|
||||
};
|
||||
|
||||
caching.codeToIdx = function(code) {
|
||||
if(code.length === 2) {
|
||||
return code.charCodeAt(1) - caching.BASE_CHAR_IDX;
|
||||
} else {
|
||||
var hi = (code.charCodeAt(1) - caching.BASE_CHAR_IDX) * caching.CACHE_CODE_DIGITS,
|
||||
lo = (code.charCodeAt(2) - caching.BASE_CHAR_IDX);
|
||||
return hi + lo;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
caching.ReadCache = function() {
|
||||
this.idx = 0;
|
||||
this.cache = [];
|
||||
};
|
||||
|
||||
caching.ReadCache.prototype.write = function(obj, asMapKey) {
|
||||
if(this.idx == caching.MAX_CACHE_ENTRIES) {
|
||||
this.idx = 0;
|
||||
}
|
||||
this.cache[this.idx] = obj;
|
||||
this.idx++;
|
||||
return obj;
|
||||
};
|
||||
|
||||
caching.ReadCache.prototype.read = function(string, asMapKey) {
|
||||
return this.cache[caching.codeToIdx(string)];
|
||||
};
|
||||
|
||||
caching.ReadCache.prototype.clear = function() {
|
||||
this.idx = 0;
|
||||
};
|
||||
|
||||
caching.readCache = function() {
|
||||
return new caching.ReadCache();
|
||||
};
|
||||
|
||||
});
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.delimiters");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var delimiters = com.cognitect.transit.delimiters;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
delimiters.ESC = "~";
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
delimiters.TAG = "#";
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
delimiters.SUB = "^";
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
delimiters.RES = "`";
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
delimiters.ESC_TAG = "~#";
|
||||
|
||||
});
|
||||
Executable
+204
@@ -0,0 +1,204 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.eq");
|
||||
goog.require("com.cognitect.transit.util");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var eq = com.cognitect.transit.eq,
|
||||
util = com.cognitect.transit.util;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
eq.hashCodeProperty = "transit$hashCode$";
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
eq.hashCodeCounter = 1;
|
||||
|
||||
eq.equals = function (x, y) {
|
||||
if(x == null) {
|
||||
return y == null;
|
||||
} else if(x === y) {
|
||||
return true;
|
||||
} else if(typeof x === "object") {
|
||||
if(util.isArray(x)) {
|
||||
if(util.isArray(y)) {
|
||||
if(x.length === y.length) {
|
||||
for(var i = 0; i < x.length; i++) {
|
||||
if(!eq.equals(x[i], y[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if(x.com$cognitect$transit$equals) {
|
||||
return x.com$cognitect$transit$equals(y);
|
||||
} else if((y != null) && (typeof y === "object")) {
|
||||
if(y.com$cognitect$transit$equals) {
|
||||
return y.com$cognitect$transit$equals(x);
|
||||
} else {
|
||||
var xklen = 0,
|
||||
yklen = util.objectKeys(y).length;
|
||||
for(var p in x) {
|
||||
if(!x.hasOwnProperty(p)) continue;
|
||||
xklen++;
|
||||
if(!y.hasOwnProperty(p)) {
|
||||
return false;
|
||||
} else {
|
||||
if(!eq.equals(x[p], y[p])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return xklen === yklen;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
};
|
||||
|
||||
eq.hashCombine = function(seed, hash) {
|
||||
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
||||
};
|
||||
|
||||
eq.stringCodeCache = {};
|
||||
eq.stringCodeCacheSize = 0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
eq.STR_CACHE_MAX = 256;
|
||||
|
||||
eq.hashString = function(str) {
|
||||
// a la goog.string.HashCode
|
||||
// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1206
|
||||
var cached = eq.stringCodeCache[str];
|
||||
if(cached != null) {
|
||||
return cached;
|
||||
}
|
||||
var code = 0;
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
code = 31 * code + str.charCodeAt(i);
|
||||
code %= 0x100000000;
|
||||
}
|
||||
eq.stringCodeCacheSize++;
|
||||
if(eq.stringCodeCacheSize >= eq.STR_CACHE_MAX) {
|
||||
eq.stringCodeCache = {};
|
||||
eq.stringCodeCacheSize = 1;
|
||||
}
|
||||
eq.stringCodeCache[str] = code;
|
||||
return code;
|
||||
};
|
||||
|
||||
eq.hashMapLike = function(m) {
|
||||
var code = 0;
|
||||
// ES6 Map-like case
|
||||
if(m.forEach != null) {
|
||||
m.forEach(function(val, key, m) {
|
||||
code = (code + (eq.hashCode(key) ^ eq.hashCode(val))) % 4503599627370496;
|
||||
});
|
||||
} else {
|
||||
// JS Object case
|
||||
var keys = util.objectKeys(m);
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var val = m[key];
|
||||
code = (code + (eq.hashCode(key) ^ eq.hashCode(val))) % 4503599627370496;
|
||||
}
|
||||
}
|
||||
return code;
|
||||
};
|
||||
|
||||
eq.hashArrayLike = function(arr) {
|
||||
var code = 0;
|
||||
if(util.isArray(arr)) {
|
||||
for(var i = 0; i < arr.length; i++) {
|
||||
code = eq.hashCombine(code, eq.hashCode(arr[i]));
|
||||
}
|
||||
} else if(arr.forEach) {
|
||||
arr.forEach(function(x, i) {
|
||||
code = eq.hashCombine(code, eq.hashCode(x));
|
||||
});
|
||||
}
|
||||
return code;
|
||||
};
|
||||
|
||||
eq.hashCode = function(x) {
|
||||
if(x == null) {
|
||||
return 0;
|
||||
} else {
|
||||
switch(typeof x) {
|
||||
case 'number':
|
||||
return x;
|
||||
break;
|
||||
case 'boolean':
|
||||
return x === true ? 1 : 0;
|
||||
break;
|
||||
case 'string':
|
||||
return eq.hashString(x);
|
||||
break;
|
||||
case 'function':
|
||||
var code = x[eq.hashCodeProperty];
|
||||
if(code) {
|
||||
return code;
|
||||
} else {
|
||||
code = eq.hashCodeCounter;
|
||||
if(typeof Object.defineProperty != "undefined") {
|
||||
Object.defineProperty(x, eq.hashCodeProperty, {
|
||||
value: code,
|
||||
enumerable: false
|
||||
});
|
||||
} else {
|
||||
x[eq.hashCodeProperty] = code;
|
||||
}
|
||||
eq.hashCodeCounter++;
|
||||
return code;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(x instanceof Date) {
|
||||
return x.valueOf();
|
||||
} else if(util.isArray(x)) {
|
||||
return eq.hashArrayLike(x);
|
||||
} if(x.com$cognitect$transit$hashCode) {
|
||||
return x.com$cognitect$transit$hashCode();
|
||||
} else {
|
||||
return eq.hashMapLike(x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eq.extendToEQ = function(obj, opts) {
|
||||
obj.com$cognitect$transit$hashCode = opts["hashCode"];
|
||||
obj.com$cognitect$transit$equals = opts["equals"];
|
||||
return obj;
|
||||
}
|
||||
|
||||
});
|
||||
Executable
+324
@@ -0,0 +1,324 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.handlers");
|
||||
goog.require("com.cognitect.transit.util");
|
||||
goog.require("com.cognitect.transit.types");
|
||||
goog.require("goog.math.Long");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var handlers = com.cognitect.transit.handlers,
|
||||
util = com.cognitect.transit.util,
|
||||
types = com.cognitect.transit.types,
|
||||
Long = goog.math.Long;
|
||||
|
||||
handlers.ctorGuid = 0;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
handlers.ctorGuidProperty = "transit$guid$" + util.randomUUID();
|
||||
|
||||
handlers.typeTag = function(ctor) {
|
||||
if(ctor == null) {
|
||||
return "null";
|
||||
} else if(ctor === String) {
|
||||
return "string";
|
||||
} else if(ctor === Boolean) {
|
||||
return "boolean";
|
||||
} else if(ctor === Number) {
|
||||
return "number";
|
||||
} else if(ctor === Array) {
|
||||
return "array";
|
||||
} else if(ctor === Object) {
|
||||
return "map";
|
||||
} else {
|
||||
var tag = ctor[handlers.ctorGuidProperty];
|
||||
if(tag == null) {
|
||||
if(typeof Object.defineProperty != "undefined") {
|
||||
tag = ++handlers.ctorGuid;
|
||||
Object.defineProperty(ctor, handlers.ctorGuidProperty, {
|
||||
value: tag,
|
||||
enumerable: false
|
||||
});
|
||||
} else {
|
||||
ctor[handlers.ctorGuidProperty] = tag = ++handlers.ctorGuid;
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
};
|
||||
|
||||
handlers.constructor = function(x) {
|
||||
if(x == null) {
|
||||
return null;
|
||||
} else {
|
||||
return x.constructor;
|
||||
}
|
||||
};
|
||||
|
||||
handlers.padZeros = function(n,m) {
|
||||
var s = n.toString();
|
||||
for(var i = s.length; i < m; i++) {
|
||||
s = "0"+s;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
handlers.stringableKeys = function(m) {
|
||||
var stringable = false,
|
||||
ks = util.objectKeys(m);
|
||||
|
||||
for(var i = 0; i < ks.length; i++) {
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.NilHandler = function(){};
|
||||
handlers.NilHandler.prototype.tag = function(v) { return "_"; };
|
||||
handlers.NilHandler.prototype.rep = function(v) { return null; };
|
||||
handlers.NilHandler.prototype.stringRep = function(v) { return "null"; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.StringHandler = function(){};
|
||||
handlers.StringHandler.prototype.tag = function(v) { return "s"; };
|
||||
handlers.StringHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.StringHandler.prototype.stringRep = function(v) { return v; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.NumberHandler = function(){};
|
||||
handlers.NumberHandler.prototype.tag = function(v) { return "i"; };
|
||||
handlers.NumberHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.NumberHandler.prototype.stringRep = function(v) { return v.toString(); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.IntegerHandler = function(){};
|
||||
handlers.IntegerHandler.prototype.tag = function(v) { return "i"; };
|
||||
handlers.IntegerHandler.prototype.rep = function(v) { return v.toString(); };
|
||||
handlers.IntegerHandler.prototype.stringRep = function(v) { return v.toString(); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.BooleanHandler = function(){};
|
||||
handlers.BooleanHandler.prototype.tag = function(v) { return "?"; };
|
||||
handlers.BooleanHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.BooleanHandler.prototype.stringRep = function(v) { return v.toString(); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.ArrayHandler = function(){};
|
||||
handlers.ArrayHandler.prototype.tag = function(v) { return "array"; };
|
||||
handlers.ArrayHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.ArrayHandler.prototype.stringRep = function(v) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.MapHandler = function(){};
|
||||
handlers.MapHandler.prototype.tag = function(v) { return "map"; };
|
||||
handlers.MapHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.MapHandler.prototype.stringRep = function(v) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.VerboseDateHandler = function(){};
|
||||
handlers.VerboseDateHandler.prototype.tag = function(v) { return "t"; };
|
||||
handlers.VerboseDateHandler.prototype.rep = function(v) {
|
||||
return v.getUTCFullYear()+"-"+handlers.padZeros(v.getUTCMonth()+1,2)+"-"+
|
||||
handlers.padZeros(v.getUTCDate(),2)+"T"+handlers.padZeros(v.getUTCHours(),2)+":"+
|
||||
handlers.padZeros(v.getUTCMinutes(),2)+":"+handlers.padZeros(v.getUTCSeconds(),2)+"."+
|
||||
handlers.padZeros(v.getUTCMilliseconds(),3)+"Z";
|
||||
};
|
||||
handlers.VerboseDateHandler.prototype.stringRep = function(v, h) {
|
||||
return h.rep(v);
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.DateHandler = function(){};
|
||||
handlers.DateHandler.prototype.tag = function(v) { return "m"; };
|
||||
handlers.DateHandler.prototype.rep = function(v) { return v.valueOf(); };
|
||||
handlers.DateHandler.prototype.stringRep = function(v) { return v.valueOf().toString(); };
|
||||
handlers.DateHandler.prototype.getVerboseHandler = function(v) {
|
||||
return new handlers.VerboseDateHandler();
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.UUIDHandler = function(){};
|
||||
handlers.UUIDHandler.prototype.tag = function(v) { return "u"; };
|
||||
handlers.UUIDHandler.prototype.rep = function(v) { return v.toString(); };
|
||||
handlers.UUIDHandler.prototype.stringRep = function(v) { return v.toString(); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.KeywordHandler = function(){};
|
||||
handlers.KeywordHandler.prototype.tag = function(v) { return ":"; };
|
||||
handlers.KeywordHandler.prototype.rep = function(v) { return v.name; }; // NOTE: should be fqn
|
||||
handlers.KeywordHandler.prototype.stringRep = function(v, h) { return h.rep(v); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.SymbolHandler = function(){};
|
||||
handlers.SymbolHandler.prototype.tag = function(v) { return "$"; };
|
||||
handlers.SymbolHandler.prototype.rep = function(v) { return v.name; }; // NOTE: should be str
|
||||
handlers.SymbolHandler.prototype.stringRep = function(v, h) { return h.rep(v); };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.TaggedHandler = function(){};
|
||||
handlers.TaggedHandler.prototype.tag = function(v) { return v.tag; };
|
||||
handlers.TaggedHandler.prototype.rep = function(v) { return v.rep; };
|
||||
handlers.TaggedHandler.prototype.stringRep = function(v, h) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.TransitSetHandler = function(){};
|
||||
handlers.TransitSetHandler.prototype.tag = function(v) { return "set"; };
|
||||
handlers.TransitSetHandler.prototype.rep = function(v) {
|
||||
var arr = [];
|
||||
v.forEach(function(key, set) {
|
||||
arr.push(key);
|
||||
});
|
||||
return types.taggedValue("array", arr);
|
||||
};
|
||||
handlers.TransitSetHandler.prototype.stringRep = function(v, h) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.TransitArrayMapHandler = function(){};
|
||||
handlers.TransitArrayMapHandler.prototype.tag = function(v) { return "map"; };
|
||||
handlers.TransitArrayMapHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.TransitArrayMapHandler.prototype.stringRep = function(v, h) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.TransitMapHandler = function(){};
|
||||
handlers.TransitMapHandler.prototype.tag = function(v) { return "map"; };
|
||||
handlers.TransitMapHandler.prototype.rep = function(v) { return v; };
|
||||
handlers.TransitMapHandler.prototype.stringRep = function(v, h) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.BufferHandler = function() {};
|
||||
handlers.BufferHandler.prototype.tag = function(v) { return "b"; };
|
||||
handlers.BufferHandler.prototype.rep = function(v) { return v.toString("base64"); };
|
||||
handlers.BufferHandler.prototype.stringRep = function(v, h) { return null; };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.Uint8ArrayHandler = function() {};
|
||||
handlers.Uint8ArrayHandler.prototype.tag = function(v) { return "b"; };
|
||||
handlers.Uint8ArrayHandler.prototype.rep = function(v) { return util.Uint8ToBase64(v); };
|
||||
handlers.Uint8ArrayHandler.prototype.stringRep = function(v, h) { return null; };
|
||||
|
||||
handlers.defaultHandlers = function(hs) {
|
||||
hs.set(null, new handlers.NilHandler());
|
||||
hs.set(String, new handlers.StringHandler());
|
||||
hs.set(Number, new handlers.NumberHandler());
|
||||
hs.set(Long, new handlers.IntegerHandler());
|
||||
hs.set(Boolean, new handlers.BooleanHandler());
|
||||
hs.set(Array, new handlers.ArrayHandler());
|
||||
hs.set(Object, new handlers.MapHandler());
|
||||
hs.set(Date, new handlers.DateHandler());
|
||||
hs.set(types.UUID, new handlers.UUIDHandler());
|
||||
hs.set(types.Keyword, new handlers.KeywordHandler());
|
||||
hs.set(types.Symbol, new handlers.SymbolHandler());
|
||||
hs.set(types.TaggedValue, new handlers.TaggedHandler());
|
||||
hs.set(types.TransitSet, new handlers.TransitSetHandler());
|
||||
hs.set(types.TransitArrayMap, new handlers.TransitArrayMapHandler());
|
||||
hs.set(types.TransitMap, new handlers.TransitMapHandler());
|
||||
|
||||
if(typeof Buffer != "undefined") {
|
||||
hs.set(Buffer, new handlers.BufferHandler());
|
||||
}
|
||||
|
||||
if(typeof Uint8Array != "undefined") {
|
||||
hs.set(Uint8Array, new handlers.Uint8ArrayHandler());
|
||||
}
|
||||
|
||||
return hs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
handlers.Handlers = function() {
|
||||
this.handlers = {};
|
||||
handlers.defaultHandlers(this);
|
||||
};
|
||||
|
||||
handlers.Handlers.prototype.get = function(ctor) {
|
||||
var h = null;
|
||||
if(typeof ctor === "string") {
|
||||
h = this.handlers[ctor];
|
||||
} else {
|
||||
h = this.handlers[handlers.typeTag(ctor)];
|
||||
}
|
||||
if(h != null) {
|
||||
return h;
|
||||
} else {
|
||||
return this.handlers["default"];
|
||||
}
|
||||
};
|
||||
handlers.Handlers.prototype["get"] = handlers.Handlers.prototype.get;
|
||||
|
||||
handlers.validTag = function(tag) {
|
||||
switch(tag) {
|
||||
case "null":
|
||||
case "string":
|
||||
case "boolean":
|
||||
case "number":
|
||||
case "array":
|
||||
case "map":
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
handlers.Handlers.prototype.set = function(ctor, handler) {
|
||||
if(typeof ctor === "string" && handlers.validTag(ctor)) {
|
||||
this.handlers[ctor] = handler;
|
||||
} else {
|
||||
this.handlers[handlers.typeTag(ctor)] = handler;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
Executable
+317
@@ -0,0 +1,317 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.impl.decoder");
|
||||
goog.require("com.cognitect.transit.util");
|
||||
goog.require("com.cognitect.transit.delimiters");
|
||||
goog.require("com.cognitect.transit.caching");
|
||||
goog.require("com.cognitect.transit.types");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var decoder = com.cognitect.transit.impl.decoder,
|
||||
util = com.cognitect.transit.util,
|
||||
d = com.cognitect.transit.delimiters,
|
||||
caching = com.cognitect.transit.caching,
|
||||
types = com.cognitect.transit.types;
|
||||
|
||||
// =============================================================================
|
||||
// Decoder
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
decoder.Tag = function(s) {
|
||||
this.str = s;
|
||||
};
|
||||
|
||||
decoder.tag = function(s) {
|
||||
return new decoder.Tag(s);
|
||||
};
|
||||
|
||||
decoder.isTag = function(x) {
|
||||
return x && (x instanceof decoder.Tag);
|
||||
};
|
||||
|
||||
decoder.isGroundHandler = function(handler) {
|
||||
switch(handler) {
|
||||
case "_":
|
||||
case "s":
|
||||
case "?":
|
||||
case "i":
|
||||
case "d":
|
||||
case "b":
|
||||
case "'":
|
||||
case "array":
|
||||
case "map":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* A transit decoder
|
||||
* @constructor
|
||||
*/
|
||||
decoder.Decoder = function(options) {
|
||||
this.options = options || {};
|
||||
this.handlers = {};
|
||||
for(var h in this.defaults.handlers) {
|
||||
this.handlers[h] = this.defaults.handlers[h];
|
||||
}
|
||||
for(var h in this.options["handlers"]) {
|
||||
if(decoder.isGroundHandler(h)) {
|
||||
throw new Error("Cannot override handler for ground type \""+h+"\"");
|
||||
}
|
||||
this.handlers[h] = this.options["handlers"][h];
|
||||
}
|
||||
this.preferStrings = this.options["preferStrings"] != null ? this.options["preferStrings"] : this.defaults.preferStrings;
|
||||
this.preferBuffers = this.options["preferBuffers"] != null ? this.options["preferBuffers"] : this.defaults.preferBuffers;
|
||||
this.defaultHandler = this.options["defaultHandler"] || this.defaults.defaultHandler;
|
||||
/* NOT PUBLIC */
|
||||
this.mapBuilder = this.options["mapBuilder"];
|
||||
this.arrayBuilder = this.options["arrayBuilder"];
|
||||
};
|
||||
|
||||
|
||||
decoder.Decoder.prototype.defaults = {
|
||||
handlers: {
|
||||
"_": function(v, d) { return types.nullValue(); },
|
||||
"?": function(v, d) { return types.boolValue(v); },
|
||||
"b": function(v, d) { return types.binary(v, d); },
|
||||
"i": function(v, d) { return types.intValue(v); },
|
||||
"n": function(v, d) { return types.bigInteger(v); },
|
||||
"d": function(v, d) { return types.floatValue(v); },
|
||||
"f": function(v, d) { return types.bigDecimalValue(v); },
|
||||
"c": function(v, d) { return types.charValue(v); },
|
||||
":": function(v, d) { return types.keyword(v); },
|
||||
"$": function(v, d) { return types.symbol(v); },
|
||||
"r": function(v, d) { return types.uri(v); },
|
||||
"z": function(v, d) { return types.specialDouble(v); },
|
||||
|
||||
// tagged
|
||||
"'": function(v, d) { return v; },
|
||||
"m": function(v, d) { return types.date(v); },
|
||||
"t": function(v, d) { return types.verboseDate(v); },
|
||||
"u": function(v, d) { return types.uuid(v); },
|
||||
"set": function(v, d) { return types.set(v); },
|
||||
"list": function(v, d) { return types.list(v); },
|
||||
"link": function(v, d) { return types.link(v); },
|
||||
"cmap": function(v, d) { return types.map(v, false); }
|
||||
},
|
||||
defaultHandler: function(c, val) {
|
||||
return types.taggedValue(c, val);
|
||||
},
|
||||
preferStrings: true,
|
||||
preferBuffers: true
|
||||
};
|
||||
|
||||
decoder.Decoder.prototype.decode = function(node, cache, asMapKey, tagValue) {
|
||||
if(node == null) return null;
|
||||
|
||||
var t = typeof node;
|
||||
|
||||
switch(t) {
|
||||
case "string":
|
||||
return this.decodeString(node, cache, asMapKey, tagValue);
|
||||
break;
|
||||
case "object":
|
||||
if(util.isArray(node)) {
|
||||
if(node[0] === "^ ") {
|
||||
return this.decodeArrayHash(node, cache, asMapKey, tagValue);
|
||||
} else {
|
||||
return this.decodeArray(node, cache, asMapKey, tagValue);
|
||||
}
|
||||
} else {
|
||||
return this.decodeHash(node, cache, asMapKey, tagValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
decoder.Decoder.prototype["decode"] = decoder.Decoder.prototype.decode;
|
||||
|
||||
decoder.Decoder.prototype.decodeString = function(string, cache, asMapKey, tagValue) {
|
||||
if(caching.isCacheable(string, asMapKey)) {
|
||||
var val = this.parseString(string, cache, false);
|
||||
if(cache) {
|
||||
cache.write(val, asMapKey);
|
||||
}
|
||||
return val;
|
||||
} else if(caching.isCacheCode(string)) {
|
||||
return cache.read(string, asMapKey);
|
||||
} else {
|
||||
return this.parseString(string, cache, asMapKey);
|
||||
}
|
||||
};
|
||||
|
||||
decoder.Decoder.prototype.decodeHash = function(hash, cache, asMapKey, tagValue) {
|
||||
var ks = util.objectKeys(hash),
|
||||
key = ks[0],
|
||||
tag = ks.length == 1 ? this.decode(key, cache, false, false) : null;
|
||||
|
||||
if(decoder.isTag(tag)) {
|
||||
var val = hash[key],
|
||||
handler = this.handlers[tag.str];
|
||||
if(handler != null) {
|
||||
return handler(this.decode(val, cache, false, true), this);
|
||||
} else {
|
||||
return types.taggedValue(tag.str, this.decode(val, cache, false, false));
|
||||
}
|
||||
} else if(this.mapBuilder) {
|
||||
if((ks.length < (types.SMALL_ARRAY_MAP_THRESHOLD*2)) && this.mapBuilder.fromArray) {
|
||||
var nodep = [];
|
||||
for(var i = 0; i < ks.length; i++) {
|
||||
var strKey = ks[i];
|
||||
nodep.push(this.decode(strKey, cache, true, false));
|
||||
nodep.push(this.decode(hash[strKey], cache, false, false));
|
||||
}
|
||||
return this.mapBuilder.fromArray(nodep, hash);
|
||||
} else {
|
||||
var ret = this.mapBuilder.init(hash);
|
||||
for(var i = 0; i < ks.length; i++) {
|
||||
var strKey = ks[i];
|
||||
ret = this.mapBuilder.add(ret,
|
||||
this.decode(strKey, cache, true, false),
|
||||
this.decode(hash[strKey], cache, false, false),
|
||||
hash);
|
||||
}
|
||||
return this.mapBuilder.finalize(ret, hash);
|
||||
}
|
||||
} else {
|
||||
var nodep = [];
|
||||
|
||||
for(var i = 0; i < ks.length; i++) {
|
||||
var strKey = ks[i];
|
||||
nodep.push(this.decode(strKey, cache, true, false));
|
||||
nodep.push(this.decode(hash[strKey], cache, false, false));
|
||||
}
|
||||
|
||||
return types.map(nodep, false);
|
||||
}
|
||||
};
|
||||
|
||||
decoder.Decoder.prototype.decodeArrayHash = function(node, cache, asMapKey, tagValue) {
|
||||
if(this.mapBuilder) {
|
||||
if((node.length < ((types.SMALL_ARRAY_MAP_THRESHOLD*2)+1)) && this.mapBuilder.fromArray) {
|
||||
var nodep = [];
|
||||
for(var i = 1; i < node.length; i+=2) {
|
||||
nodep.push(this.decode(node[i], cache, true, false));
|
||||
nodep.push(this.decode(node[i+1], cache, false, false));
|
||||
}
|
||||
return this.mapBuilder.fromArray(nodep, node);
|
||||
} else {
|
||||
var ret = this.mapBuilder.init(node);
|
||||
for(var i = 1; i < node.length; i+=2) {
|
||||
ret = this.mapBuilder.add(ret,
|
||||
this.decode(node[i], cache, true, false),
|
||||
this.decode(node[i+1], cache, false, false),
|
||||
node)
|
||||
}
|
||||
return this.mapBuilder.finalize(ret, node);
|
||||
}
|
||||
} else {
|
||||
var nodep = [];
|
||||
|
||||
// collect keys
|
||||
for(var i = 1; i < node.length; i +=2) {
|
||||
nodep.push(this.decode(node[i], cache, true, false));
|
||||
nodep.push(this.decode(node[i+1], cache, false, false));
|
||||
}
|
||||
|
||||
return types.map(nodep, false);
|
||||
}
|
||||
};
|
||||
|
||||
decoder.Decoder.prototype.decodeArray = function(node, cache, asMapKey, tagValue) {
|
||||
if(tagValue) {
|
||||
var ret = [];
|
||||
for(var i = 0; i < node.length; i++) {
|
||||
ret.push(this.decode(node[i], cache, asMapKey, false));
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
var cacheIdx = cache && cache.idx;
|
||||
// tagged value as 2-array case
|
||||
if((node.length === 2) &&
|
||||
(typeof node[0] === "string")) {
|
||||
var tag = this.decode(node[0], cache, false, false);
|
||||
if(decoder.isTag(tag)) {
|
||||
var val = node[1],
|
||||
handler = this.handlers[tag.str];
|
||||
if(handler != null) {
|
||||
var ret = handler(this.decode(val, cache, asMapKey, true), this);
|
||||
return ret;
|
||||
} else {
|
||||
return types.taggedValue(tag.str, this.decode(val, cache, asMapKey, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rewind cache
|
||||
if(cache && (cacheIdx != cache.idx)) {
|
||||
cache.idx = cacheIdx;
|
||||
}
|
||||
|
||||
if(this.arrayBuilder) {
|
||||
// NOTE: hard coded for ClojureScript for now - David
|
||||
if(node.length <= 32 && this.arrayBuilder.fromArray) {
|
||||
var arr = [];
|
||||
for(var i = 0; i < node.length; i++) {
|
||||
arr.push(this.decode(node[i], cache, asMapKey, false));
|
||||
}
|
||||
return this.arrayBuilder.fromArray(arr, node);
|
||||
} else {
|
||||
var ret = this.arrayBuilder.init();
|
||||
for(var i = 0; i < node.length; i++) {
|
||||
ret = this.arrayBuilder.add(ret, this.decode(node[i], cache, asMapKey, false), node);
|
||||
}
|
||||
return this.arrayBuilder.finalize(ret, node);
|
||||
}
|
||||
} else {
|
||||
var ret = [];
|
||||
for(var i = 0; i < node.length; i++) {
|
||||
ret.push(this.decode(node[i], cache, asMapKey, false));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
decoder.Decoder.prototype.parseString = function(string, cache, asMapKey) {
|
||||
if(string.charAt(0) === d.ESC) {
|
||||
var c = string.charAt(1);
|
||||
if(c === d.ESC || c === d.SUB || c === d.RES) {
|
||||
return string.substring(1);
|
||||
} else if (c === d.TAG) {
|
||||
return decoder.tag(string.substring(2));
|
||||
} else {
|
||||
var handler = this.handlers[c];
|
||||
if(handler == null) {
|
||||
return this.defaultHandler(c, string.substring(2));
|
||||
} else {
|
||||
return handler(string.substring(2), this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
decoder.decoder = function(options) {
|
||||
return new decoder.Decoder(options);
|
||||
};
|
||||
|
||||
});
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.impl.reader");
|
||||
goog.require("com.cognitect.transit.impl.decoder");
|
||||
goog.require("com.cognitect.transit.caching");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var reader = com.cognitect.transit.impl.reader,
|
||||
decoder = com.cognitect.transit.impl.decoder,
|
||||
caching = com.cognitect.transit.caching;
|
||||
|
||||
/**
|
||||
* A JSON unmarshaller
|
||||
* @constructor
|
||||
*/
|
||||
reader.JSONUnmarshaller = function(opts) {
|
||||
this.decoder = new decoder.Decoder(opts);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} str a JSON string
|
||||
* @param {caching.ReadCache} cache a read cache
|
||||
* @returns {Object}
|
||||
*/
|
||||
reader.JSONUnmarshaller.prototype.unmarshal = function(str, cache) {
|
||||
return this.decoder.decode(JSON.parse(str), cache);
|
||||
};
|
||||
|
||||
/**
|
||||
* A transit reader
|
||||
* @constructor
|
||||
* @param {reader.JSONUnmarshaller} unmarshaller
|
||||
* @param {Object} options
|
||||
*/
|
||||
reader.Reader = function(unmarshaller, options) {
|
||||
this.unmarshaller = unmarshaller;
|
||||
this.options = options || {};
|
||||
this.cache = this.options["cache"] ? this.options["cache"] : new caching.ReadCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} str a string to be read
|
||||
* @returns {Object}
|
||||
*/
|
||||
reader.Reader.prototype.read = function(str) {
|
||||
var ret = this.unmarshaller.unmarshal(str, this.cache)
|
||||
this.cache.clear();
|
||||
return ret;
|
||||
};
|
||||
reader.Reader.prototype["read"] = reader.Reader.prototype.read;
|
||||
|
||||
});
|
||||
Executable
+491
@@ -0,0 +1,491 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.impl.writer");
|
||||
goog.require("com.cognitect.transit.util");
|
||||
goog.require("com.cognitect.transit.caching");
|
||||
goog.require("com.cognitect.transit.handlers");
|
||||
goog.require("com.cognitect.transit.types");
|
||||
goog.require("com.cognitect.transit.delimiters");
|
||||
goog.require("goog.math.Long");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var writer = com.cognitect.transit.impl.writer,
|
||||
util = com.cognitect.transit.util,
|
||||
caching = com.cognitect.transit.caching,
|
||||
handlers = com.cognitect.transit.handlers,
|
||||
types = com.cognitect.transit.types,
|
||||
d = com.cognitect.transit.delimiters,
|
||||
Long = goog.math.Long;
|
||||
|
||||
writer.escape = function(string) {
|
||||
if(string.length > 0) {
|
||||
var c = string.charAt(0);
|
||||
if(c === d.ESC || c === d.SUB || c === d.RES) {
|
||||
return d.ESC+string;
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
writer.JSONMarshaller = function(opts) {
|
||||
this.opts = opts || {};
|
||||
this.preferStrings = this.opts["preferStrings"] != null ? this.opts["preferStrings"] : true;
|
||||
|
||||
this.objectBuilder = this.opts["objectBuilder"] || null;
|
||||
|
||||
this.handlers = new handlers.Handlers();
|
||||
|
||||
var optsHandlers = this.opts["handlers"];
|
||||
if(optsHandlers) {
|
||||
if(util.isArray(optsHandlers) || !optsHandlers.forEach) {
|
||||
throw new Error("transit writer \"handlers\" option must be a map");
|
||||
}
|
||||
var self = this;
|
||||
optsHandlers.forEach(function(v, k) {
|
||||
self.handlers.set(k, v);
|
||||
});
|
||||
}
|
||||
|
||||
// Multiple JS context helper
|
||||
this.handlerForForeign = this.opts["handlerForForeign"];
|
||||
|
||||
this.unpack = this.opts["unpack"] || function(x) {
|
||||
if(types.isArrayMap(x) && x.backingMap === null) {
|
||||
return x._entries;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
this.verbose = (this.opts && this.opts["verbose"]) || false;
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.handler = function(obj) {
|
||||
var h = this.handlers.get(handlers.constructor(obj));
|
||||
|
||||
if(h != null) {
|
||||
return h;
|
||||
} else {
|
||||
var tag = obj && obj["transitTag"];
|
||||
if(tag) {
|
||||
return this.handlers.get(tag)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.registerHandler = function(ctor, handler) {
|
||||
this.handlers.set(ctor, handler);
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitNil = function(asMapKey, cache) {
|
||||
if(asMapKey) {
|
||||
return this.emitString(d.ESC, "_", "", asMapKey, cache);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitString = function(prefix, tag, s, asMapKey, cache) {
|
||||
var string = prefix+tag+s;
|
||||
if(cache) {
|
||||
return cache.write(string, asMapKey);
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitBoolean = function(b, asMapKey, cache) {
|
||||
if(asMapKey) {
|
||||
var s = b.toString();
|
||||
return this.emitString(d.ESC, "?", s[0], asMapKey, cache);
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitInteger = function(i, asMapKey, cache) {
|
||||
if(i === Infinity) {
|
||||
return this.emitString(d.ESC, "z", "INF", asMapKey, cache);
|
||||
} else if(i === -Infinity) {
|
||||
return this.emitString(d.ESC, "z", "-INF", asMapKey, cache);
|
||||
} else if(isNaN(i)) {
|
||||
return this.emitString(d.ESC, "z", "NaN", asMapKey, cache);
|
||||
} else if(asMapKey || (typeof i === "string") || (i instanceof Long)) {
|
||||
return this.emitString(d.ESC, "i", i.toString(), asMapKey, cache);
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitDouble = function(d, asMapKey, cache) {
|
||||
if(asMapKey) {
|
||||
return this.emitString(d.ESC, "d", d, asMapKey, cache);
|
||||
} else {
|
||||
return d;
|
||||
}
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitBinary = function(b, asMapKey, cache) {
|
||||
return this.emitString(d.ESC, "b", b, asMapKey, cache);
|
||||
};
|
||||
|
||||
writer.JSONMarshaller.prototype.emitQuoted = function(em, obj, cache) {
|
||||
if(em.verbose) {
|
||||
var ret = {},
|
||||
k = this.emitString(d.ESC_TAG, "'", "", true, cache);
|
||||
ret[k] = writer.marshal(this, obj, false, cache);
|
||||
return ret;
|
||||
} else {
|
||||
return [this.emitString(d.ESC_TAG, "'", "", true, cache), writer.marshal(this, obj, false, cache)];
|
||||
}
|
||||
};
|
||||
|
||||
writer.emitObjects = function(em, iterable, cache) {
|
||||
var ret = [];
|
||||
if(util.isArray(iterable)) {
|
||||
for(var i = 0; i < iterable.length; i++) {
|
||||
ret.push(writer.marshal(em, iterable[i], false, cache));
|
||||
}
|
||||
} else {
|
||||
iterable.forEach(function(v, i) {
|
||||
ret.push(writer.marshal(em, v, false, cache));
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
writer.emitArray = function(em, iterable, skip, cache) {
|
||||
return writer.emitObjects(em, iterable, cache);
|
||||
};
|
||||
|
||||
writer.isStringableKey = function(em, k) {
|
||||
if(typeof k !== "string") {
|
||||
var h = em.handler(k);
|
||||
return h && h.tag(k).length === 1;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
writer.stringableKeys = function(em, obj) {
|
||||
var arr = em.unpack(obj),
|
||||
stringableKeys = true;
|
||||
|
||||
if(arr) {
|
||||
for(var i = 0; i < arr.length; i+=2) {
|
||||
stringableKeys = writer.isStringableKey(em, arr[i]);
|
||||
if(!stringableKeys) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stringableKeys;
|
||||
} else if(obj.keys) {
|
||||
var iter = obj.keys(),
|
||||
step = null;
|
||||
|
||||
if(iter.next) {
|
||||
step = iter.next();
|
||||
while(!step.done) {
|
||||
stringableKeys = writer.isStringableKey(em, step.value);
|
||||
if(!stringableKeys) {
|
||||
break;
|
||||
}
|
||||
step = iter.next();
|
||||
}
|
||||
return stringableKeys;
|
||||
}
|
||||
}
|
||||
|
||||
if(obj.forEach) {
|
||||
obj.forEach(function(v, k) {
|
||||
stringableKeys = stringableKeys && writer.isStringableKey(em, k);
|
||||
});
|
||||
return stringableKeys;
|
||||
} else {
|
||||
throw new Error("Cannot walk keys of object type " + handlers.constructor(obj).name);
|
||||
}
|
||||
};
|
||||
|
||||
writer.isForeignObject = function(x) {
|
||||
if(x.constructor["transit$isObject"]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var ret = x.constructor.toString(),
|
||||
ret = ret.substr('function '.length),
|
||||
ret = ret.substr(0, ret.indexOf('(')),
|
||||
isObject = ret == "Object";
|
||||
|
||||
if(typeof Object.defineProperty != "undefined") {
|
||||
Object.defineProperty(x.constructor, "transit$isObject", {
|
||||
value: isObject,
|
||||
enumerable: false
|
||||
});
|
||||
} else {
|
||||
x.constructor["transit$isObject"] = isObject;
|
||||
}
|
||||
|
||||
return isObject;
|
||||
};
|
||||
|
||||
writer.emitMap = function(em, obj, skip, cache) {
|
||||
if((obj.constructor === Object) ||
|
||||
(obj.forEach != null) ||
|
||||
(em.handlerForForeign && writer.isForeignObject(obj))) {
|
||||
if(em.verbose) {
|
||||
if(obj.forEach != null) {
|
||||
if(writer.stringableKeys(em, obj)) {
|
||||
var ret = {};
|
||||
obj.forEach(function(v, k) {
|
||||
ret[writer.marshal(em, k, true, false)] = writer.marshal(em, v, false, cache);
|
||||
});
|
||||
return ret;
|
||||
} else {
|
||||
var arr = em.unpack(obj),
|
||||
rep = [],
|
||||
tag = em.emitString(d.ESC_TAG, "cmap", "", true, cache);
|
||||
if(arr) {
|
||||
for(var i = 0; i < arr.length; i+=2) {
|
||||
rep.push(writer.marshal(em, arr[i], true, false));
|
||||
rep.push(writer.marshal(em, arr[i+1], false, cache));
|
||||
}
|
||||
} else {
|
||||
obj.forEach(function(v, k) {
|
||||
rep.push(writer.marshal(em, k, true, false));
|
||||
rep.push(writer.marshal(em, v, false, cache));
|
||||
});
|
||||
}
|
||||
var ret = {};
|
||||
ret[tag] = rep;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
var ret = {},
|
||||
ks = util.objectKeys(obj);
|
||||
for(var i = 0; i < ks.length; i++) {
|
||||
ret[writer.marshal(em, ks[i], true, false)] = writer.marshal(em, obj[ks[i]], false, cache);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if(obj.forEach != null) {
|
||||
if(writer.stringableKeys(em, obj)) {
|
||||
var arr = em.unpack(obj),
|
||||
ret = ["^ "];
|
||||
if(arr) {
|
||||
for(var i = 0; i < arr.length; i+=2) {
|
||||
ret.push(writer.marshal(em, arr[i], true, cache));
|
||||
ret.push(writer.marshal(em, arr[i+1], false, cache));
|
||||
}
|
||||
} else {
|
||||
obj.forEach(function(v, k) {
|
||||
ret.push(writer.marshal(em, k, true, cache));
|
||||
ret.push(writer.marshal(em, v, false, cache));
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
var arr = em.unpack(obj),
|
||||
rep = [],
|
||||
tag = em.emitString(d.ESC_TAG, "cmap", "", true, cache);
|
||||
if(arr) {
|
||||
for(var i = 0; i < arr.length; i+=2) {
|
||||
rep.push(writer.marshal(em, arr[i], true, cache));
|
||||
rep.push(writer.marshal(em, arr[i+1], false, cache));
|
||||
}
|
||||
} else {
|
||||
obj.forEach(function(v, k) {
|
||||
rep.push(writer.marshal(em, k, true, cache));
|
||||
rep.push(writer.marshal(em, v, false, cache));
|
||||
});
|
||||
}
|
||||
return [tag, rep];
|
||||
}
|
||||
} else {
|
||||
var ret = ["^ "],
|
||||
ks = util.objectKeys(obj);
|
||||
for(var i = 0; i < ks.length; i++) {
|
||||
ret.push(writer.marshal(em, ks[i], true, cache));
|
||||
ret.push(writer.marshal(em, obj[ks[i]], false, cache));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else if(em.objectBuilder != null) {
|
||||
return em.objectBuilder(obj, function(k) { return writer.marshal(em, k, true, cache); },
|
||||
function(v) { return writer.marshal(em, v, false, cache); });
|
||||
} else {
|
||||
var name = handlers.constructor(obj).name,
|
||||
err = new Error("Cannot write " + name);
|
||||
err.data = {obj: obj, type: name};
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
writer.emitTaggedMap = function(em, tag, rep, skip, cache) {
|
||||
if(em.verbose) {
|
||||
var ret = {};
|
||||
ret[em.emitString(d.ESC_TAG, tag, "", true, cache)] = writer.marshal(em, rep, false, cache);
|
||||
return ret;
|
||||
} else {
|
||||
return [em.emitString(d.ESC_TAG, tag, "", true, cache), writer.marshal(em, rep, false, cache)];
|
||||
}
|
||||
};
|
||||
|
||||
writer.emitEncoded = function(em, h, tag, rep, obj, asMapKey, cache) {
|
||||
if(tag.length === 1) {
|
||||
if(typeof rep === "string") {
|
||||
return em.emitString(d.ESC, tag, rep, asMapKey, cache);
|
||||
} else if(asMapKey || em.preferStrings) {
|
||||
var vh = em.verbose && h.getVerboseHandler();
|
||||
if(vh) {
|
||||
tag = vh.tag(obj);
|
||||
rep = vh.stringRep(obj, vh);
|
||||
} else {
|
||||
rep = h.stringRep(obj, h);
|
||||
}
|
||||
if(rep !== null) {
|
||||
return em.emitString(d.ESC, tag, rep, asMapKey, cache);
|
||||
} else {
|
||||
var err = new Error("Tag \""+tag+"\" cannot be encoded as string");
|
||||
err.data = {tag: tag, rep: rep, obj: obj};
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
return writer.emitTaggedMap(em, tag, rep, asMapKey, cache);
|
||||
}
|
||||
} else {
|
||||
return writer.emitTaggedMap(em, tag, rep, asMapKey, cache);
|
||||
}
|
||||
}
|
||||
|
||||
writer.marshal = function(em, obj, asMapKey, cache) {
|
||||
var h = em.handler(obj) || (em.handlerForForeign ? em.handlerForForeign(obj, em.handlers) : null),
|
||||
tag = h ? h.tag(obj) : null,
|
||||
rep = h ? h.rep(obj) : null;
|
||||
|
||||
if(h != null && tag != null) {
|
||||
switch(tag) {
|
||||
case "_":
|
||||
return em.emitNil(asMapKey, cache);
|
||||
break;
|
||||
case "s":
|
||||
return em.emitString("", "", writer.escape(rep), asMapKey, cache);
|
||||
break;
|
||||
case "?":
|
||||
return em.emitBoolean(rep, asMapKey, cache);
|
||||
break;
|
||||
case "i":
|
||||
return em.emitInteger(rep, asMapKey, cache);
|
||||
break;
|
||||
case "d":
|
||||
return em.emitDouble(rep, asMapKey, cache);
|
||||
break;
|
||||
case "b":
|
||||
return em.emitBinary(rep, asMapKey, cache);
|
||||
break;
|
||||
case "'":
|
||||
return em.emitQuoted(em, rep, cache);
|
||||
break;
|
||||
case "array":
|
||||
return writer.emitArray(em, rep, asMapKey, cache);
|
||||
break;
|
||||
case "map":
|
||||
return writer.emitMap(em, rep, asMapKey, cache);
|
||||
break;
|
||||
default:
|
||||
return writer.emitEncoded(em, h, tag, rep, obj, asMapKey, cache);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
var name = handlers.constructor(obj).name,
|
||||
err = new Error("Cannot write " + name);
|
||||
err.data = {obj: obj, type: name};
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
writer.maybeQuoted = function(em, obj) {
|
||||
var h = em.handler(obj) || (em.handlerForForeign ? em.handlerForForeign(obj, em.handlers) : null);
|
||||
|
||||
if(h != null) {
|
||||
if(h.tag(obj).length === 1) {
|
||||
return types.quoted(obj);
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
} else {
|
||||
var name = handlers.constructor(obj).name,
|
||||
err = new Error("Cannot write " + name);
|
||||
err.data = {obj: obj, type: name};
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
writer.marshalTop = function(em, obj, asMapKey, cache) {
|
||||
return JSON.stringify(writer.marshal(em, writer.maybeQuoted(em, obj), asMapKey, cache));
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
writer.Writer = function(marshaller, options) {
|
||||
this._marshaller = marshaller;
|
||||
this.options = options || {};
|
||||
if(this.options["cache"] === false) {
|
||||
this.cache = null;
|
||||
} else {
|
||||
this.cache = this.options["cache"] ? this.options["cache"] : new caching.WriteCache();
|
||||
}
|
||||
};
|
||||
|
||||
writer.Writer.prototype.marshaller = function() {
|
||||
return this._marshaller;
|
||||
};
|
||||
writer.Writer.prototype["marshaller"] = writer.Writer.prototype.marshaller;
|
||||
|
||||
writer.Writer.prototype.write = function(obj, opts) {
|
||||
var ret = null,
|
||||
ropts = opts || {},
|
||||
asMapKey = ropts["asMapKey"] || false,
|
||||
cache = this._marshaller.verbose ? false : this.cache;
|
||||
|
||||
if(ropts["marshalTop"] === false) {
|
||||
ret = writer.marshal(this._marshaller, obj, asMapKey, cache)
|
||||
} else {
|
||||
ret = writer.marshalTop(this._marshaller, obj, asMapKey, cache)
|
||||
}
|
||||
if(this.cache != null) {
|
||||
this.cache.clear();
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
writer.Writer.prototype["write"] = writer.Writer.prototype.write;
|
||||
|
||||
writer.Writer.prototype.register = function(type, handler) {
|
||||
this._marshaller.registerHandler(type, handler);
|
||||
};
|
||||
writer.Writer.prototype["register"] = writer.Writer.prototype.register;
|
||||
|
||||
});
|
||||
Executable
+1089
File diff suppressed because it is too large
Load Diff
Executable
+144
@@ -0,0 +1,144 @@
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide("com.cognitect.transit.util");
|
||||
goog.require("goog.object");
|
||||
|
||||
goog.scope(function() {
|
||||
|
||||
var util = com.cognitect.transit.util,
|
||||
gobject = goog.object;
|
||||
|
||||
if(typeof Object.keys != "undefined") {
|
||||
util.objectKeys = function(obj) {
|
||||
return Object.keys(obj);
|
||||
};
|
||||
} else {
|
||||
util.objectKeys = function(obj) {
|
||||
return gobject.getKeys(obj);
|
||||
};
|
||||
}
|
||||
|
||||
if(typeof Array.isArray != "undefined") {
|
||||
util.isArray = function(obj) {
|
||||
return Array.isArray(obj);
|
||||
};
|
||||
} else {
|
||||
util.isArray = function(obj) {
|
||||
return goog.typeOf(obj) === "array";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
util.chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
util.randInt = function(ub) {
|
||||
return Math.round(Math.random()*ub);
|
||||
};
|
||||
|
||||
util.randHex = function() {
|
||||
return util.randInt(15).toString(16);
|
||||
};
|
||||
|
||||
util.randomUUID = function() {
|
||||
var rhex = (0x8 | (0x3 & util.randInt(14))).toString(16),
|
||||
ret = util.randHex() + util.randHex() + util.randHex() + util.randHex() +
|
||||
util.randHex() + util.randHex() + util.randHex() + util.randHex() + "-" +
|
||||
util.randHex() + util.randHex() + util.randHex() + util.randHex() + "-" +
|
||||
"4" + util.randHex() + util.randHex() + util.randHex() + "-" +
|
||||
rhex + util.randHex() + util.randHex() + util.randHex() + "-" +
|
||||
util.randHex() + util.randHex() + util.randHex() + util.randHex() +
|
||||
util.randHex() + util.randHex() + util.randHex() + util.randHex() +
|
||||
util.randHex() + util.randHex() + util.randHex() + util.randHex();
|
||||
return ret;
|
||||
};
|
||||
|
||||
// https://github.com/davidchambers/Base64.js
|
||||
|
||||
util.btoa = function(input) {
|
||||
if(typeof btoa != "undefined") {
|
||||
return btoa(input);
|
||||
} else {
|
||||
var str = String(input);
|
||||
for (
|
||||
var block, charCode, idx = 0, map = util.chars, output = '';
|
||||
str.charAt(idx | 0) || (map = '=', idx % 1);
|
||||
output += map.charAt(63 & block >> 8 - idx % 1 * 8)
|
||||
) {
|
||||
charCode = str.charCodeAt(idx += 3/4);
|
||||
if (charCode > 0xFF) {
|
||||
throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
|
||||
}
|
||||
block = block << 8 | charCode;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @suppress {uselessCode}
|
||||
*/
|
||||
util.atob = function(input) {
|
||||
if(typeof atob != "undefined") {
|
||||
return atob(input);
|
||||
} else {
|
||||
var str = String(input).replace(/=+$/, '');
|
||||
if (str.length % 4 == 1) {
|
||||
throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
|
||||
}
|
||||
for (
|
||||
var bc = 0, bs, buffer, idx = 0, output = '';
|
||||
buffer = str.charAt(idx++);
|
||||
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
|
||||
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
|
||||
) {
|
||||
buffer = util.chars.indexOf(buffer);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
util.Uint8ToBase64 = function(u8Arr) {
|
||||
var CHUNK_SIZE = 0x8000,
|
||||
index = 0,
|
||||
length = u8Arr.length,
|
||||
result = '',
|
||||
slice = null;
|
||||
|
||||
while (index < length) {
|
||||
slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
|
||||
result += String.fromCharCode.apply(null, slice);
|
||||
index += CHUNK_SIZE;
|
||||
}
|
||||
|
||||
return util.btoa(result);
|
||||
};
|
||||
|
||||
util.Base64ToUint8 = function(base64) {
|
||||
var binary_string = util.atob(base64),
|
||||
len = binary_string.length,
|
||||
bytes = new Uint8Array(len);
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var ascii = binary_string.charCodeAt(i);
|
||||
bytes[i] = ascii;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
});
|
||||
Executable
+1793
File diff suppressed because it is too large
Load Diff
Executable
+471
@@ -0,0 +1,471 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Utilities to check the preconditions, postconditions and
|
||||
* invariants runtime.
|
||||
*
|
||||
* Methods in this package are given special treatment by the compiler
|
||||
* for type-inference. For example, <code>goog.asserts.assert(foo)</code>
|
||||
* will make the compiler treat <code>foo</code> as non-nullable. Similarly,
|
||||
* <code>goog.asserts.assertNumber(foo)</code> informs the compiler about the
|
||||
* type of <code>foo</code>. Where applicable, such assertions are preferable to
|
||||
* casts by jsdoc with <code>@type</code>.
|
||||
*
|
||||
* The compiler has an option to disable asserts. So code like:
|
||||
* <code>
|
||||
* var x = goog.asserts.assert(foo());
|
||||
* goog.asserts.assert(bar());
|
||||
* </code>
|
||||
* will be transformed into:
|
||||
* <code>
|
||||
* var x = foo();
|
||||
* </code>
|
||||
* The compiler will leave in foo() (because its return value is used),
|
||||
* but it will remove bar() because it assumes it does not have side-effects.
|
||||
*
|
||||
* Additionally, note the compiler will consider the type to be "tightened" for
|
||||
* all statements <em>after</em> the assertion. For example:
|
||||
* <code>
|
||||
* const /** ?Object &#ast;/ value = foo();
|
||||
* goog.asserts.assert(value);
|
||||
* // "value" is of type {!Object} at this point.
|
||||
* </code>
|
||||
*/
|
||||
|
||||
goog.provide('goog.asserts');
|
||||
goog.provide('goog.asserts.AssertionError');
|
||||
|
||||
goog.require('goog.debug.Error');
|
||||
goog.require('goog.dom.NodeType');
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to strip out asserts or to leave them in.
|
||||
*/
|
||||
goog.asserts.ENABLE_ASSERTS =
|
||||
goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Error object for failed assertions.
|
||||
* @param {string} messagePattern The pattern that was used to form message.
|
||||
* @param {!Array<*>} messageArgs The items to substitute into the pattern.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
* @final
|
||||
*/
|
||||
goog.asserts.AssertionError = function(messagePattern, messageArgs) {
|
||||
'use strict';
|
||||
goog.debug.Error.call(this, goog.asserts.subs_(messagePattern, messageArgs));
|
||||
|
||||
/**
|
||||
* The message pattern used to format the error message. Error handlers can
|
||||
* use this to uniquely identify the assertion.
|
||||
* @type {string}
|
||||
*/
|
||||
this.messagePattern = messagePattern;
|
||||
};
|
||||
goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
|
||||
|
||||
|
||||
/** @override @type {string} */
|
||||
goog.asserts.AssertionError.prototype.name = 'AssertionError';
|
||||
|
||||
|
||||
/**
|
||||
* The default error handler.
|
||||
* @param {!goog.asserts.AssertionError} e The exception to be handled.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.asserts.DEFAULT_ERROR_HANDLER = function(e) {
|
||||
'use strict';
|
||||
throw e;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The handler responsible for throwing or logging assertion errors.
|
||||
* @private {function(!goog.asserts.AssertionError)}
|
||||
*/
|
||||
goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER;
|
||||
|
||||
|
||||
/**
|
||||
* Does simple python-style string substitution.
|
||||
* subs("foo%s hot%s", "bar", "dog") becomes "foobar hotdog".
|
||||
* @param {string} pattern The string containing the pattern.
|
||||
* @param {!Array<*>} subs The items to substitute into the pattern.
|
||||
* @return {string} A copy of `str` in which each occurrence of
|
||||
* {@code %s} has been replaced an argument from `var_args`.
|
||||
* @private
|
||||
*/
|
||||
goog.asserts.subs_ = function(pattern, subs) {
|
||||
'use strict';
|
||||
var splitParts = pattern.split('%s');
|
||||
var returnString = '';
|
||||
|
||||
// Replace up to the last split part. We are inserting in the
|
||||
// positions between split parts.
|
||||
var subLast = splitParts.length - 1;
|
||||
for (var i = 0; i < subLast; i++) {
|
||||
// keep unsupplied as '%s'
|
||||
var sub = (i < subs.length) ? subs[i] : '%s';
|
||||
returnString += splitParts[i] + sub;
|
||||
}
|
||||
return returnString + splitParts[subLast];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Throws an exception with the given message and "Assertion failed" prefixed
|
||||
* onto it.
|
||||
* @param {string} defaultMessage The message to use if givenMessage is empty.
|
||||
* @param {Array<*>} defaultArgs The substitution arguments for defaultMessage.
|
||||
* @param {string|undefined} givenMessage Message supplied by the caller.
|
||||
* @param {Array<*>} givenArgs The substitution arguments for givenMessage.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a number.
|
||||
* @private
|
||||
*/
|
||||
goog.asserts.doAssertFailure_ = function(
|
||||
defaultMessage, defaultArgs, givenMessage, givenArgs) {
|
||||
'use strict';
|
||||
var message = 'Assertion failed';
|
||||
if (givenMessage) {
|
||||
message += ': ' + givenMessage;
|
||||
var args = givenArgs;
|
||||
} else if (defaultMessage) {
|
||||
message += ': ' + defaultMessage;
|
||||
args = defaultArgs;
|
||||
}
|
||||
// The '' + works around an Opera 10 bug in the unit tests. Without it,
|
||||
// a stack trace is added to var message above. With this, a stack trace is
|
||||
// not added until this line (it causes the extra garbage to be added after
|
||||
// the assertion message instead of in the middle of it).
|
||||
var e = new goog.asserts.AssertionError('' + message, args || []);
|
||||
goog.asserts.errorHandler_(e);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a custom error handler that can be used to customize the behavior of
|
||||
* assertion failures, for example by turning all assertion failures into log
|
||||
* messages.
|
||||
* @param {function(!goog.asserts.AssertionError)} errorHandler
|
||||
* @return {void}
|
||||
*/
|
||||
goog.asserts.setErrorHandler = function(errorHandler) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
goog.asserts.errorHandler_ = errorHandler;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is
|
||||
* true.
|
||||
* @template T
|
||||
* @param {T} condition The condition to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {T} The value of the condition.
|
||||
* @throws {goog.asserts.AssertionError} When the condition evaluates to false.
|
||||
* @closurePrimitive {asserts.truthy}
|
||||
*/
|
||||
goog.asserts.assert = function(condition, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && !condition) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'', null, opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return condition;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if `value` is `null` or `undefined` if goog.asserts.ENABLE_ASSERTS is
|
||||
* true.
|
||||
*
|
||||
* @param {T} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {R} `value` with its type narrowed to exclude `null` and `undefined`.
|
||||
*
|
||||
* @template T
|
||||
* @template R :=
|
||||
* mapunion(T, (V) =>
|
||||
* cond(eq(V, 'null'),
|
||||
* none(),
|
||||
* cond(eq(V, 'undefined'),
|
||||
* none(),
|
||||
* V)))
|
||||
* =:
|
||||
*
|
||||
* @throws {!goog.asserts.AssertionError} When `value` is `null` or `undefined`.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertExists = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && value == null) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected to exist: %s.', [value], opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case
|
||||
* when we want to add a check in the unreachable area like switch-case
|
||||
* statement:
|
||||
*
|
||||
* <pre>
|
||||
* switch(type) {
|
||||
* case FOO: doSomething(); break;
|
||||
* case BAR: doSomethingElse(); break;
|
||||
* default: goog.asserts.fail('Unrecognized type: ' + type);
|
||||
* // We have only 2 types - "default:" section is unreachable code.
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {void}
|
||||
* @throws {goog.asserts.AssertionError} Failure.
|
||||
* @closurePrimitive {asserts.fail}
|
||||
*/
|
||||
goog.asserts.fail = function(opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
goog.asserts.errorHandler_(new goog.asserts.AssertionError(
|
||||
'Failure' + (opt_message ? ': ' + opt_message : ''),
|
||||
Array.prototype.slice.call(arguments, 1)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {number} The value, guaranteed to be a number when asserts enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a number.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertNumber = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && typeof value !== 'number') {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected number but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {number} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {string} The value, guaranteed to be a string when asserts enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a string.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertString = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && typeof value !== 'string') {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected string but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {string} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Function} The value, guaranteed to be a function when asserts
|
||||
* enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a function.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertFunction = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && typeof value !== 'function') {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected function but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Function} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Object} The value, guaranteed to be a non-null object.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an object.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertObject = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected object but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Object} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Array<?>} The value, guaranteed to be a non-null array.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an array.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertArray = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && !Array.isArray(value)) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected array but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Array<?>} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {boolean} The value, guaranteed to be a boolean when asserts are
|
||||
* enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a boolean.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertBoolean = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && typeof value !== 'boolean') {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected boolean but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {boolean} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a DOM Element if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Element} The value, likely to be a DOM Element when asserts are
|
||||
* enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an Element.
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
* @deprecated Use goog.asserts.dom.assertIsElement instead.
|
||||
*/
|
||||
goog.asserts.assertElement = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS &&
|
||||
(!goog.isObject(value) ||
|
||||
/** @type {!Node} */ (value).nodeType != goog.dom.NodeType.ELEMENT)) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected Element but got %s: %s.', [goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Element} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is an instance of the user-defined type if
|
||||
* goog.asserts.ENABLE_ASSERTS is true.
|
||||
*
|
||||
* The compiler may tighten the type returned by this function.
|
||||
*
|
||||
* Do not use this to ensure a value is an HTMLElement or a subclass! Cross-
|
||||
* document DOM inherits from separate - though identical - browser classes, and
|
||||
* such a check will unexpectedly fail. Please use the methods in
|
||||
* goog.asserts.dom for these purposes.
|
||||
*
|
||||
* @param {?} value The value to check.
|
||||
* @param {function(new: T, ...)} type A user-defined constructor.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an instance of
|
||||
* type.
|
||||
* @return {T}
|
||||
* @template T
|
||||
* @closurePrimitive {asserts.matchesReturn}
|
||||
*/
|
||||
goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected instanceof %s but got %s.',
|
||||
[goog.asserts.getType_(type), goog.asserts.getType_(value)],
|
||||
opt_message, Array.prototype.slice.call(arguments, 3));
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the value is a finite number, if goog.asserts.ENABLE_ASSERTS
|
||||
* is true.
|
||||
*
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a number, or is
|
||||
* a non-finite number such as NaN, Infinity or -Infinity.
|
||||
* @return {number} The value initially passed in.
|
||||
*/
|
||||
goog.asserts.assertFinite = function(value, opt_message, var_args) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS &&
|
||||
(typeof value != 'number' || !isFinite(value))) {
|
||||
goog.asserts.doAssertFailure_(
|
||||
'Expected %s to be a finite number but it is not.', [value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {number} */ (value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the type of a value. If a constructor is passed, and a suitable
|
||||
* string cannot be found, 'unknown type name' will be returned.
|
||||
* @param {*} value A constructor, object, or primitive.
|
||||
* @return {string} The best display name for the value, or 'unknown type name'.
|
||||
* @private
|
||||
*/
|
||||
goog.asserts.getType_ = function(value) {
|
||||
'use strict';
|
||||
if (value instanceof Function) {
|
||||
return value.displayName || value.name || 'unknown type name';
|
||||
} else if (value instanceof Object) {
|
||||
return /** @type {string} */ (value.constructor.displayName) ||
|
||||
value.constructor.name || Object.prototype.toString.call(value);
|
||||
} else {
|
||||
return value === null ? 'null' : typeof value;
|
||||
}
|
||||
};
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Simple freelist.
|
||||
*
|
||||
* An anterative to goog.structs.SimplePool, it imposes the requirement that the
|
||||
* objects in the list contain a "next" property that can be used to maintain
|
||||
* the pool.
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.FreeList');
|
||||
|
||||
|
||||
/**
|
||||
* @template ITEM
|
||||
*/
|
||||
goog.async.FreeList = class {
|
||||
/**
|
||||
* @param {function():ITEM} create
|
||||
* @param {function(ITEM):void} reset
|
||||
* @param {number} limit
|
||||
*/
|
||||
constructor(create, reset, limit) {
|
||||
/** @private @const {number} */
|
||||
this.limit_ = limit;
|
||||
/** @private @const {function()} */
|
||||
this.create_ = create;
|
||||
/** @private @const {function(ITEM):void} */
|
||||
this.reset_ = reset;
|
||||
|
||||
/** @private {number} */
|
||||
this.occupants_ = 0;
|
||||
/** @private {ITEM} */
|
||||
this.head_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {ITEM}
|
||||
*/
|
||||
get() {
|
||||
let item;
|
||||
if (this.occupants_ > 0) {
|
||||
this.occupants_--;
|
||||
item = this.head_;
|
||||
this.head_ = item.next;
|
||||
item.next = null;
|
||||
} else {
|
||||
item = this.create_();
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ITEM} item An item available for possible future reuse.
|
||||
*/
|
||||
put(item) {
|
||||
this.reset_(item);
|
||||
if (this.occupants_ < this.limit_) {
|
||||
this.occupants_++;
|
||||
item.next = this.head_;
|
||||
this.head_ = item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visible for testing.
|
||||
* @package
|
||||
* @return {number}
|
||||
*/
|
||||
occupants() {
|
||||
return this.occupants_;
|
||||
}
|
||||
};
|
||||
Executable
+237
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Provides a function to schedule running a function as soon
|
||||
* as possible after the current JS execution stops and yields to the event
|
||||
* loop.
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.nextTick');
|
||||
|
||||
goog.require('goog.debug.entryPointRegistry');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.labs.userAgent.browser');
|
||||
goog.require('goog.labs.userAgent.engine');
|
||||
|
||||
|
||||
/**
|
||||
* Fires the provided callbacks as soon as possible after the current JS
|
||||
* execution context. setTimeout(…, 0) takes at least 4ms when called from
|
||||
* within another setTimeout(…, 0) for legacy reasons.
|
||||
*
|
||||
* This will not schedule the callback as a microtask (i.e. a task that can
|
||||
* preempt user input or networking callbacks). It is meant to emulate what
|
||||
* setTimeout(_, 0) would do if it were not throttled. If you desire microtask
|
||||
* behavior, use {@see goog.Promise} instead.
|
||||
*
|
||||
* @param {function(this:SCOPE)} callback Callback function to fire as soon as
|
||||
* possible.
|
||||
* @param {SCOPE=} opt_context Object in whose scope to call the listener.
|
||||
* @param {boolean=} opt_useSetImmediate Avoid the IE workaround that
|
||||
* ensures correctness at the cost of speed. See comments for details.
|
||||
* @template SCOPE
|
||||
*/
|
||||
goog.async.nextTick = function(callback, opt_context, opt_useSetImmediate) {
|
||||
'use strict';
|
||||
var cb = callback;
|
||||
if (opt_context) {
|
||||
cb = goog.bind(callback, opt_context);
|
||||
}
|
||||
cb = goog.async.nextTick.wrapCallback_(cb);
|
||||
// Note we do allow callers to also request setImmediate if they are willing
|
||||
// to accept the possible tradeoffs of incorrectness in exchange for speed.
|
||||
// The IE fallback of readystate change is much slower. See useSetImmediate_
|
||||
// for details.
|
||||
if (typeof goog.global.setImmediate === 'function' &&
|
||||
(opt_useSetImmediate || goog.async.nextTick.useSetImmediate_())) {
|
||||
goog.global.setImmediate(cb);
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for and cache the custom fallback version of setImmediate.
|
||||
if (!goog.async.nextTick.setImmediate_) {
|
||||
goog.async.nextTick.setImmediate_ =
|
||||
goog.async.nextTick.getSetImmediateEmulator_();
|
||||
}
|
||||
goog.async.nextTick.setImmediate_(cb);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether should use setImmediate implementation currently on window.
|
||||
*
|
||||
* window.setImmediate was introduced and currently only supported by IE10+,
|
||||
* but due to a bug in the implementation it is not guaranteed that
|
||||
* setImmediate is faster than setTimeout nor that setImmediate N is before
|
||||
* setImmediate N+1. That is why we do not use the native version if
|
||||
* available. We do, however, call setImmediate if it is a non-native function
|
||||
* because that indicates that it has been replaced by goog.testing.MockClock
|
||||
* which we do want to support.
|
||||
* See
|
||||
* http://connect.microsoft.com/IE/feedback/details/801823/setimmediate-and-messagechannel-are-broken-in-ie10
|
||||
*
|
||||
* @return {boolean} Whether to use the implementation of setImmediate defined
|
||||
* on Window.
|
||||
* @private
|
||||
* @suppress {missingProperties} For "Window.prototype.setImmediate"
|
||||
*/
|
||||
goog.async.nextTick.useSetImmediate_ = function() {
|
||||
'use strict';
|
||||
// Not a browser environment.
|
||||
if (!goog.global.Window || !goog.global.Window.prototype) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// MS Edge has window.setImmediate natively, but it's not on Window.prototype.
|
||||
// Also, there's no clean way to detect if the goog.global.setImmediate has
|
||||
// been replaced by mockClock as its replacement also shows up as "[native
|
||||
// code]" when using toString. Therefore, just always use
|
||||
// goog.global.setImmediate for Edge. It's unclear if it suffers the same
|
||||
// issues as IE10/11, but based on
|
||||
// https://dev.modern.ie/testdrive/demos/setimmediatesorting/
|
||||
// it seems they've been working to ensure it's WAI.
|
||||
if (goog.labs.userAgent.browser.isEdge() ||
|
||||
goog.global.Window.prototype.setImmediate != goog.global.setImmediate) {
|
||||
// Something redefined setImmediate in which case we decide to use it (This
|
||||
// is so that we use the mockClock setImmediate).
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cache for the setImmediate implementation.
|
||||
* @type {function(function())}
|
||||
* @private
|
||||
*/
|
||||
goog.async.nextTick.setImmediate_;
|
||||
|
||||
|
||||
/**
|
||||
* Determines the best possible implementation to run a function as soon as
|
||||
* the JS event loop is idle.
|
||||
* @return {function(function())} The "setImmediate" implementation.
|
||||
* @private
|
||||
*/
|
||||
goog.async.nextTick.getSetImmediateEmulator_ = function() {
|
||||
'use strict';
|
||||
// Create a private message channel and use it to postMessage empty messages
|
||||
// to ourselves.
|
||||
/** @type {!Function|undefined} */
|
||||
var Channel = goog.global['MessageChannel'];
|
||||
// If MessageChannel is not available and we are in a browser, implement
|
||||
// an iframe based polyfill in browsers that have postMessage and
|
||||
// document.addEventListener. The latter excludes IE8 because it has a
|
||||
// synchronous postMessage implementation.
|
||||
if (typeof Channel === 'undefined' && typeof window !== 'undefined' &&
|
||||
window.postMessage && window.addEventListener &&
|
||||
// Presto (The old pre-blink Opera engine) has problems with iframes
|
||||
// and contentWindow.
|
||||
!goog.labs.userAgent.engine.isPresto()) {
|
||||
/** @constructor */
|
||||
Channel = function() {
|
||||
'use strict';
|
||||
// Make an empty, invisible iframe.
|
||||
var iframe = goog.dom.createElement(goog.dom.TagName.IFRAME);
|
||||
iframe.style.display = 'none';
|
||||
document.documentElement.appendChild(iframe);
|
||||
var win = iframe.contentWindow;
|
||||
var doc = win.document;
|
||||
doc.open();
|
||||
doc.close();
|
||||
// Do not post anything sensitive over this channel, as the workaround for
|
||||
// pages with file: origin could allow that information to be modified or
|
||||
// intercepted.
|
||||
var message = 'callImmediate' + Math.random();
|
||||
// The same origin policy rejects attempts to postMessage from file: urls
|
||||
// unless the origin is '*'.
|
||||
var origin = win.location.protocol == 'file:' ?
|
||||
'*' :
|
||||
win.location.protocol + '//' + win.location.host;
|
||||
var onmessage = goog.bind(function(e) {
|
||||
'use strict';
|
||||
// Validate origin and message to make sure that this message was
|
||||
// intended for us. If the origin is set to '*' (see above) only the
|
||||
// message needs to match since, for example, '*' != 'file://'. Allowing
|
||||
// the wildcard is ok, as we are not concerned with security here.
|
||||
if ((origin != '*' && e.origin != origin) || e.data != message) {
|
||||
return;
|
||||
}
|
||||
this['port1'].onmessage();
|
||||
}, this);
|
||||
win.addEventListener('message', onmessage, false);
|
||||
this['port1'] = {};
|
||||
this['port2'] = {
|
||||
postMessage: function() {
|
||||
'use strict';
|
||||
win.postMessage(message, origin);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
if (typeof Channel !== 'undefined' && !goog.labs.userAgent.browser.isIE()) {
|
||||
// Exclude all of IE due to
|
||||
// http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/
|
||||
// which allows starving postMessage with a busy setTimeout loop.
|
||||
// This currently affects IE10 and IE11 which would otherwise be able
|
||||
// to use the postMessage based fallbacks.
|
||||
var channel = new Channel();
|
||||
// Use a fifo linked list to call callbacks in the right order.
|
||||
var head = {};
|
||||
var tail = head;
|
||||
channel['port1'].onmessage = function() {
|
||||
'use strict';
|
||||
if (head.next !== undefined) {
|
||||
head = head.next;
|
||||
var cb = head.cb;
|
||||
head.cb = null;
|
||||
cb();
|
||||
}
|
||||
};
|
||||
return function(cb) {
|
||||
'use strict';
|
||||
tail.next = {cb: cb};
|
||||
tail = tail.next;
|
||||
channel['port2'].postMessage(0);
|
||||
};
|
||||
}
|
||||
// Fall back to setTimeout with 0. In browsers this creates a delay of 5ms
|
||||
// or more.
|
||||
// NOTE(user): This fallback is used for IE.
|
||||
return function(cb) {
|
||||
'use strict';
|
||||
goog.global.setTimeout(/** @type {function()} */ (cb), 0);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function that is overrided to protect callbacks with entry point
|
||||
* monitor if the application monitors entry points.
|
||||
* @param {function()} callback Callback function to fire as soon as possible.
|
||||
* @return {function()} The wrapped callback.
|
||||
* @private
|
||||
*/
|
||||
goog.async.nextTick.wrapCallback_ = goog.functions.identity;
|
||||
|
||||
|
||||
// Register the callback function as an entry point, so that it can be
|
||||
// monitored for exception handling, etc. This has to be done in this file
|
||||
// since it requires special code to handle all browsers.
|
||||
goog.debug.entryPointRegistry.register(
|
||||
/**
|
||||
* @param {function(!Function): !Function} transformer The transforming
|
||||
* function.
|
||||
*/
|
||||
function(transformer) {
|
||||
'use strict';
|
||||
goog.async.nextTick.wrapCallback_ = transformer;
|
||||
});
|
||||
Executable
+149
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.run');
|
||||
|
||||
goog.require('goog.async.WorkQueue');
|
||||
goog.require('goog.async.nextTick');
|
||||
goog.require('goog.async.throwException');
|
||||
|
||||
/**
|
||||
* @define {boolean} If true, use the global Promise to implement goog.async.run
|
||||
* assuming either the native, or polyfill version will be used. Does still
|
||||
* permit tests to use forceNextTick.
|
||||
*/
|
||||
goog.ASSUME_NATIVE_PROMISE = goog.define('goog.ASSUME_NATIVE_PROMISE', false);
|
||||
|
||||
/**
|
||||
* Fires the provided callback just before the current callstack unwinds, or as
|
||||
* soon as possible after the current JS execution context.
|
||||
* @param {function(this:THIS)} callback
|
||||
* @param {THIS=} opt_context Object to use as the "this value" when calling
|
||||
* the provided function.
|
||||
* @template THIS
|
||||
*/
|
||||
goog.async.run = function(callback, opt_context) {
|
||||
'use strict';
|
||||
if (!goog.async.run.schedule_) {
|
||||
goog.async.run.initializeRunner_();
|
||||
}
|
||||
if (!goog.async.run.workQueueScheduled_) {
|
||||
// Nothing is currently scheduled, schedule it now.
|
||||
goog.async.run.schedule_();
|
||||
goog.async.run.workQueueScheduled_ = true;
|
||||
}
|
||||
|
||||
goog.async.run.workQueue_.add(callback, opt_context);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the function to use to process the work queue.
|
||||
* @private
|
||||
*/
|
||||
goog.async.run.initializeRunner_ = function() {
|
||||
'use strict';
|
||||
if (goog.ASSUME_NATIVE_PROMISE ||
|
||||
(goog.global.Promise && goog.global.Promise.resolve)) {
|
||||
// Use goog.global.Promise instead of just Promise because the relevant
|
||||
// externs may be missing, and don't alias it because this could confuse the
|
||||
// compiler into thinking the polyfill is required when it should be treated
|
||||
// as optional.
|
||||
var promise = goog.global.Promise.resolve(undefined);
|
||||
goog.async.run.schedule_ = function() {
|
||||
'use strict';
|
||||
promise.then(goog.async.run.processWorkQueue);
|
||||
};
|
||||
} else {
|
||||
goog.async.run.schedule_ = function() {
|
||||
'use strict';
|
||||
goog.async.nextTick(goog.async.run.processWorkQueue);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Forces goog.async.run to use nextTick instead of Promise.
|
||||
*
|
||||
* This should only be done in unit tests. It's useful because MockClock
|
||||
* replaces nextTick, but not the browser Promise implementation, so it allows
|
||||
* Promise-based code to be tested with MockClock.
|
||||
*
|
||||
* However, we also want to run promises if the MockClock is no longer in
|
||||
* control so we schedule a backup "setTimeout" to the unmocked timeout if
|
||||
* provided.
|
||||
*
|
||||
* @param {function(function())=} opt_realSetTimeout
|
||||
*/
|
||||
goog.async.run.forceNextTick = function(opt_realSetTimeout) {
|
||||
'use strict';
|
||||
goog.async.run.schedule_ = function() {
|
||||
'use strict';
|
||||
goog.async.nextTick(goog.async.run.processWorkQueue);
|
||||
if (opt_realSetTimeout) {
|
||||
opt_realSetTimeout(goog.async.run.processWorkQueue);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The function used to schedule work asynchronousely.
|
||||
* @private {function()}
|
||||
*/
|
||||
goog.async.run.schedule_;
|
||||
|
||||
|
||||
/** @private {boolean} */
|
||||
goog.async.run.workQueueScheduled_ = false;
|
||||
|
||||
|
||||
/** @private {!goog.async.WorkQueue} */
|
||||
goog.async.run.workQueue_ = new goog.async.WorkQueue();
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Reset the work queue. Only available for tests in debug mode.
|
||||
*/
|
||||
goog.async.run.resetQueue = function() {
|
||||
'use strict';
|
||||
goog.async.run.workQueueScheduled_ = false;
|
||||
goog.async.run.workQueue_ = new goog.async.WorkQueue();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Resets the scheduler. Only available for tests in debug mode.
|
||||
*/
|
||||
goog.async.run.resetSchedulerForTest = function() {
|
||||
goog.async.run.initializeRunner_();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run any pending goog.async.run work items. This function is not intended
|
||||
* for general use, but for use by entry point handlers to run items ahead of
|
||||
* goog.async.nextTick.
|
||||
*/
|
||||
goog.async.run.processWorkQueue = function() {
|
||||
'use strict';
|
||||
// NOTE: additional work queue items may be added while processing.
|
||||
var item = null;
|
||||
while (item = goog.async.run.workQueue_.remove()) {
|
||||
try {
|
||||
item.fn.call(item.scope);
|
||||
} catch (e) {
|
||||
goog.async.throwException(e);
|
||||
}
|
||||
goog.async.run.workQueue_.returnUnused(item);
|
||||
}
|
||||
|
||||
// There are no more work items, allow processing to be scheduled again.
|
||||
goog.async.run.workQueueScheduled_ = false;
|
||||
};
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Provides a function to throw an error without interrupting
|
||||
* the current execution context.
|
||||
*/
|
||||
|
||||
goog.module('goog.async.throwException');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/**
|
||||
* Throw an item without interrupting the current execution context. For
|
||||
* example, if processing a group of items in a loop, sometimes it is useful
|
||||
* to report an error while still allowing the rest of the batch to be
|
||||
* processed.
|
||||
* @param {*} exception
|
||||
*/
|
||||
function throwException(exception) {
|
||||
// Each throw needs to be in its own context.
|
||||
goog.global.setTimeout(() => {
|
||||
throw exception;
|
||||
}, 0);
|
||||
}
|
||||
exports = throwException;
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.module('goog.async.WorkQueue');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const FreeList = goog.require('goog.async.FreeList');
|
||||
const {assert} = goog.require('goog.asserts');
|
||||
|
||||
// TODO(johnlenz): generalize the WorkQueue if this is used by more
|
||||
// than goog.async.run.
|
||||
|
||||
|
||||
/**
|
||||
* A low GC workqueue. The key elements of this design:
|
||||
* - avoids the need for goog.bind or equivalent by carrying scope
|
||||
* - avoids the need for array reallocation by using a linked list
|
||||
* - minimizes work entry objects allocation by recycling objects
|
||||
* @final
|
||||
* @struct
|
||||
*/
|
||||
class WorkQueue {
|
||||
constructor() {
|
||||
this.workHead_ = null;
|
||||
this.workTail_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function()} fn
|
||||
* @param {Object|null|undefined} scope
|
||||
*/
|
||||
add(fn, scope) {
|
||||
const item = this.getUnusedItem_();
|
||||
item.set(fn, scope);
|
||||
|
||||
if (this.workTail_) {
|
||||
this.workTail_.next = item;
|
||||
this.workTail_ = item;
|
||||
} else {
|
||||
assert(!this.workHead_);
|
||||
this.workHead_ = item;
|
||||
this.workTail_ = item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {?WorkItem}
|
||||
*/
|
||||
remove() {
|
||||
let item = null;
|
||||
|
||||
if (this.workHead_) {
|
||||
item = this.workHead_;
|
||||
this.workHead_ = this.workHead_.next;
|
||||
if (!this.workHead_) {
|
||||
this.workTail_ = null;
|
||||
}
|
||||
item.next = null;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!WorkItem} item
|
||||
*/
|
||||
returnUnused(item) {
|
||||
WorkQueue.freelist_.put(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!WorkItem}
|
||||
* @private
|
||||
*/
|
||||
getUnusedItem_() {
|
||||
return WorkQueue.freelist_.get();
|
||||
}
|
||||
}
|
||||
|
||||
/** @define {number} The maximum number of entries to keep for recycling. */
|
||||
WorkQueue.DEFAULT_MAX_UNUSED =
|
||||
goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);
|
||||
|
||||
/** @const @private {!FreeList<!WorkItem>} */
|
||||
WorkQueue.freelist_ = new FreeList(
|
||||
() => new WorkItem(), item => item.reset(), WorkQueue.DEFAULT_MAX_UNUSED);
|
||||
|
||||
/**
|
||||
* @final
|
||||
* @struct
|
||||
*/
|
||||
class WorkItem {
|
||||
constructor() {
|
||||
/** @type {?function()} */
|
||||
this.fn = null;
|
||||
/** @type {?Object|null|undefined} */
|
||||
this.scope = null;
|
||||
/** @type {?WorkItem} */
|
||||
this.next = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function()} fn
|
||||
* @param {Object|null|undefined} scope
|
||||
*/
|
||||
set(fn, scope) {
|
||||
'use strict';
|
||||
this.fn = fn;
|
||||
this.scope = scope;
|
||||
this.next = null;
|
||||
}
|
||||
|
||||
/** Reset the work item so they don't prevent GC before reuse */
|
||||
reset() {
|
||||
this.fn = null;
|
||||
this.scope = null;
|
||||
this.next = null;
|
||||
}
|
||||
}
|
||||
|
||||
exports = WorkQueue;
|
||||
Executable
+3889
File diff suppressed because it is too large
Load Diff
Executable
+222
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Utilities for working with ES6 iterables.
|
||||
*
|
||||
* The goal is that this should be a replacement for goog.iter which uses
|
||||
* a now non-standard approach to iterables.
|
||||
*
|
||||
* @see https://goo.gl/Rok5YQ
|
||||
*/
|
||||
|
||||
goog.module('goog.collections.iters');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/**
|
||||
* Get the iterator for an iterable.
|
||||
* @param {!Iterable<VALUE>} iterable
|
||||
* @return {!Iterator<VALUE>}
|
||||
* @template VALUE
|
||||
*/
|
||||
function getIterator(iterable) {
|
||||
return iterable[goog.global.Symbol.iterator]();
|
||||
}
|
||||
exports.getIterator = getIterator;
|
||||
|
||||
|
||||
/**
|
||||
* Call a function with every value of an iterable.
|
||||
*
|
||||
* Warning: this function will never halt if given an iterable that
|
||||
* is never exhausted.
|
||||
*
|
||||
* @param {!Iterable<VALUE>} iterable
|
||||
* @param {function(VALUE) : *} f
|
||||
* @template VALUE
|
||||
*/
|
||||
exports.forEach = function(iterable, f) {
|
||||
for (const elem of iterable) {
|
||||
f(elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An Iterable that wraps a child iterable, and maps every element of the child
|
||||
* iterator to a new value, using a mapping function. Similar to Array.map, but
|
||||
* for Iterable.
|
||||
* @template TO,FROM
|
||||
* @implements {IteratorIterable<TO>}
|
||||
*/
|
||||
class MapIterator {
|
||||
/**
|
||||
* @param {!Iterable<FROM>} childIter
|
||||
* @param {function(FROM, number): TO} mapFn
|
||||
*/
|
||||
constructor(childIter, mapFn) {
|
||||
/** @private @const {!Iterator<FROM>} */
|
||||
this.childIterator_ = getIterator(childIter);
|
||||
|
||||
/** @private @const {function(FROM, number): TO} */
|
||||
this.mapFn_ = mapFn;
|
||||
|
||||
/** @private {number} */
|
||||
this.nextIndex_ = 0;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
next() {
|
||||
const childResult = this.childIterator_.next();
|
||||
// Always return a new object, even when childResult.done == true. This is
|
||||
// so that we don't accidentally preserve generator return values, which
|
||||
// are unlikely to be meaningful in the context of this MapIterator.
|
||||
return {
|
||||
value: childResult.done ?
|
||||
undefined :
|
||||
this.mapFn_.call(undefined, childResult.value, this.nextIndex_++),
|
||||
done: childResult.done,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps the values of one iterable to create another iterable.
|
||||
*
|
||||
* When next() is called on the returned iterable, it will call the given
|
||||
* function `f` with the next value of the given iterable
|
||||
* `iterable` until the given iterable is exhausted.
|
||||
*
|
||||
* @param {!Iterable<VALUE>} iterable
|
||||
* @param {function(VALUE, number): RESULT} f
|
||||
* @return {!IteratorIterable<RESULT>} The created iterable that gives the
|
||||
* mapped values.
|
||||
* @template VALUE, RESULT
|
||||
*/
|
||||
exports.map = function(iterable, f) {
|
||||
return new MapIterator(iterable, f);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An Iterable that wraps a child Iterable and returns a subset of the child's
|
||||
* items, based on a filter function. Similar to Array.filter, but for
|
||||
* Iterable.
|
||||
* @template T
|
||||
* @implements {IteratorIterable<T>}
|
||||
*/
|
||||
class FilterIterator {
|
||||
/**
|
||||
* @param {!Iterable<T>} childIter
|
||||
* @param {function(T, number): boolean} filterFn
|
||||
*/
|
||||
constructor(childIter, filterFn) {
|
||||
/** @private @const {!Iterator<T>} */
|
||||
this.childIter_ = getIterator(childIter);
|
||||
|
||||
/** @private @const {function(T, number): boolean} */
|
||||
this.filterFn_ = filterFn;
|
||||
|
||||
/** @private {number} */
|
||||
this.nextIndex_ = 0;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
next() {
|
||||
while (true) {
|
||||
const childResult = this.childIter_.next();
|
||||
if (childResult.done) {
|
||||
// Don't return childResult directly, because that would preserve
|
||||
// generator return values, and we want to ignore them.
|
||||
return {done: true, value: undefined};
|
||||
}
|
||||
const passesFilter =
|
||||
this.filterFn_.call(undefined, childResult.value, this.nextIndex_++);
|
||||
if (passesFilter) {
|
||||
return childResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter elements from one iterator to create another iterable.
|
||||
*
|
||||
* When next() is called on the returned iterator, it will call next() on the
|
||||
* given iterator and call the given function `f` with that value until `true`
|
||||
* is returned or the given iterator is exhausted.
|
||||
*
|
||||
* @param {!Iterable<VALUE>} iterable
|
||||
* @param {function(VALUE, number): boolean} f
|
||||
* @return {!IteratorIterable<VALUE>} The created iterable that gives the mapped
|
||||
* values.
|
||||
* @template VALUE
|
||||
*/
|
||||
exports.filter = function(iterable, f) {
|
||||
return new FilterIterator(iterable, f);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @implements {IteratorIterable<T>}
|
||||
*/
|
||||
class ConcatIterator {
|
||||
/** @param {!Array<!Iterator<T>>} iterators */
|
||||
constructor(iterators) {
|
||||
/** @private @const {!Array<!Iterator<T>>} */
|
||||
this.iterators_ = iterators;
|
||||
|
||||
/** @private {number} */
|
||||
this.iterIndex_ = 0;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
next() {
|
||||
while (this.iterIndex_ < this.iterators_.length) {
|
||||
const result = this.iterators_[this.iterIndex_].next();
|
||||
if (!result.done) {
|
||||
return result;
|
||||
}
|
||||
this.iterIndex_++;
|
||||
}
|
||||
return /** @type {!IIterableResult<T>} */ ({done: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Concatenates multiple iterators to create a new iterable.
|
||||
*
|
||||
* When next() is called on the return iterator, it will call next() on the
|
||||
* current passed iterator. When the current passed iterator is exhausted, it
|
||||
* will move on to the next iterator until there are no more left.
|
||||
*
|
||||
* All generator return values will be ignored (i.e. when childIter.next()
|
||||
* returns {done: true, value: notUndefined} it will be treated as just
|
||||
* {done: true}).
|
||||
*
|
||||
* @param {...!Iterable<VALUE>} iterables
|
||||
* @return {!IteratorIterable<VALUE>}
|
||||
* @template VALUE
|
||||
*/
|
||||
exports.concat = function(...iterables) {
|
||||
return new ConcatIterator(iterables.map(getIterator));
|
||||
};
|
||||
Executable
+159
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Helper methods that operate on Map-like objects (e.g. ES6
|
||||
* Maps).
|
||||
*/
|
||||
|
||||
goog.module('goog.collections.maps');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/**
|
||||
* A MapLike implements the same public interface as an ES6 Map, without tying
|
||||
* the underlying code directly to the implementation. Any additions to this
|
||||
* type should also be present on ES6 Maps.
|
||||
* @template K,V
|
||||
* @record
|
||||
*/
|
||||
class MapLike {
|
||||
constructor() {
|
||||
/** @const {number} The number of items in this map. */
|
||||
this.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {K} key The key to set in the map.
|
||||
* @param {V} val The value to set for the given key in the map.
|
||||
*/
|
||||
set(key, val) {};
|
||||
|
||||
/**
|
||||
* @param {K} key The key to retrieve from the map.
|
||||
* @return {V|undefined} The value for this key, or undefined if the key is
|
||||
* not present in the map.
|
||||
*/
|
||||
get(key) {};
|
||||
|
||||
/**
|
||||
* @return {!IteratorIterable<K>} An ES6 Iterator that iterates over the keys
|
||||
* in the map.
|
||||
*/
|
||||
keys() {};
|
||||
|
||||
/**
|
||||
* @return {!IteratorIterable<V>} An ES6 Iterator that iterates over the
|
||||
* values in the map.
|
||||
*/
|
||||
values() {};
|
||||
|
||||
/**
|
||||
* @param {K} key The key to check.
|
||||
* @return {boolean} True iff this key is present in the map.
|
||||
*/
|
||||
has(key) {};
|
||||
}
|
||||
exports.MapLike = MapLike;
|
||||
|
||||
/**
|
||||
* Iterates over each entry in the given entries and sets the entry in
|
||||
* the map, overwriting any existing entries for the key.
|
||||
* @param {!MapLike<K,V>} map The map to set entries on.
|
||||
* @param {?Iterable<!Array<K|V>>} entries The iterable of entries. This
|
||||
* iterable should really be of type Iterable<Array<[K,V]>>, but the tuple
|
||||
* type is not representable in the Closure Type System.
|
||||
* @template K,V
|
||||
*/
|
||||
function setAll(map, entries) {
|
||||
if (!entries) return;
|
||||
for (const [k, v] of entries) {
|
||||
map.set(k, v);
|
||||
}
|
||||
}
|
||||
exports.setAll = setAll;
|
||||
|
||||
/**
|
||||
* Determines if a given map contains the given value, optionally using
|
||||
* a custom comparison function.
|
||||
* @param {!MapLike<?,V1>} map The map whose values to check.
|
||||
* @param {V2} val The value to check for.
|
||||
* @param {(function(V1,V2): boolean)=} valueEqualityFn The comparison function
|
||||
* used to determine if the given value is equivalent to any of the values
|
||||
* in the map. If no function is provided, defaults to strict equality
|
||||
* (===).
|
||||
* @return {boolean} True iff the given map contains the given value according
|
||||
* to the comparison function.
|
||||
* @template V1,V2
|
||||
*/
|
||||
function hasValue(map, val, valueEqualityFn = defaultEqualityFn) {
|
||||
for (const v of map.values()) {
|
||||
if (valueEqualityFn(v, val)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.hasValue = hasValue;
|
||||
|
||||
/** @const {function(?,?): boolean} */
|
||||
const defaultEqualityFn = (a, b) => a === b;
|
||||
|
||||
/**
|
||||
* Compares two maps using their public APIs to determine if they have
|
||||
* equal contents, optionally using a custom comparison function when comaring
|
||||
* values.
|
||||
* @param {!MapLike<K,V1>} map The first map
|
||||
* @param {!MapLike<K,V2>} otherMap The other map
|
||||
* @param {(function(V1,V2): boolean)=} valueEqualityFn The comparison function
|
||||
* used to determine if the values obtained from each map are equivalent. If
|
||||
* no function is provided, defaults to strict equality (===).
|
||||
* @return {boolean}
|
||||
* @template K,V1,V2
|
||||
*/
|
||||
function equals(map, otherMap, valueEqualityFn = defaultEqualityFn) {
|
||||
if (map === otherMap) return true;
|
||||
if (map.size !== otherMap.size) return false;
|
||||
for (const key of map.keys()) {
|
||||
if (!otherMap.has(key)) return false;
|
||||
if (!valueEqualityFn(map.get(key), otherMap.get(key))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.equals = equals;
|
||||
|
||||
/**
|
||||
* Returns a new ES6 Map in which all the keys and values from the
|
||||
* given map are interchanged (keys become values and values become keys). If
|
||||
* multiple keys in the given map to the same value, the resulting value in the
|
||||
* transposed map is implementation-dependent.
|
||||
*
|
||||
* It acts very similarly to {goog.object.transpose(Object)}.
|
||||
* @param {!MapLike<K,V>} map The map to transpose.
|
||||
* @return {!Map<V,K>} A transposed version of the given map.
|
||||
* @template K,V
|
||||
*/
|
||||
function transpose(map) {
|
||||
const /** !Map<V,K> */ transposed = new Map();
|
||||
for (const key of map.keys()) {
|
||||
const val = map.get(key);
|
||||
transposed.set(val, key);
|
||||
}
|
||||
return transposed;
|
||||
}
|
||||
exports.transpose = transpose;
|
||||
|
||||
/**
|
||||
* ToObject returns a new object whose properties are the keys from the Map.
|
||||
* @param {!MapLike<K,V>} map The map to convert into an object.
|
||||
* @return {!Object<K,V>} An object representation of the Map.
|
||||
* @template K,V
|
||||
*/
|
||||
function toObject(map) {
|
||||
const /** !Object<K,V> */ obj = {};
|
||||
for (const key of map.keys()) {
|
||||
obj[key] = map.get(key);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
exports.toObject = toObject;
|
||||
Executable
+747
@@ -0,0 +1,747 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Logging and debugging utilities.
|
||||
*
|
||||
* @see ../demos/debug.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.debug.errorcontext');
|
||||
|
||||
|
||||
/** @define {boolean} Whether logging should be enabled. */
|
||||
goog.debug.LOGGING_ENABLED =
|
||||
goog.define('goog.debug.LOGGING_ENABLED', goog.DEBUG);
|
||||
|
||||
|
||||
/** @define {boolean} Whether to force "sloppy" stack building. */
|
||||
goog.debug.FORCE_SLOPPY_STACKS =
|
||||
goog.define('goog.debug.FORCE_SLOPPY_STACKS', false);
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} TODO(user): Remove this hack once bug is resolved.
|
||||
*/
|
||||
goog.debug.CHECK_FOR_THROWN_EVENT =
|
||||
goog.define('goog.debug.CHECK_FOR_THROWN_EVENT', false);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Catches onerror events fired by windows and similar objects.
|
||||
* @param {function(Object)} logFunc The function to call with the error
|
||||
* information.
|
||||
* @param {boolean=} opt_cancel Whether to stop the error from reaching the
|
||||
* browser.
|
||||
* @param {Object=} opt_target Object that fires onerror events.
|
||||
* @suppress {strictMissingProperties} onerror is not defined as a property
|
||||
* on Object.
|
||||
*/
|
||||
goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) {
|
||||
'use strict';
|
||||
var target = opt_target || goog.global;
|
||||
var oldErrorHandler = target.onerror;
|
||||
var retVal = !!opt_cancel;
|
||||
|
||||
/**
|
||||
* New onerror handler for this target. This onerror handler follows the spec
|
||||
* according to
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#runtime-script-errors
|
||||
* The spec was changed in August 2013 to support receiving column information
|
||||
* and an error object for all scripts on the same origin or cross origin
|
||||
* scripts with the proper headers. See
|
||||
* https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
|
||||
*
|
||||
* @param {string} message The error message. For cross-origin errors, this
|
||||
* will be scrubbed to just "Script error.". For new browsers that have
|
||||
* updated to follow the latest spec, errors that come from origins that
|
||||
* have proper cross origin headers will not be scrubbed.
|
||||
* @param {string} url The URL of the script that caused the error. The URL
|
||||
* will be scrubbed to "" for cross origin scripts unless the script has
|
||||
* proper cross origin headers and the browser has updated to the latest
|
||||
* spec.
|
||||
* @param {number} line The line number in the script that the error
|
||||
* occurred on.
|
||||
* @param {number=} opt_col The optional column number that the error
|
||||
* occurred on. Only browsers that have updated to the latest spec will
|
||||
* include this.
|
||||
* @param {Error=} opt_error The optional actual error object for this
|
||||
* error that should include the stack. Only browsers that have updated
|
||||
* to the latest spec will inlude this parameter.
|
||||
* @return {boolean} Whether to prevent the error from reaching the browser.
|
||||
*/
|
||||
target.onerror = function(message, url, line, opt_col, opt_error) {
|
||||
'use strict';
|
||||
if (oldErrorHandler) {
|
||||
oldErrorHandler(message, url, line, opt_col, opt_error);
|
||||
}
|
||||
logFunc({
|
||||
message: message,
|
||||
fileName: url,
|
||||
line: line,
|
||||
lineNumber: line,
|
||||
col: opt_col,
|
||||
error: opt_error
|
||||
});
|
||||
return retVal;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string representing an object and all its properties.
|
||||
* @param {Object|null|undefined} obj Object to expose.
|
||||
* @param {boolean=} opt_showFn Show the functions as well as the properties,
|
||||
* default is false.
|
||||
* @return {string} The string representation of `obj`.
|
||||
*/
|
||||
goog.debug.expose = function(obj, opt_showFn) {
|
||||
'use strict';
|
||||
if (typeof obj == 'undefined') {
|
||||
return 'undefined';
|
||||
}
|
||||
if (obj == null) {
|
||||
return 'NULL';
|
||||
}
|
||||
var str = [];
|
||||
|
||||
for (var x in obj) {
|
||||
if (!opt_showFn && typeof obj[x] === 'function') {
|
||||
continue;
|
||||
}
|
||||
var s = x + ' = ';
|
||||
|
||||
try {
|
||||
s += obj[x];
|
||||
} catch (e) {
|
||||
s += '*** ' + e + ' ***';
|
||||
}
|
||||
str.push(s);
|
||||
}
|
||||
return str.join('\n');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string representing a given primitive or object, and for an
|
||||
* object, all its properties and nested objects. NOTE: The output will include
|
||||
* Uids on all objects that were exposed. Any added Uids will be removed before
|
||||
* returning.
|
||||
* @param {*} obj Object to expose.
|
||||
* @param {boolean=} opt_showFn Also show properties that are functions (by
|
||||
* default, functions are omitted).
|
||||
* @return {string} A string representation of `obj`.
|
||||
*/
|
||||
goog.debug.deepExpose = function(obj, opt_showFn) {
|
||||
'use strict';
|
||||
var str = [];
|
||||
|
||||
// Track any objects where deepExpose added a Uid, so they can be cleaned up
|
||||
// before return. We do this globally, rather than only on ancestors so that
|
||||
// if the same object appears in the output, you can see it.
|
||||
var uidsToCleanup = [];
|
||||
var ancestorUids = {};
|
||||
|
||||
var helper = function(obj, space) {
|
||||
'use strict';
|
||||
var nestspace = space + ' ';
|
||||
|
||||
var indentMultiline = function(str) {
|
||||
'use strict';
|
||||
return str.replace(/\n/g, '\n' + space);
|
||||
};
|
||||
|
||||
|
||||
try {
|
||||
if (obj === undefined) {
|
||||
str.push('undefined');
|
||||
} else if (obj === null) {
|
||||
str.push('NULL');
|
||||
} else if (typeof obj === 'string') {
|
||||
str.push('"' + indentMultiline(obj) + '"');
|
||||
} else if (typeof obj === 'function') {
|
||||
str.push(indentMultiline(String(obj)));
|
||||
} else if (goog.isObject(obj)) {
|
||||
// Add a Uid if needed. The struct calls implicitly adds them.
|
||||
if (!goog.hasUid(obj)) {
|
||||
uidsToCleanup.push(obj);
|
||||
}
|
||||
var uid = goog.getUid(obj);
|
||||
if (ancestorUids[uid]) {
|
||||
str.push('*** reference loop detected (id=' + uid + ') ***');
|
||||
} else {
|
||||
ancestorUids[uid] = true;
|
||||
str.push('{');
|
||||
for (var x in obj) {
|
||||
if (!opt_showFn && typeof obj[x] === 'function') {
|
||||
continue;
|
||||
}
|
||||
str.push('\n');
|
||||
str.push(nestspace);
|
||||
str.push(x + ' = ');
|
||||
helper(obj[x], nestspace);
|
||||
}
|
||||
str.push('\n' + space + '}');
|
||||
delete ancestorUids[uid];
|
||||
}
|
||||
} else {
|
||||
str.push(obj);
|
||||
}
|
||||
} catch (e) {
|
||||
str.push('*** ' + e + ' ***');
|
||||
}
|
||||
};
|
||||
|
||||
helper(obj, '');
|
||||
|
||||
// Cleanup any Uids that were added by the deepExpose.
|
||||
for (var i = 0; i < uidsToCleanup.length; i++) {
|
||||
goog.removeUid(uidsToCleanup[i]);
|
||||
}
|
||||
|
||||
return str.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively outputs a nested array as a string.
|
||||
* @param {Array<?>} arr The array.
|
||||
* @return {string} String representing nested array.
|
||||
*/
|
||||
goog.debug.exposeArray = function(arr) {
|
||||
'use strict';
|
||||
var str = [];
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (Array.isArray(arr[i])) {
|
||||
str.push(goog.debug.exposeArray(arr[i]));
|
||||
} else {
|
||||
str.push(arr[i]);
|
||||
}
|
||||
}
|
||||
return '[ ' + str.join(', ') + ' ]';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the error/exception object between browsers.
|
||||
* @param {*} err Raw error object.
|
||||
* @return {{
|
||||
* message: (?|undefined),
|
||||
* name: (?|undefined),
|
||||
* lineNumber: (?|undefined),
|
||||
* fileName: (?|undefined),
|
||||
* stack: (?|undefined)
|
||||
* }} Representation of err as an Object. It will never return err.
|
||||
* @suppress {strictMissingProperties} properties not defined on err
|
||||
*/
|
||||
goog.debug.normalizeErrorObject = function(err) {
|
||||
'use strict';
|
||||
var href = goog.getObjectByName('window.location.href');
|
||||
if (err == null) {
|
||||
err = 'Unknown Error of type "null/undefined"';
|
||||
}
|
||||
if (typeof err === 'string') {
|
||||
return {
|
||||
'message': err,
|
||||
'name': 'Unknown error',
|
||||
'lineNumber': 'Not available',
|
||||
'fileName': href,
|
||||
'stack': 'Not available'
|
||||
};
|
||||
}
|
||||
|
||||
var lineNumber, fileName;
|
||||
var threwError = false;
|
||||
|
||||
try {
|
||||
lineNumber = err.lineNumber || err.line || 'Not available';
|
||||
} catch (e) {
|
||||
// Firefox 2 sometimes throws an error when accessing 'lineNumber':
|
||||
// Message: Permission denied to get property UnnamedClass.lineNumber
|
||||
lineNumber = 'Not available';
|
||||
threwError = true;
|
||||
}
|
||||
|
||||
try {
|
||||
fileName = err.fileName || err.filename || err.sourceURL ||
|
||||
// $googDebugFname may be set before a call to eval to set the filename
|
||||
// that the eval is supposed to present.
|
||||
goog.global['$googDebugFname'] || href;
|
||||
} catch (e) {
|
||||
// Firefox 2 may also throw an error when accessing 'filename'.
|
||||
fileName = 'Not available';
|
||||
threwError = true;
|
||||
}
|
||||
|
||||
var stack = goog.debug.serializeErrorStack_(err);
|
||||
|
||||
// The IE Error object contains only the name and the message.
|
||||
// The Safari Error object uses the line and sourceURL fields.
|
||||
if (threwError || !err.lineNumber || !err.fileName || !err.stack ||
|
||||
!err.message || !err.name) {
|
||||
var message = err.message;
|
||||
if (message == null) {
|
||||
if (err.constructor && err.constructor instanceof Function) {
|
||||
var ctorName = err.constructor.name ?
|
||||
err.constructor.name :
|
||||
goog.debug.getFunctionName(err.constructor);
|
||||
message = 'Unknown Error of type "' + ctorName + '"';
|
||||
// TODO(user): Remove this hack once bug is resolved.
|
||||
if (goog.debug.CHECK_FOR_THROWN_EVENT && ctorName == 'Event') {
|
||||
try {
|
||||
message = message + ' with Event.type "' + (err.type || '') + '"';
|
||||
} catch (e) {
|
||||
// Just give up on getting more information out of the error object.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message = 'Unknown Error of unknown type';
|
||||
}
|
||||
|
||||
// Avoid TypeError since toString could be missing from the instance
|
||||
// (e.g. if created Object.create(null)).
|
||||
if (typeof err.toString === 'function' &&
|
||||
Object.prototype.toString !== err.toString) {
|
||||
message += ': ' + err.toString();
|
||||
}
|
||||
}
|
||||
return {
|
||||
'message': message,
|
||||
'name': err.name || 'UnknownError',
|
||||
'lineNumber': lineNumber,
|
||||
'fileName': fileName,
|
||||
'stack': stack || 'Not available'
|
||||
};
|
||||
}
|
||||
// Standards error object
|
||||
// Typed !Object. Should be a subtype of the return type, but it's not.
|
||||
err.stack = stack;
|
||||
|
||||
// Return non-standard error to allow for consistent result (eg. enumerable).
|
||||
return {
|
||||
'message': err.message,
|
||||
'name': err.name,
|
||||
'lineNumber': err.lineNumber,
|
||||
'fileName': err.fileName,
|
||||
'stack': err.stack
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Serialize stack by including the cause chain of the exception if it exists.
|
||||
*
|
||||
*
|
||||
* @param {*} e an exception that may have a cause
|
||||
* @param {!Object=} seen set of cause that have already been serialized
|
||||
* @return {string}
|
||||
* @private
|
||||
* @suppress {missingProperties} properties not defined on cause and e
|
||||
*/
|
||||
goog.debug.serializeErrorStack_ = function(e, seen) {
|
||||
'use strict';
|
||||
if (!seen) {
|
||||
seen = {};
|
||||
}
|
||||
seen[goog.debug.serializeErrorAsKey_(e)] = true;
|
||||
|
||||
var stack = e['stack'] || '';
|
||||
|
||||
// Add cause if exists.
|
||||
var cause = e.cause;
|
||||
if (cause && !seen[goog.debug.serializeErrorAsKey_(cause)]) {
|
||||
stack += '\nCaused by: ';
|
||||
// Some browsers like Chrome add the error message as the first frame of the
|
||||
// stack, In this case we don't need to add it. Note: we don't use
|
||||
// String.startsWith method because it might have to be polyfilled.
|
||||
if (!cause.stack || cause.stack.indexOf(cause.toString()) != 0) {
|
||||
stack += (typeof cause === 'string') ? cause : cause.message + '\n';
|
||||
}
|
||||
stack += goog.debug.serializeErrorStack_(cause, seen);
|
||||
}
|
||||
|
||||
return stack;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize an error to a string key.
|
||||
* @param {*} e an exception
|
||||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.serializeErrorAsKey_ = function(e) {
|
||||
'use strict';
|
||||
var keyPrefix = '';
|
||||
|
||||
if (typeof e.toString === 'function') {
|
||||
keyPrefix = '' + e;
|
||||
}
|
||||
|
||||
return keyPrefix + e['stack'];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an object to an Error using the object's toString if it's not
|
||||
* already an Error, adds a stacktrace if there isn't one, and optionally adds
|
||||
* an extra message.
|
||||
* @param {*} err The original thrown error, object, or string.
|
||||
* @param {string=} opt_message optional additional message to add to the
|
||||
* error.
|
||||
* @return {!Error} If err is an Error, it is enhanced and returned. Otherwise,
|
||||
* it is converted to an Error which is enhanced and returned.
|
||||
*/
|
||||
goog.debug.enhanceError = function(err, opt_message) {
|
||||
'use strict';
|
||||
var error;
|
||||
if (!(err instanceof Error)) {
|
||||
error = Error(err);
|
||||
if (Error.captureStackTrace) {
|
||||
// Trim this function off the call stack, if we can.
|
||||
Error.captureStackTrace(error, goog.debug.enhanceError);
|
||||
}
|
||||
} else {
|
||||
error = err;
|
||||
}
|
||||
|
||||
if (!error.stack) {
|
||||
error.stack = goog.debug.getStacktrace(goog.debug.enhanceError);
|
||||
}
|
||||
if (opt_message) {
|
||||
// find the first unoccupied 'messageX' property
|
||||
var x = 0;
|
||||
while (error['message' + x]) {
|
||||
++x;
|
||||
}
|
||||
error['message' + x] = String(opt_message);
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an object to an Error using the object's toString if it's not
|
||||
* already an Error, adds a stacktrace if there isn't one, and optionally adds
|
||||
* context to the Error, which is reported by the closure error reporter.
|
||||
* @param {*} err The original thrown error, object, or string.
|
||||
* @param {!Object<string, string>=} opt_context Key-value context to add to the
|
||||
* Error.
|
||||
* @return {!Error} If err is an Error, it is enhanced and returned. Otherwise,
|
||||
* it is converted to an Error which is enhanced and returned.
|
||||
*/
|
||||
goog.debug.enhanceErrorWithContext = function(err, opt_context) {
|
||||
'use strict';
|
||||
var error = goog.debug.enhanceError(err);
|
||||
if (opt_context) {
|
||||
for (var key in opt_context) {
|
||||
goog.debug.errorcontext.addErrorContext(error, key, opt_context[key]);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current stack trace. Simple and iterative - doesn't worry about
|
||||
* catching circular references or getting the args.
|
||||
* @param {number=} opt_depth Optional maximum depth to trace back to.
|
||||
* @return {string} A string with the function names of all functions in the
|
||||
* stack, separated by \n.
|
||||
* @suppress {es5Strict}
|
||||
*/
|
||||
goog.debug.getStacktraceSimple = function(opt_depth) {
|
||||
'use strict';
|
||||
if (!goog.debug.FORCE_SLOPPY_STACKS) {
|
||||
var stack = goog.debug.getNativeStackTrace_(goog.debug.getStacktraceSimple);
|
||||
if (stack) {
|
||||
return stack;
|
||||
}
|
||||
// NOTE: browsers that have strict mode support also have native "stack"
|
||||
// properties. Fall-through for legacy browser support.
|
||||
}
|
||||
|
||||
var sb = [];
|
||||
var fn = arguments.callee.caller;
|
||||
var depth = 0;
|
||||
|
||||
while (fn && (!opt_depth || depth < opt_depth)) {
|
||||
sb.push(goog.debug.getFunctionName(fn));
|
||||
sb.push('()\n');
|
||||
|
||||
try {
|
||||
fn = fn.caller;
|
||||
} catch (e) {
|
||||
sb.push('[exception trying to get caller]\n');
|
||||
break;
|
||||
}
|
||||
depth++;
|
||||
if (depth >= goog.debug.MAX_STACK_DEPTH) {
|
||||
sb.push('[...long stack...]');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opt_depth && depth >= opt_depth) {
|
||||
sb.push('[...reached max depth limit...]');
|
||||
} else {
|
||||
sb.push('[end]');
|
||||
}
|
||||
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Max length of stack to try and output
|
||||
* @type {number}
|
||||
*/
|
||||
goog.debug.MAX_STACK_DEPTH = 50;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Function} fn The function to start getting the trace from.
|
||||
* @return {?string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.getNativeStackTrace_ = function(fn) {
|
||||
'use strict';
|
||||
var tempErr = new Error();
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(tempErr, fn);
|
||||
return String(tempErr.stack);
|
||||
} else {
|
||||
// IE10, only adds stack traces when an exception is thrown.
|
||||
try {
|
||||
throw tempErr;
|
||||
} catch (e) {
|
||||
tempErr = e;
|
||||
}
|
||||
var stack = tempErr.stack;
|
||||
if (stack) {
|
||||
return String(stack);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current stack trace, either starting from the caller or starting
|
||||
* from a specified function that's currently on the call stack.
|
||||
* @param {?Function=} fn If provided, when collecting the stack trace all
|
||||
* frames above the topmost call to this function, including that call,
|
||||
* will be left out of the stack trace.
|
||||
* @return {string} Stack trace.
|
||||
* @suppress {es5Strict}
|
||||
*/
|
||||
goog.debug.getStacktrace = function(fn) {
|
||||
'use strict';
|
||||
var stack;
|
||||
if (!goog.debug.FORCE_SLOPPY_STACKS) {
|
||||
// Try to get the stack trace from the environment if it is available.
|
||||
var contextFn = fn || goog.debug.getStacktrace;
|
||||
stack = goog.debug.getNativeStackTrace_(contextFn);
|
||||
}
|
||||
if (!stack) {
|
||||
// NOTE: browsers that have strict mode support also have native "stack"
|
||||
// properties. This function will throw in strict mode.
|
||||
stack = goog.debug.getStacktraceHelper_(fn || arguments.callee.caller, []);
|
||||
}
|
||||
return stack;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private helper for getStacktrace().
|
||||
* @param {?Function} fn If provided, when collecting the stack trace all
|
||||
* frames above the topmost call to this function, including that call,
|
||||
* will be left out of the stack trace.
|
||||
* @param {Array<!Function>} visited List of functions visited so far.
|
||||
* @return {string} Stack trace starting from function fn.
|
||||
* @suppress {es5Strict}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.getStacktraceHelper_ = function(fn, visited) {
|
||||
'use strict';
|
||||
var sb = [];
|
||||
|
||||
// Circular reference, certain functions like bind seem to cause a recursive
|
||||
// loop so we need to catch circular references
|
||||
if (goog.array.contains(visited, fn)) {
|
||||
sb.push('[...circular reference...]');
|
||||
|
||||
// Traverse the call stack until function not found or max depth is reached
|
||||
} else if (fn && visited.length < goog.debug.MAX_STACK_DEPTH) {
|
||||
sb.push(goog.debug.getFunctionName(fn) + '(');
|
||||
var args = fn.arguments;
|
||||
// Args may be null for some special functions such as host objects or eval.
|
||||
for (var i = 0; args && i < args.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.push(', ');
|
||||
}
|
||||
var argDesc;
|
||||
var arg = args[i];
|
||||
switch (typeof arg) {
|
||||
case 'object':
|
||||
argDesc = arg ? 'object' : 'null';
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
argDesc = arg;
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
argDesc = String(arg);
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
argDesc = arg ? 'true' : 'false';
|
||||
break;
|
||||
|
||||
case 'function':
|
||||
argDesc = goog.debug.getFunctionName(arg);
|
||||
argDesc = argDesc ? argDesc : '[fn]';
|
||||
break;
|
||||
|
||||
case 'undefined':
|
||||
default:
|
||||
argDesc = typeof arg;
|
||||
break;
|
||||
}
|
||||
|
||||
if (argDesc.length > 40) {
|
||||
argDesc = argDesc.substr(0, 40) + '...';
|
||||
}
|
||||
sb.push(argDesc);
|
||||
}
|
||||
visited.push(fn);
|
||||
sb.push(')\n');
|
||||
|
||||
try {
|
||||
sb.push(goog.debug.getStacktraceHelper_(fn.caller, visited));
|
||||
} catch (e) {
|
||||
sb.push('[exception trying to get caller]\n');
|
||||
}
|
||||
|
||||
} else if (fn) {
|
||||
sb.push('[...long stack...]');
|
||||
} else {
|
||||
sb.push('[end]');
|
||||
}
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a function name
|
||||
* @param {Function} fn Function to get name of.
|
||||
* @return {string} Function's name.
|
||||
*/
|
||||
goog.debug.getFunctionName = function(fn) {
|
||||
'use strict';
|
||||
if (goog.debug.fnNameCache_[fn]) {
|
||||
return goog.debug.fnNameCache_[fn];
|
||||
}
|
||||
|
||||
// Heuristically determine function name based on code.
|
||||
var functionSource = String(fn);
|
||||
if (!goog.debug.fnNameCache_[functionSource]) {
|
||||
var matches = /function\s+([^\(]+)/m.exec(functionSource);
|
||||
if (matches) {
|
||||
var method = matches[1];
|
||||
goog.debug.fnNameCache_[functionSource] = method;
|
||||
} else {
|
||||
goog.debug.fnNameCache_[functionSource] = '[Anonymous]';
|
||||
}
|
||||
}
|
||||
|
||||
return goog.debug.fnNameCache_[functionSource];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes whitespace visible by replacing it with printable characters.
|
||||
* This is useful in finding diffrences between the expected and the actual
|
||||
* output strings of a testcase.
|
||||
* @param {string} string whose whitespace needs to be made visible.
|
||||
* @return {string} string whose whitespace is made visible.
|
||||
*/
|
||||
goog.debug.makeWhitespaceVisible = function(string) {
|
||||
'use strict';
|
||||
return string.replace(/ /g, '[_]')
|
||||
.replace(/\f/g, '[f]')
|
||||
.replace(/\n/g, '[n]\n')
|
||||
.replace(/\r/g, '[r]')
|
||||
.replace(/\t/g, '[t]');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of a value. If a constructor is passed, and a suitable
|
||||
* string cannot be found, 'unknown type name' will be returned.
|
||||
*
|
||||
* <p>Forked rather than moved from {@link goog.asserts.getType_}
|
||||
* to avoid adding a dependency to goog.asserts.
|
||||
* @param {*} value A constructor, object, or primitive.
|
||||
* @return {string} The best display name for the value, or 'unknown type name'.
|
||||
*/
|
||||
goog.debug.runtimeType = function(value) {
|
||||
'use strict';
|
||||
if (value instanceof Function) {
|
||||
return value.displayName || value.name || 'unknown type name';
|
||||
} else if (value instanceof Object) {
|
||||
return /** @type {string} */ (value.constructor.displayName) ||
|
||||
value.constructor.name || Object.prototype.toString.call(value);
|
||||
} else {
|
||||
return value === null ? 'null' : typeof value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hash map for storing function names that have already been looked up.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.fnNameCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* Private internal function to support goog.debug.freeze.
|
||||
* @param {T} arg
|
||||
* @return {T}
|
||||
* @template T
|
||||
* @private
|
||||
*/
|
||||
goog.debug.freezeInternal_ = goog.DEBUG && Object.freeze || function(arg) {
|
||||
'use strict';
|
||||
return arg;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Freezes the given object, but only in debug mode (and in browsers that
|
||||
* support it). Note that this is a shallow freeze, so for deeply nested
|
||||
* objects it must be called at every level to ensure deep immutability.
|
||||
* @param {T} arg
|
||||
* @return {T}
|
||||
* @template T
|
||||
*/
|
||||
goog.debug.freeze = function(arg) {
|
||||
'use strict';
|
||||
// NOTE: this compiles to nothing, but hides the possible side effect of
|
||||
// freezeInternal_ from the compiler so that the entire call can be
|
||||
// removed if the result is not used.
|
||||
return {
|
||||
valueOf: function() {
|
||||
'use strict';
|
||||
return goog.debug.freezeInternal_(arg);
|
||||
}
|
||||
}.valueOf();
|
||||
};
|
||||
Executable
+158
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A global registry for entry points into a program,
|
||||
* so that they can be instrumented. Each module should register their
|
||||
* entry points with this registry. Designed to be compiled out
|
||||
* if no instrumentation is requested.
|
||||
*
|
||||
* Entry points may be registered before or after a call to
|
||||
* goog.debug.entryPointRegistry.monitorAll. If an entry point is registered
|
||||
* later, the existing monitor will instrument the new entry point.
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.EntryPointMonitor');
|
||||
goog.provide('goog.debug.entryPointRegistry');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
goog.debug.entryPointRegistry.EntryPointMonitor = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Instruments a function.
|
||||
*
|
||||
* @param {!Function} fn A function to instrument.
|
||||
* @return {!Function} The instrumented function.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.EntryPointMonitor.prototype.wrap;
|
||||
|
||||
|
||||
/**
|
||||
* Try to remove an instrumentation wrapper created by this monitor.
|
||||
* If the function passed to unwrap is not a wrapper created by this
|
||||
* monitor, then we will do nothing.
|
||||
*
|
||||
* Notice that some wrappers may not be unwrappable. For example, if other
|
||||
* monitors have applied their own wrappers, then it will be impossible to
|
||||
* unwrap them because their wrappers will have captured our wrapper.
|
||||
*
|
||||
* So it is important that entry points are unwrapped in the reverse
|
||||
* order that they were wrapped.
|
||||
*
|
||||
* @param {!Function} fn A function to unwrap.
|
||||
* @return {!Function} The unwrapped function, or `fn` if it was not
|
||||
* a wrapped function created by this monitor.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.EntryPointMonitor.prototype.unwrap;
|
||||
|
||||
/**
|
||||
* Alias for goog.debug.entryPointRegistry.EntryPointMonitor, for compatibility
|
||||
* purposes.
|
||||
* @const
|
||||
*/
|
||||
goog.debug.EntryPointMonitor = goog.debug.entryPointRegistry.EntryPointMonitor;
|
||||
|
||||
|
||||
/**
|
||||
* An array of entry point callbacks.
|
||||
* @type {!Array<function(!Function)>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.entryPointRegistry.refList_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Monitors that should wrap all the entry points.
|
||||
* @type {!Array<!goog.debug.EntryPointMonitor>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.entryPointRegistry.monitors_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Whether goog.debug.entryPointRegistry.monitorAll has ever been called.
|
||||
* Checking this allows the compiler to optimize out the registrations.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.entryPointRegistry.monitorsMayExist_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Register an entry point with this module.
|
||||
*
|
||||
* The entry point will be instrumented when a monitor is passed to
|
||||
* goog.debug.entryPointRegistry.monitorAll. If this has already occurred, the
|
||||
* entry point is instrumented immediately.
|
||||
*
|
||||
* @param {function(!Function)} callback A callback function which is called
|
||||
* with a transforming function to instrument the entry point. The callback
|
||||
* is responsible for wrapping the relevant entry point with the
|
||||
* transforming function.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.register = function(callback) {
|
||||
'use strict';
|
||||
// Don't use push(), so that this can be compiled out.
|
||||
goog.debug.entryPointRegistry
|
||||
.refList_[goog.debug.entryPointRegistry.refList_.length] = callback;
|
||||
// If no one calls monitorAll, this can be compiled out.
|
||||
if (goog.debug.entryPointRegistry.monitorsMayExist_) {
|
||||
var monitors = goog.debug.entryPointRegistry.monitors_;
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
callback(goog.bind(monitors[i].wrap, monitors[i]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Configures a monitor to wrap all entry points.
|
||||
*
|
||||
* Entry points that have already been registered are immediately wrapped by
|
||||
* the monitor. When an entry point is registered in the future, it will also
|
||||
* be wrapped by the monitor when it is registered.
|
||||
*
|
||||
* @param {!goog.debug.EntryPointMonitor} monitor An entry point monitor.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.monitorAll = function(monitor) {
|
||||
'use strict';
|
||||
goog.debug.entryPointRegistry.monitorsMayExist_ = true;
|
||||
var transformer = goog.bind(monitor.wrap, monitor);
|
||||
for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
|
||||
goog.debug.entryPointRegistry.refList_[i](transformer);
|
||||
}
|
||||
goog.debug.entryPointRegistry.monitors_.push(monitor);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Try to unmonitor all the entry points that have already been registered. If
|
||||
* an entry point is registered in the future, it will not be wrapped by the
|
||||
* monitor when it is registered. Note that this may fail if the entry points
|
||||
* have additional wrapping.
|
||||
*
|
||||
* @param {!goog.debug.EntryPointMonitor} monitor The last monitor to wrap
|
||||
* the entry points.
|
||||
* @throws {Error} If the monitor is not the most recently configured monitor.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.unmonitorAllIfPossible = function(monitor) {
|
||||
'use strict';
|
||||
var monitors = goog.debug.entryPointRegistry.monitors_;
|
||||
goog.asserts.assert(
|
||||
monitor == monitors[monitors.length - 1],
|
||||
'Only the most recent monitor can be unwrapped.');
|
||||
var transformer = goog.bind(monitor.unwrap, monitor);
|
||||
for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
|
||||
goog.debug.entryPointRegistry.refList_[i](transformer);
|
||||
}
|
||||
monitors.length--;
|
||||
};
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Provides a base class for custom Error objects such that the
|
||||
* stack is correctly maintained.
|
||||
*
|
||||
* You should never need to throw DebugError(msg) directly, Error(msg) is
|
||||
* sufficient.
|
||||
*/
|
||||
|
||||
goog.module('goog.debug.Error');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for custom error objects.
|
||||
* @param {*=} msg The message associated with the error.
|
||||
* @param {{
|
||||
* message: (?|undefined),
|
||||
* name: (?|undefined),
|
||||
* lineNumber: (?|undefined),
|
||||
* fileName: (?|undefined),
|
||||
* stack: (?|undefined),
|
||||
* cause: (?|undefined),
|
||||
* }=} cause The original error object to chain with.
|
||||
* @constructor
|
||||
* @extends {Error}
|
||||
*/
|
||||
function DebugError(msg = undefined, cause = undefined) {
|
||||
// Attempt to ensure there is a stack trace.
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, DebugError);
|
||||
} else {
|
||||
const stack = new Error().stack;
|
||||
if (stack) {
|
||||
/** @override */
|
||||
this.stack = stack;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
/** @override */
|
||||
this.message = String(msg);
|
||||
}
|
||||
|
||||
if (cause !== undefined) {
|
||||
/** @type {?} */
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to report this error to the server. Setting this to false will
|
||||
* cause the error reporter to not report the error back to the server,
|
||||
* which can be useful if the client knows that the error has already been
|
||||
* logged on the server.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.reportErrorToServer = true;
|
||||
}
|
||||
goog.inherits(DebugError, Error);
|
||||
|
||||
|
||||
/** @override @type {string} */
|
||||
DebugError.prototype.name = 'CustomError';
|
||||
|
||||
|
||||
exports = DebugError;
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Provides methods dealing with context on error objects.
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.errorcontext');
|
||||
|
||||
|
||||
/**
|
||||
* Adds key-value context to the error.
|
||||
* @param {!Error} err The error to add context to.
|
||||
* @param {string} contextKey Key for the context to be added.
|
||||
* @param {string} contextValue Value for the context to be added.
|
||||
*/
|
||||
goog.debug.errorcontext.addErrorContext = function(
|
||||
err, contextKey, contextValue) {
|
||||
'use strict';
|
||||
if (!err[goog.debug.errorcontext.CONTEXT_KEY_]) {
|
||||
err[goog.debug.errorcontext.CONTEXT_KEY_] = {};
|
||||
}
|
||||
err[goog.debug.errorcontext.CONTEXT_KEY_][contextKey] = contextValue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Error} err The error to get context from.
|
||||
* @return {!Object<string, string>} The context of the provided error.
|
||||
*/
|
||||
goog.debug.errorcontext.getErrorContext = function(err) {
|
||||
'use strict';
|
||||
return err[goog.debug.errorcontext.CONTEXT_KEY_] || {};
|
||||
};
|
||||
|
||||
|
||||
// TODO(user): convert this to a Symbol once goog.debug.ErrorReporter is
|
||||
// able to use ES6.
|
||||
/** @private @const {string} */
|
||||
goog.debug.errorcontext.CONTEXT_KEY_ = '__closure__error__context__984382';
|
||||
Executable
+364
@@ -0,0 +1,364 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Error handling utilities.
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.ErrorHandler');
|
||||
goog.provide('goog.debug.ErrorHandler.ProtectedFunctionError');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug.EntryPointMonitor');
|
||||
goog.require('goog.debug.Error');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The ErrorHandler can be used to to wrap functions with a try/catch
|
||||
* statement. If an exception is thrown, the given error handler function will
|
||||
* be called.
|
||||
*
|
||||
* When this object is disposed, it will stop handling exceptions and tracing.
|
||||
* It will also try to restore window.setTimeout and window.setInterval
|
||||
* if it wrapped them. Notice that in the general case, it is not technically
|
||||
* possible to remove the wrapper, because functions have no knowledge of
|
||||
* what they have been assigned to. So the app is responsible for other
|
||||
* forms of unwrapping.
|
||||
*
|
||||
* @param {Function} handler Handler for exceptions.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @implements {goog.debug.EntryPointMonitor}
|
||||
*/
|
||||
goog.debug.ErrorHandler = function(handler) {
|
||||
'use strict';
|
||||
goog.debug.ErrorHandler.base(this, 'constructor');
|
||||
|
||||
/**
|
||||
* Handler for exceptions, which can do logging, reporting, etc.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.errorHandlerFn_ = handler;
|
||||
|
||||
/**
|
||||
* Whether errors should be wrapped in
|
||||
* goog.debug.ErrorHandler.ProtectedFunctionError before rethrowing.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.wrapErrors_ = true; // TODO(malteubl) Change default.
|
||||
|
||||
/**
|
||||
* Whether to add a prefix to all error messages. The prefix is
|
||||
* goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX. This option
|
||||
* only has an effect if this.wrapErrors_ is set to false.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.prefixErrorMessages_ = false;
|
||||
};
|
||||
goog.inherits(goog.debug.ErrorHandler, goog.Disposable);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorHandler.prototype.wrap = function(fn) {
|
||||
'use strict';
|
||||
return this.protectEntryPoint(goog.asserts.assertFunction(fn));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorHandler.prototype.unwrap = function(fn) {
|
||||
'use strict';
|
||||
goog.asserts.assertFunction(fn);
|
||||
return fn[this.getFunctionIndex_(false)] || fn;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the index for a function. Used for internal indexing.
|
||||
* @param {boolean} wrapper True for the wrapper; false for the wrapped.
|
||||
* @return {string} The index where we should store the function in its
|
||||
* wrapper/wrapped function.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.getFunctionIndex_ = function(wrapper) {
|
||||
'use strict';
|
||||
return (wrapper ? '__wrapper_' : '__protected_') + goog.getUid(this) + '__';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Installs exception protection for an entry point function. When an exception
|
||||
* is thrown from a protected function, a handler will be invoked to handle it.
|
||||
*
|
||||
* @param {Function} fn An entry point function to be protected.
|
||||
* @return {!Function} A protected wrapper function that calls the entry point
|
||||
* function.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectEntryPoint = function(fn) {
|
||||
'use strict';
|
||||
var protectedFnName = this.getFunctionIndex_(true);
|
||||
if (!fn[protectedFnName]) {
|
||||
var wrapper = fn[protectedFnName] = this.getProtectedFunction(fn);
|
||||
wrapper[this.getFunctionIndex_(false)] = fn;
|
||||
}
|
||||
return fn[protectedFnName];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helps {@link #protectEntryPoint} by actually creating the protected
|
||||
* wrapper function, after {@link #protectEntryPoint} determines that one does
|
||||
* not already exist for the given function. Can be overridden by subclasses
|
||||
* that may want to implement different error handling, or add additional
|
||||
* entry point hooks.
|
||||
* @param {!Function} fn An entry point function to be protected.
|
||||
* @return {!Function} protected wrapper function.
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.getProtectedFunction = function(fn) {
|
||||
'use strict';
|
||||
var that = this;
|
||||
var googDebugErrorHandlerProtectedFunction = function() {
|
||||
'use strict';
|
||||
var self = /** @type {?} */ (this);
|
||||
if (that.isDisposed()) {
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
|
||||
try {
|
||||
return fn.apply(self, arguments);
|
||||
} catch (e) {
|
||||
that.handleError_(e);
|
||||
}
|
||||
};
|
||||
googDebugErrorHandlerProtectedFunction[this.getFunctionIndex_(false)] = fn;
|
||||
return googDebugErrorHandlerProtectedFunction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal error handler.
|
||||
* @param {?} e The error string or an Error-like object.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.handleError_ = function(e) {
|
||||
'use strict';
|
||||
// Don't re-report errors that have already been handled by this code.
|
||||
var MESSAGE_PREFIX =
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX;
|
||||
if ((e && typeof e === 'object' && typeof e.message === 'string' &&
|
||||
e.message.indexOf(MESSAGE_PREFIX) == 0) ||
|
||||
(typeof e === 'string' && e.indexOf(MESSAGE_PREFIX) == 0)) {
|
||||
return;
|
||||
}
|
||||
this.errorHandlerFn_(e);
|
||||
if (!this.wrapErrors_) {
|
||||
// Add the prefix to the existing message.
|
||||
if (this.prefixErrorMessages_) {
|
||||
if (typeof e === 'object' && e && typeof e.message === 'string') {
|
||||
/** @type {{message}} */ (e).message = MESSAGE_PREFIX + e.message;
|
||||
} else {
|
||||
e = MESSAGE_PREFIX + e;
|
||||
}
|
||||
}
|
||||
if (goog.DEBUG) {
|
||||
// Work around for https://code.google.com/p/v8/issues/detail?id=2625
|
||||
// and https://code.google.com/p/chromium/issues/detail?id=237059
|
||||
// Custom errors and errors with custom stack traces show the wrong
|
||||
// stack trace
|
||||
// If it has a stack and Error.captureStackTrace is supported (only
|
||||
// supported in V8 as of May 2013) log the stack to the console.
|
||||
if (e && typeof e.stack === 'string' && Error.captureStackTrace &&
|
||||
goog.global['console']) {
|
||||
goog.global['console']['error'](e.message, e.stack);
|
||||
}
|
||||
}
|
||||
// Re-throw original error. This is great for debugging as it makes
|
||||
// browser JS dev consoles show the correct error and stack trace.
|
||||
throw e;
|
||||
}
|
||||
// Re-throw it since this may be expected by the caller.
|
||||
throw new goog.debug.ErrorHandler.ProtectedFunctionError(e);
|
||||
};
|
||||
|
||||
|
||||
// TODO(mknichel): Allow these functions to take in the window to protect.
|
||||
/**
|
||||
* Installs exception protection for window.setTimeout to handle exceptions.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowSetTimeout = function() {
|
||||
'use strict';
|
||||
this.protectWindowFunctionsHelper_('setTimeout');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Install exception protection for window.setInterval to handle exceptions.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowSetInterval = function() {
|
||||
'use strict';
|
||||
this.protectWindowFunctionsHelper_('setInterval');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Install an unhandledrejection event listener that reports rejected promises.
|
||||
* Note: this will only work with Chrome 49+ and friends, but so far is the only
|
||||
* way to report uncaught errors in aysnc/await functions.
|
||||
* @param {!Window=} win the window to instrument, defaults to current window
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.catchUnhandledRejections = function(win) {
|
||||
'use strict';
|
||||
win = win || goog.global['window'];
|
||||
if ('onunhandledrejection' in win) {
|
||||
win.onunhandledrejection = (event) => {
|
||||
// event.reason contains the rejection reason. When an Error is
|
||||
// thrown, this is the Error object. If it is undefined, create a new
|
||||
// error object.
|
||||
const e =
|
||||
event && event.reason ? event.reason : new Error('uncaught error');
|
||||
this.handleError_(e);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Install exception protection for window.requestAnimationFrame to handle
|
||||
* exceptions.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowRequestAnimationFrame =
|
||||
function() {
|
||||
'use strict';
|
||||
var win = goog.global['window'];
|
||||
var fnNames = [
|
||||
'requestAnimationFrame', 'mozRequestAnimationFrame', 'webkitAnimationFrame',
|
||||
'msRequestAnimationFrame'
|
||||
];
|
||||
for (var i = 0; i < fnNames.length; i++) {
|
||||
var fnName = fnNames[i];
|
||||
if (fnNames[i] in win) {
|
||||
this.protectWindowFunctionsHelper_(fnName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for protecting a function that causes a function to be
|
||||
* asynchronously called, for example setTimeout or requestAnimationFrame.
|
||||
* @param {string} fnName The name of the function to protect.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowFunctionsHelper_ = function(
|
||||
fnName) {
|
||||
'use strict';
|
||||
var win = goog.global['window'];
|
||||
var originalFn = win[fnName];
|
||||
var that = this;
|
||||
win[fnName] = function(fn, time) {
|
||||
'use strict';
|
||||
// Don't try to protect strings. In theory, we could try to globalEval
|
||||
// the string, but this seems to lead to permission errors on IE6.
|
||||
if (typeof fn === 'string') {
|
||||
fn = goog.partial(goog.globalEval, fn);
|
||||
}
|
||||
arguments[0] = fn = that.protectEntryPoint(fn);
|
||||
|
||||
// IE doesn't support .call for setInterval/setTimeout, but it
|
||||
// also doesn't care what "this" is, so we can just call the
|
||||
// original function directly
|
||||
if (originalFn.apply) {
|
||||
return originalFn.apply(/** @type {?} */ (this), arguments);
|
||||
} else {
|
||||
var callback = fn;
|
||||
if (arguments.length > 2) {
|
||||
var args = Array.prototype.slice.call(arguments, 2);
|
||||
callback = function() {
|
||||
'use strict';
|
||||
fn.apply(/** @type {?} */ (this), args);
|
||||
};
|
||||
}
|
||||
return originalFn(callback, time);
|
||||
}
|
||||
};
|
||||
win[fnName][this.getFunctionIndex_(false)] = originalFn;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to wrap errors that occur in protected functions in a
|
||||
* goog.debug.ErrorHandler.ProtectedFunctionError.
|
||||
* @param {boolean} wrapErrors Whether to wrap errors.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.setWrapErrors = function(wrapErrors) {
|
||||
'use strict';
|
||||
this.wrapErrors_ = wrapErrors;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to add a prefix to all error messages that occur in protected
|
||||
* functions.
|
||||
* @param {boolean} prefixErrorMessages Whether to add a prefix to error
|
||||
* messages.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.setPrefixErrorMessages = function(
|
||||
prefixErrorMessages) {
|
||||
'use strict';
|
||||
this.prefixErrorMessages_ = prefixErrorMessages;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorHandler.prototype.disposeInternal = function() {
|
||||
'use strict';
|
||||
// Try to unwrap window.setTimeout and window.setInterval.
|
||||
var win = goog.global['window'];
|
||||
win.setTimeout = this.unwrap(win.setTimeout);
|
||||
win.setInterval = this.unwrap(win.setInterval);
|
||||
|
||||
goog.debug.ErrorHandler.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Error thrown to the caller of a protected entry point if the entry point
|
||||
* throws an error.
|
||||
* @param {*} cause The error thrown by the entry point.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
* @final
|
||||
*/
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError = function(cause) {
|
||||
'use strict';
|
||||
/** @suppress {missingProperties} message may not be defined. */
|
||||
var message = goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
|
||||
(cause && cause.message ? String(cause.message) : String(cause));
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError.base(
|
||||
this, 'constructor', message, /** @type {?} */ (cause));
|
||||
|
||||
/** @suppress {missingProperties} stack may not be defined. */
|
||||
var stack = cause && cause.stack;
|
||||
if (stack && typeof stack === 'string') {
|
||||
this.stack = /** @type {string} */ (stack);
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.debug.ErrorHandler.ProtectedFunctionError, goog.debug.Error);
|
||||
|
||||
|
||||
/**
|
||||
* Text to prefix the message with.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX =
|
||||
'Error in protected function: ';
|
||||
Executable
+285
@@ -0,0 +1,285 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Implements the disposable interface.
|
||||
*/
|
||||
|
||||
goog.provide('goog.Disposable');
|
||||
|
||||
goog.require('goog.disposable.IDisposable');
|
||||
goog.require('goog.dispose');
|
||||
/**
|
||||
* TODO(user): Remove this require.
|
||||
* @suppress {extraRequire}
|
||||
*/
|
||||
goog.require('goog.disposeAll');
|
||||
|
||||
/**
|
||||
* Class that provides the basic implementation for disposable objects. If your
|
||||
* class holds references or resources that can't be collected by standard GC,
|
||||
* it should extend this class or implement the disposable interface (defined
|
||||
* in goog.disposable.IDisposable). See description of
|
||||
* goog.disposable.IDisposable for examples of cleanup.
|
||||
* @constructor
|
||||
* @implements {goog.disposable.IDisposable}
|
||||
*/
|
||||
goog.Disposable = function() {
|
||||
'use strict';
|
||||
/**
|
||||
* If monitoring the goog.Disposable instances is enabled, stores the creation
|
||||
* stack trace of the Disposable instance.
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.creationStack;
|
||||
|
||||
if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
|
||||
if (goog.Disposable.INCLUDE_STACK_ON_CREATION) {
|
||||
this.creationStack = new Error().stack;
|
||||
}
|
||||
goog.Disposable.instances_[goog.getUid(this)] = this;
|
||||
}
|
||||
// Support sealing
|
||||
this.disposed_ = this.disposed_;
|
||||
this.onDisposeCallbacks_ = this.onDisposeCallbacks_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number} Different monitoring modes for Disposable.
|
||||
*/
|
||||
goog.Disposable.MonitoringMode = {
|
||||
/**
|
||||
* No monitoring.
|
||||
*/
|
||||
OFF: 0,
|
||||
/**
|
||||
* Creating and disposing the goog.Disposable instances is monitored. All
|
||||
* disposable objects need to call the `goog.Disposable` base
|
||||
* constructor. The PERMANENT mode must be switched on before creating any
|
||||
* goog.Disposable instances.
|
||||
*/
|
||||
PERMANENT: 1,
|
||||
/**
|
||||
* INTERACTIVE mode can be switched on and off on the fly without producing
|
||||
* errors. It also doesn't warn if the disposable objects don't call the
|
||||
* `goog.Disposable` base constructor.
|
||||
*/
|
||||
INTERACTIVE: 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} The monitoring mode of the goog.Disposable
|
||||
* instances. Default is OFF. Switching on the monitoring is only
|
||||
* recommended for debugging because it has a significant impact on
|
||||
* performance and memory usage. If switched off, the monitoring code
|
||||
* compiles down to 0 bytes.
|
||||
*/
|
||||
goog.Disposable.MONITORING_MODE =
|
||||
goog.define('goog.Disposable.MONITORING_MODE', 0);
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to attach creation stack to each created disposable
|
||||
* instance; This is only relevant for when MonitoringMode != OFF.
|
||||
*/
|
||||
goog.Disposable.INCLUDE_STACK_ON_CREATION =
|
||||
goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true);
|
||||
|
||||
|
||||
/**
|
||||
* Maps the unique ID of every undisposed `goog.Disposable` object to
|
||||
* the object itself.
|
||||
* @type {!Object<number, !goog.Disposable>}
|
||||
* @private
|
||||
*/
|
||||
goog.Disposable.instances_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array<!goog.Disposable>} All `goog.Disposable` objects that
|
||||
* haven't been disposed of.
|
||||
*/
|
||||
goog.Disposable.getUndisposedObjects = function() {
|
||||
'use strict';
|
||||
var ret = [];
|
||||
for (var id in goog.Disposable.instances_) {
|
||||
if (goog.Disposable.instances_.hasOwnProperty(id)) {
|
||||
ret.push(goog.Disposable.instances_[Number(id)]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the registry of undisposed objects but doesn't dispose of them.
|
||||
*/
|
||||
goog.Disposable.clearUndisposedObjects = function() {
|
||||
'use strict';
|
||||
goog.Disposable.instances_ = {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the object has been disposed of.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.Disposable.prototype.disposed_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks to invoke when this object is disposed.
|
||||
* @type {Array<!Function>}
|
||||
* @private
|
||||
*/
|
||||
goog.Disposable.prototype.onDisposeCallbacks_;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the object has been disposed of.
|
||||
* @override
|
||||
*/
|
||||
goog.Disposable.prototype.isDisposed = function() {
|
||||
'use strict';
|
||||
return this.disposed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the object has been disposed of.
|
||||
* @deprecated Use {@link #isDisposed} instead.
|
||||
*/
|
||||
goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of the object. If the object hasn't already been disposed of, calls
|
||||
* {@link #disposeInternal}. Classes that extend `goog.Disposable` should
|
||||
* override {@link #disposeInternal} in order to cleanup references, resources
|
||||
* and other disposable objects. Reentrant.
|
||||
*
|
||||
* @return {void} Nothing.
|
||||
* @override
|
||||
*/
|
||||
goog.Disposable.prototype.dispose = function() {
|
||||
'use strict';
|
||||
if (!this.disposed_) {
|
||||
// Set disposed_ to true first, in case during the chain of disposal this
|
||||
// gets disposed recursively.
|
||||
this.disposed_ = true;
|
||||
this.disposeInternal();
|
||||
if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
|
||||
var uid = goog.getUid(this);
|
||||
if (goog.Disposable.MONITORING_MODE ==
|
||||
goog.Disposable.MonitoringMode.PERMANENT &&
|
||||
!goog.Disposable.instances_.hasOwnProperty(uid)) {
|
||||
throw new Error(
|
||||
this + ' did not call the goog.Disposable base ' +
|
||||
'constructor or was disposed of after a clearUndisposedObjects ' +
|
||||
'call');
|
||||
}
|
||||
if (goog.Disposable.MONITORING_MODE !=
|
||||
goog.Disposable.MonitoringMode.OFF &&
|
||||
this.onDisposeCallbacks_ && this.onDisposeCallbacks_.length > 0) {
|
||||
throw new Error(
|
||||
this + ' did not empty its onDisposeCallbacks queue. This ' +
|
||||
'probably means it overrode dispose() or disposeInternal() ' +
|
||||
'without calling the superclass\' method.');
|
||||
}
|
||||
delete goog.Disposable.instances_[uid];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Associates a disposable object with this object so that they will be disposed
|
||||
* together.
|
||||
* @param {goog.disposable.IDisposable} disposable that will be disposed when
|
||||
* this object is disposed.
|
||||
*/
|
||||
goog.Disposable.prototype.registerDisposable = function(disposable) {
|
||||
'use strict';
|
||||
this.addOnDisposeCallback(goog.partial(goog.dispose, disposable));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Invokes a callback function when this object is disposed. Callbacks are
|
||||
* invoked in the order in which they were added. If a callback is added to
|
||||
* an already disposed Disposable, it will be called immediately.
|
||||
* @param {function(this:T):?} callback The callback function.
|
||||
* @param {T=} opt_scope An optional scope to call the callback in.
|
||||
* @template T
|
||||
*/
|
||||
goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {
|
||||
'use strict';
|
||||
if (this.disposed_) {
|
||||
opt_scope !== undefined ? callback.call(opt_scope) : callback();
|
||||
return;
|
||||
}
|
||||
if (!this.onDisposeCallbacks_) {
|
||||
this.onDisposeCallbacks_ = [];
|
||||
}
|
||||
|
||||
this.onDisposeCallbacks_.push(
|
||||
opt_scope !== undefined ? goog.bind(callback, opt_scope) : callback);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Performs appropriate cleanup. See description of goog.disposable.IDisposable
|
||||
* for examples. Classes that extend `goog.Disposable` should override this
|
||||
* method. Not reentrant. To avoid calling it twice, it must only be called from
|
||||
* the subclass' `disposeInternal` method. Everywhere else the public `dispose`
|
||||
* method must be used. For example:
|
||||
*
|
||||
* <pre>
|
||||
* mypackage.MyClass = function() {
|
||||
* mypackage.MyClass.base(this, 'constructor');
|
||||
* // Constructor logic specific to MyClass.
|
||||
* ...
|
||||
* };
|
||||
* goog.inherits(mypackage.MyClass, goog.Disposable);
|
||||
*
|
||||
* mypackage.MyClass.prototype.disposeInternal = function() {
|
||||
* // Dispose logic specific to MyClass.
|
||||
* ...
|
||||
* // Call superclass's disposeInternal at the end of the subclass's, like
|
||||
* // in C++, to avoid hard-to-catch issues.
|
||||
* mypackage.MyClass.base(this, 'disposeInternal');
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
goog.Disposable.prototype.disposeInternal = function() {
|
||||
'use strict';
|
||||
if (this.onDisposeCallbacks_) {
|
||||
while (this.onDisposeCallbacks_.length) {
|
||||
this.onDisposeCallbacks_.shift()();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns True if we can verify the object is disposed.
|
||||
* Calls `isDisposed` on the argument if it supports it. If obj
|
||||
* is not an object with an isDisposed() method, return false.
|
||||
* @param {*} obj The object to investigate.
|
||||
* @return {boolean} True if we can verify the object is disposed.
|
||||
*/
|
||||
goog.Disposable.isDisposed = function(obj) {
|
||||
'use strict';
|
||||
if (obj && typeof obj.isDisposed == 'function') {
|
||||
return obj.isDisposed();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview The dispose method is used to clean up references and
|
||||
* resources.
|
||||
*/
|
||||
|
||||
goog.module('goog.dispose');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
/**
|
||||
* Calls `dispose` on the argument if it supports it. If obj is not an
|
||||
* object with a dispose() method, this is a no-op.
|
||||
* @param {*} obj The object to dispose of.
|
||||
*/
|
||||
function dispose(obj) {
|
||||
if (obj && typeof obj.dispose == 'function') {
|
||||
obj.dispose();
|
||||
}
|
||||
}
|
||||
exports = dispose;
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview The disposeAll method is used to clean up references and
|
||||
* resources.
|
||||
*/
|
||||
|
||||
goog.module('goog.disposeAll');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const dispose = goog.require('goog.dispose');
|
||||
|
||||
/**
|
||||
* Calls `dispose` on each member of the list that supports it. (If the
|
||||
* member is an ArrayLike, then `goog.disposeAll()` will be called
|
||||
* recursively on each of its members.) If the member is not an object with a
|
||||
* `dispose()` method, then it is ignored.
|
||||
* @param {...*} var_args The list.
|
||||
*/
|
||||
function disposeAll(var_args) {
|
||||
for (let i = 0, len = arguments.length; i < len; ++i) {
|
||||
const disposable = arguments[i];
|
||||
if (goog.isArrayLike(disposable)) {
|
||||
disposeAll.apply(null, disposable);
|
||||
} else {
|
||||
dispose(disposable);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports = disposeAll;
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Definition of the disposable interface. A disposable object
|
||||
* has a dispose method to to clean up references and resources.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.disposable.IDisposable');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a disposable object. If a instance requires cleanup, it should
|
||||
* implement this interface (it may subclass goog.Disposable).
|
||||
*
|
||||
* Examples of cleanup that can be done in `dispose` method:
|
||||
* 1. Remove event listeners.
|
||||
* 2. Cancel timers (setTimeout, setInterval, goog.Timer).
|
||||
* 3. Call `dispose` on other disposable objects hold by current object.
|
||||
* 4. Close connections (e.g. WebSockets).
|
||||
*
|
||||
* Note that it's not required to delete properties (e.g. DOM nodes) or set them
|
||||
* to null as garbage collector will collect them assuming that references to
|
||||
* current object will be lost after it is disposed.
|
||||
*
|
||||
* See also http://go/mdn/JavaScript/Memory_Management.
|
||||
*
|
||||
* @record
|
||||
*/
|
||||
goog.disposable.IDisposable = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of the object and its resources.
|
||||
* @return {void} Nothing.
|
||||
*/
|
||||
goog.disposable.IDisposable.prototype.dispose = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the object has been disposed of.
|
||||
*/
|
||||
goog.disposable.IDisposable.prototype.isDisposed = goog.abstractMethod;
|
||||
Executable
+398
@@ -0,0 +1,398 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.provide('goog.dom.asserts');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
/**
|
||||
* @fileoverview Custom assertions to ensure that an element has the appropriate
|
||||
* type.
|
||||
*
|
||||
* Using a goog.dom.safe wrapper on an object on the incorrect type (via an
|
||||
* incorrect static type cast) can result in security bugs: For instance,
|
||||
* g.d.s.setAnchorHref ensures that the URL assigned to the .href attribute
|
||||
* satisfies the SafeUrl contract, i.e., is safe to dereference as a hyperlink.
|
||||
* However, the value assigned to a HTMLLinkElement's .href property requires
|
||||
* the stronger TrustedResourceUrl contract, since it can refer to a stylesheet.
|
||||
* Thus, using g.d.s.setAnchorHref on an (incorrectly statically typed) object
|
||||
* of type HTMLLinkElement can result in a security vulnerability.
|
||||
* Assertions of the correct run-time type help prevent such incorrect use.
|
||||
*
|
||||
* In some cases, code using the DOM API is tested using mock objects (e.g., a
|
||||
* plain object such as {'href': url} instead of an actual Location object).
|
||||
* To allow such mocking, the assertions permit objects of types that are not
|
||||
* relevant DOM API objects at all (for instance, not Element or Location).
|
||||
*
|
||||
* Note that instanceof checks don't work straightforwardly in older versions of
|
||||
* IE, or across frames (see,
|
||||
* http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object,
|
||||
* http://stackoverflow.com/questions/26248599/instanceof-htmlelement-in-iframe-is-not-element-or-object).
|
||||
*
|
||||
* Hence, these assertions may pass vacuously in such scenarios. The resulting
|
||||
* risk of security bugs is limited by the following factors:
|
||||
* - A bug can only arise in scenarios involving incorrect static typing (the
|
||||
* wrapper methods are statically typed to demand objects of the appropriate,
|
||||
* precise type).
|
||||
* - Typically, code is tested and exercised in multiple browsers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a Location.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where DOM APIs might
|
||||
* be mocked, also accepts any other type except for subtypes of {!Element}.
|
||||
* This is to ensure that, for instance, HTMLLinkElement is not being used in
|
||||
* place of a Location, since this could result in security bugs due to stronger
|
||||
* contracts required for assignments to the href property of the latter.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!Location}
|
||||
*/
|
||||
goog.dom.asserts.assertIsLocation = function(o) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
var win = goog.dom.asserts.getWindow_(o);
|
||||
if (win) {
|
||||
if (!o || (!(o instanceof win.Location) && o instanceof win.Element)) {
|
||||
goog.asserts.fail(
|
||||
'Argument is not a Location (or a non-Element mock); got: %s',
|
||||
goog.dom.asserts.debugStringForType_(o));
|
||||
}
|
||||
}
|
||||
}
|
||||
return /** @type {!Location} */ (o);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that a given object is either the given subtype of Element
|
||||
* or a non-Element, non-Location Mock.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where DOM
|
||||
* APIs might be mocked, also accepts any other type except for
|
||||
* subtypes of {!Element}. This is to ensure that, for instance,
|
||||
* HTMLScriptElement is not being used in place of a HTMLImageElement,
|
||||
* since this could result in security bugs due to stronger contracts
|
||||
* required for assignments to the src property of the latter.
|
||||
*
|
||||
* The DOM type is looked up in the window the object belongs to. In
|
||||
* some contexts, this might not be possible (e.g. when running tests
|
||||
* outside a browser, cross-domain lookup). In this case, the
|
||||
* assertions are skipped.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @param {string} typename The name of the DOM type.
|
||||
* @return {!Element} The object.
|
||||
* @private
|
||||
*/
|
||||
// TODO(bangert): Make an analog of goog.dom.TagName to correctly handle casts?
|
||||
goog.dom.asserts.assertIsElementType_ = function(o, typename) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
var win = goog.dom.asserts.getWindow_(o);
|
||||
if (win && typeof win[typename] != 'undefined') {
|
||||
if (!o ||
|
||||
(!(o instanceof win[typename]) &&
|
||||
(o instanceof win.Location || o instanceof win.Element))) {
|
||||
goog.asserts.fail(
|
||||
'Argument is not a %s (or a non-Element, non-Location mock); ' +
|
||||
'got: %s',
|
||||
typename, goog.dom.asserts.debugStringForType_(o));
|
||||
}
|
||||
}
|
||||
}
|
||||
return /** @type {!Element} */ (o);
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLAnchorElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not of type Location nor a subtype
|
||||
* of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLAnchorElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlAnchorElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLAnchorElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLAnchorElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLAnchorElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLButtonElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLButtonElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlButtonElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLButtonElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLButtonElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLButtonElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLLinkElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLLinkElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlLinkElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLLinkElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLLinkElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLLinkElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLImageElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLImageElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlImageElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLImageElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLImageElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLImageElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLAudioElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLAudioElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlAudioElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLAudioElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLAudioElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLAudioElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLVideoElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLVideoElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlVideoElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLVideoElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLVideoElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLVideoElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLInputElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLInputElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlInputElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLInputElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLInputElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLInputElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLTextAreaElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLTextAreaElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlTextAreaElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLTextAreaElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLTextAreaElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLTextAreaElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLCanvasElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLCanvasElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlCanvasElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLCanvasElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLCanvasElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLCanvasElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLEmbedElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLEmbedElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlEmbedElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLEmbedElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLEmbedElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLEmbedElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLFormElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLFormElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlFormElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLFormElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLFormElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLFormElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLFrameElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLFrameElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlFrameElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLFrameElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLFrameElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLFrameElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLIFrameElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLIFrameElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlIFrameElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLIFrameElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLIFrameElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLIFrameElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLObjectElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLObjectElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlObjectElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLObjectElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLObjectElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLObjectElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a given object is a HTMLScriptElement.
|
||||
*
|
||||
* To permit this assertion to pass in the context of tests where elements might
|
||||
* be mocked, also accepts objects that are not a subtype of Element.
|
||||
*
|
||||
* @param {?Object} o The object whose type to assert.
|
||||
* @return {!HTMLScriptElement}
|
||||
* @deprecated Use goog.asserts.dom.assertIsHtmlScriptElement instead.
|
||||
*/
|
||||
goog.dom.asserts.assertIsHTMLScriptElement = function(o) {
|
||||
'use strict';
|
||||
return /** @type {!HTMLScriptElement} */ (
|
||||
goog.dom.asserts.assertIsElementType_(o, 'HTMLScriptElement'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of a value's type.
|
||||
*
|
||||
* @param {*} value An object, or primitive.
|
||||
* @return {string} The best display name for the value.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.asserts.debugStringForType_ = function(value) {
|
||||
'use strict';
|
||||
if (goog.isObject(value)) {
|
||||
try {
|
||||
return /** @type {string|undefined} */ (value.constructor.displayName) ||
|
||||
value.constructor.name || Object.prototype.toString.call(value);
|
||||
} catch (e) {
|
||||
return '<object could not be stringified>';
|
||||
}
|
||||
} else {
|
||||
return value === undefined ? 'undefined' :
|
||||
value === null ? 'null' : typeof value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets window of element.
|
||||
* @param {?Object} o
|
||||
* @return {?Window}
|
||||
* @private
|
||||
* @suppress {strictMissingProperties} ownerDocument not defined on Object
|
||||
*/
|
||||
goog.dom.asserts.getWindow_ = function(o) {
|
||||
'use strict';
|
||||
try {
|
||||
var doc = o && o.ownerDocument;
|
||||
// This can throw “Blocked a frame with origin "chrome-extension://..." from
|
||||
// accessing a cross-origin frame” in Chrome extension.
|
||||
var win =
|
||||
doc && /** @type {?Window} */ (doc.defaultView || doc.parentWindow);
|
||||
win = win || /** @type {!Window} */ (goog.global);
|
||||
// This can throw “Permission denied to access property "Element" on
|
||||
// cross-origin object”.
|
||||
if (win.Element && win.Location) {
|
||||
return win;
|
||||
}
|
||||
} catch (ex) {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Browser capability checks for the dom package.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.dom.BrowserFeature');
|
||||
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether we know at compile time that the browser doesn't
|
||||
* support OffscreenCanvas.
|
||||
*/
|
||||
goog.dom.BrowserFeature.ASSUME_NO_OFFSCREEN_CANVAS =
|
||||
goog.define('goog.dom.ASSUME_NO_OFFSCREEN_CANVAS', false);
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether we know at compile time that the browser supports
|
||||
* all OffscreenCanvas contexts.
|
||||
*/
|
||||
// TODO(user): Eventually this should default to "FEATURESET_YEAR >= 202X".
|
||||
goog.dom.BrowserFeature.ASSUME_OFFSCREEN_CANVAS =
|
||||
goog.define('goog.dom.ASSUME_OFFSCREEN_CANVAS', false);
|
||||
|
||||
/**
|
||||
* Detects if a particular OffscreenCanvas context is supported.
|
||||
* @param {string} contextName name of the context to test.
|
||||
* @return {boolean} Whether the browser supports this OffscreenCanvas context.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.BrowserFeature.detectOffscreenCanvas_ = function(contextName) {
|
||||
'use strict';
|
||||
// This code only gets removed because we forced @nosideeffects on
|
||||
// the functions. See: b/138802376
|
||||
try {
|
||||
return Boolean(new self.OffscreenCanvas(0, 0).getContext(contextName));
|
||||
} catch (ex) {
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether the browser supports OffscreenCanvas 2D context.
|
||||
* @const {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature.OFFSCREEN_CANVAS_2D =
|
||||
!goog.dom.BrowserFeature.ASSUME_NO_OFFSCREEN_CANVAS &&
|
||||
(goog.dom.BrowserFeature.ASSUME_OFFSCREEN_CANVAS ||
|
||||
goog.dom.BrowserFeature.detectOffscreenCanvas_('2d'));
|
||||
|
||||
/**
|
||||
* Whether attributes 'name' and 'type' can be added to an element after it's
|
||||
* created. False in Internet Explorer prior to version 9.
|
||||
* @const {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature.CAN_ADD_NAME_OR_TYPE_ATTRIBUTES = true;
|
||||
|
||||
/**
|
||||
* Whether we can use element.children to access an element's Element
|
||||
* children. Available since Gecko 1.9.1, IE 9. (IE<9 also includes comment
|
||||
* nodes in the collection.)
|
||||
* @const {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature.CAN_USE_CHILDREN_ATTRIBUTE = true;
|
||||
|
||||
/**
|
||||
* Opera, Safari 3, and Internet Explorer 9 all support innerText but they
|
||||
* include text nodes in script and style tags. Not document-mode-dependent.
|
||||
* @const {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature.CAN_USE_INNER_TEXT = false;
|
||||
|
||||
/**
|
||||
* MSIE, Opera, and Safari>=4 support element.parentElement to access an
|
||||
* element's parent if it is an Element.
|
||||
* @const {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature.CAN_USE_PARENT_ELEMENT_PROPERTY =
|
||||
goog.userAgent.IE || goog.userAgent.WEBKIT;
|
||||
|
||||
/**
|
||||
* Whether NoScope elements need a scoped element written before them in
|
||||
* innerHTML.
|
||||
* MSDN: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx#1
|
||||
* @const {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT = goog.userAgent.IE;
|
||||
Executable
+3499
File diff suppressed because it is too large
Load Diff
Executable
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.provide('goog.dom.HtmlElement');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This subclass of HTMLElement is used when only a HTMLElement is possible and
|
||||
* not any of its subclasses. Normally, a type can refer to an instance of
|
||||
* itself or an instance of any subtype. More concretely, if HTMLElement is used
|
||||
* then the compiler must assume that it might still be e.g. HTMLScriptElement.
|
||||
* With this, the type check knows that it couldn't be any special element.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {HTMLElement}
|
||||
*/
|
||||
goog.dom.HtmlElement = function() {};
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Defines the goog.dom.InputType enum. This enumerates all
|
||||
* input element types (for INPUT, BUTTON, SELECT and TEXTAREA elements) in
|
||||
* either the W3C HTML 4.01 index of elements or the HTML5 draft specification.
|
||||
*
|
||||
* References:
|
||||
* http://www.w3.org/TR/html401/sgml/dtd.html#InputType
|
||||
* http://www.w3.org/TR/html-markup/input.html#input
|
||||
* https://html.spec.whatwg.org/multipage/forms.html#dom-input-type
|
||||
* https://html.spec.whatwg.org/multipage/forms.html#dom-button-type
|
||||
* https://html.spec.whatwg.org/multipage/forms.html#dom-select-type
|
||||
* https://html.spec.whatwg.org/multipage/forms.html#dom-textarea-type
|
||||
*/
|
||||
goog.provide('goog.dom.InputType');
|
||||
|
||||
|
||||
/**
|
||||
* Enum of all input types (for INPUT, BUTTON, SELECT and TEXTAREA elements)
|
||||
* specified by the W3C HTML4.01 and HTML5 specifications.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.dom.InputType = {
|
||||
BUTTON: 'button',
|
||||
CHECKBOX: 'checkbox',
|
||||
COLOR: 'color',
|
||||
DATE: 'date',
|
||||
DATETIME: 'datetime',
|
||||
DATETIME_LOCAL: 'datetime-local',
|
||||
EMAIL: 'email',
|
||||
FILE: 'file',
|
||||
HIDDEN: 'hidden',
|
||||
IMAGE: 'image',
|
||||
MENU: 'menu',
|
||||
MONTH: 'month',
|
||||
NUMBER: 'number',
|
||||
PASSWORD: 'password',
|
||||
RADIO: 'radio',
|
||||
RANGE: 'range',
|
||||
RESET: 'reset',
|
||||
SEARCH: 'search',
|
||||
SELECT_MULTIPLE: 'select-multiple',
|
||||
SELECT_ONE: 'select-one',
|
||||
SUBMIT: 'submit',
|
||||
TEL: 'tel',
|
||||
TEXT: 'text',
|
||||
TEXTAREA: 'textarea',
|
||||
TIME: 'time',
|
||||
URL: 'url',
|
||||
WEEK: 'week'
|
||||
};
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Definition of goog.dom.NodeType.
|
||||
*/
|
||||
|
||||
goog.provide('goog.dom.NodeType');
|
||||
|
||||
|
||||
/**
|
||||
* Constants for the nodeType attribute in the Node interface.
|
||||
*
|
||||
* These constants match those specified in the Node interface. These are
|
||||
* usually present on the Node object in recent browsers, but not in older
|
||||
* browsers (specifically, early IEs) and thus are given here.
|
||||
*
|
||||
* In some browsers (early IEs), these are not defined on the Node object,
|
||||
* so they are provided here.
|
||||
*
|
||||
* See http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.dom.NodeType = {
|
||||
ELEMENT: 1,
|
||||
ATTRIBUTE: 2,
|
||||
TEXT: 3,
|
||||
CDATA_SECTION: 4,
|
||||
ENTITY_REFERENCE: 5,
|
||||
ENTITY: 6,
|
||||
PROCESSING_INSTRUCTION: 7,
|
||||
COMMENT: 8,
|
||||
DOCUMENT: 9,
|
||||
DOCUMENT_TYPE: 10,
|
||||
DOCUMENT_FRAGMENT: 11,
|
||||
NOTATION: 12
|
||||
};
|
||||
Executable
+941
@@ -0,0 +1,941 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Type-safe wrappers for unsafe DOM APIs.
|
||||
*
|
||||
* This file provides type-safe wrappers for DOM APIs that can result in
|
||||
* cross-site scripting (XSS) vulnerabilities, if the API is supplied with
|
||||
* untrusted (attacker-controlled) input. Instead of plain strings, the type
|
||||
* safe wrappers consume values of types from the goog.html package whose
|
||||
* contract promises that values are safe to use in the corresponding context.
|
||||
*
|
||||
* Hence, a program that exclusively uses the wrappers in this file (i.e., whose
|
||||
* only reference to security-sensitive raw DOM APIs are in this file) is
|
||||
* guaranteed to be free of XSS due to incorrect use of such DOM APIs (modulo
|
||||
* correctness of code that produces values of the respective goog.html types,
|
||||
* and absent code that violates type safety).
|
||||
*
|
||||
* For example, assigning to an element's .innerHTML property a string that is
|
||||
* derived (even partially) from untrusted input typically results in an XSS
|
||||
* vulnerability. The type-safe wrapper goog.dom.safe.setInnerHtml consumes a
|
||||
* value of type goog.html.SafeHtml, whose contract states that using its values
|
||||
* in a HTML context will not result in XSS. Hence a program that is free of
|
||||
* direct assignments to any element's innerHTML property (with the exception of
|
||||
* the assignment to .innerHTML in this file) is guaranteed to be free of XSS
|
||||
* due to assignment of untrusted strings to the innerHTML property.
|
||||
*/
|
||||
|
||||
goog.provide('goog.dom.safe');
|
||||
goog.provide('goog.dom.safe.InsertAdjacentHtmlPosition');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom.asserts');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.html.SafeHtml');
|
||||
goog.require('goog.html.SafeScript');
|
||||
goog.require('goog.html.SafeStyle');
|
||||
goog.require('goog.html.SafeUrl');
|
||||
goog.require('goog.html.TrustedResourceUrl');
|
||||
goog.require('goog.html.uncheckedconversions');
|
||||
goog.require('goog.string.Const');
|
||||
goog.require('goog.string.internal');
|
||||
|
||||
|
||||
/** @enum {string} */
|
||||
goog.dom.safe.InsertAdjacentHtmlPosition = {
|
||||
AFTERBEGIN: 'afterbegin',
|
||||
AFTEREND: 'afterend',
|
||||
BEFOREBEGIN: 'beforebegin',
|
||||
BEFOREEND: 'beforeend'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Inserts known-safe HTML into a Node, at the specified position.
|
||||
* @param {!Node} node The node on which to call insertAdjacentHTML.
|
||||
* @param {!goog.dom.safe.InsertAdjacentHtmlPosition} position Position where
|
||||
* to insert the HTML.
|
||||
* @param {!goog.html.SafeHtml} html The known-safe HTML to insert.
|
||||
*/
|
||||
goog.dom.safe.insertAdjacentHtml = function(node, position, html) {
|
||||
'use strict';
|
||||
node.insertAdjacentHTML(position, goog.html.SafeHtml.unwrapTrustedHTML(html));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tags not allowed in goog.dom.safe.setInnerHtml.
|
||||
* @private @const {!Object<string, boolean>}
|
||||
*/
|
||||
goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_ = {
|
||||
'MATH': true,
|
||||
'SCRIPT': true,
|
||||
'STYLE': true,
|
||||
'SVG': true,
|
||||
'TEMPLATE': true
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether assigning to innerHTML results in a non-spec-compliant clean-up. Used
|
||||
* to define goog.dom.safe.unsafeSetInnerHtmlDoNotUseOrElse.
|
||||
*
|
||||
* <p>As mentioned in https://stackoverflow.com/questions/28741528, re-rendering
|
||||
* an element in IE by setting innerHTML causes IE to recursively disconnect all
|
||||
* parent/children connections that were in the previous contents of the
|
||||
* element. Unfortunately, this can unexpectedly result in confusing cases where
|
||||
* a function is run (typically asynchronously) on element that has since
|
||||
* disconnected from the DOM but assumes the presence of its children. A simple
|
||||
* workaround is to remove all children first. Testing on IE11 via
|
||||
* https://jsperf.com/innerhtml-vs-removechild/239, removeChild seems to be
|
||||
* ~10x faster than innerHTML='' for a large number of children (perhaps due
|
||||
* to the latter's recursive behavior), implying that this workaround would
|
||||
* not hurt performance and might actually improve it.
|
||||
* @return {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.dom.safe.isInnerHtmlCleanupRecursive_ =
|
||||
goog.functions.cacheReturnValue(function() {
|
||||
'use strict';
|
||||
// `document` missing in some test frameworks.
|
||||
if (goog.DEBUG && typeof document === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
// Create 3 nested <div>s without using innerHTML.
|
||||
// We're not chaining the appendChilds in one call, as this breaks
|
||||
// in a DocumentFragment.
|
||||
var div = document.createElement('div');
|
||||
var childDiv = document.createElement('div');
|
||||
childDiv.appendChild(document.createElement('div'));
|
||||
div.appendChild(childDiv);
|
||||
// `firstChild` is null in Google Js Test.
|
||||
if (goog.DEBUG && !div.firstChild) {
|
||||
return false;
|
||||
}
|
||||
var innerChild = div.firstChild.firstChild;
|
||||
div.innerHTML =
|
||||
goog.html.SafeHtml.unwrapTrustedHTML(goog.html.SafeHtml.EMPTY);
|
||||
return !innerChild.parentElement;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Assigns HTML to an element's innerHTML property. Helper to use only here and
|
||||
* in soy.js.
|
||||
* @param {?Element|?ShadowRoot} elem The element whose innerHTML is to be
|
||||
* assigned to.
|
||||
* @param {!goog.html.SafeHtml} html
|
||||
*/
|
||||
goog.dom.safe.unsafeSetInnerHtmlDoNotUseOrElse = function(elem, html) {
|
||||
'use strict';
|
||||
// See comment above goog.dom.safe.isInnerHtmlCleanupRecursive_.
|
||||
if (goog.dom.safe.isInnerHtmlCleanupRecursive_()) {
|
||||
while (elem.lastChild) {
|
||||
elem.removeChild(elem.lastChild);
|
||||
}
|
||||
}
|
||||
elem.innerHTML = goog.html.SafeHtml.unwrapTrustedHTML(html);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Assigns known-safe HTML to an element's innerHTML property.
|
||||
* @param {!Element|!ShadowRoot} elem The element whose innerHTML is to be
|
||||
* assigned to.
|
||||
* @param {!goog.html.SafeHtml} html The known-safe HTML to assign.
|
||||
* @throws {Error} If called with one of these tags: math, script, style, svg,
|
||||
* template.
|
||||
*/
|
||||
goog.dom.safe.setInnerHtml = function(elem, html) {
|
||||
'use strict';
|
||||
if (goog.asserts.ENABLE_ASSERTS && elem.tagName) {
|
||||
var tagName = elem.tagName.toUpperCase();
|
||||
if (goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_[tagName]) {
|
||||
throw new Error(
|
||||
'goog.dom.safe.setInnerHtml cannot be used to set content of ' +
|
||||
elem.tagName + '.');
|
||||
}
|
||||
}
|
||||
|
||||
goog.dom.safe.unsafeSetInnerHtmlDoNotUseOrElse(elem, html);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Assigns constant HTML to an element's innerHTML property.
|
||||
* @param {!Element} element The element whose innerHTML is to be assigned to.
|
||||
* @param {!goog.string.Const} constHtml The known-safe HTML to assign.
|
||||
* @throws {!Error} If called with one of these tags: math, script, style, svg,
|
||||
* template.
|
||||
*/
|
||||
goog.dom.safe.setInnerHtmlFromConstant = function(element, constHtml) {
|
||||
'use strict';
|
||||
goog.dom.safe.setInnerHtml(
|
||||
element,
|
||||
goog.html.uncheckedconversions
|
||||
.safeHtmlFromStringKnownToSatisfyTypeContract(
|
||||
goog.string.Const.from('Constant HTML to be immediatelly used.'),
|
||||
goog.string.Const.unwrap(constHtml)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Assigns known-safe HTML to an element's outerHTML property.
|
||||
* @param {!Element} elem The element whose outerHTML is to be assigned to.
|
||||
* @param {!goog.html.SafeHtml} html The known-safe HTML to assign.
|
||||
*/
|
||||
goog.dom.safe.setOuterHtml = function(elem, html) {
|
||||
'use strict';
|
||||
elem.outerHTML = goog.html.SafeHtml.unwrapTrustedHTML(html);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL a form element's action property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* form's action property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setFormElementAction(formEl, url);
|
||||
* which is a safe alternative to
|
||||
* formEl.action = url;
|
||||
* The latter can result in XSS vulnerabilities if url is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {!Element} form The form element whose action property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setFormElementAction = function(form, url) {
|
||||
'use strict';
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
goog.dom.asserts.assertIsHTMLFormElement(form).action =
|
||||
goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to a button element's formaction property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* button's formaction property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setButtonFormAction(buttonEl, url);
|
||||
* which is a safe alternative to
|
||||
* buttonEl.action = url;
|
||||
* The latter can result in XSS vulnerabilities if url is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {!Element} button The button element whose action property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setButtonFormAction = function(button, url) {
|
||||
'use strict';
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
goog.dom.asserts.assertIsHTMLButtonElement(button).formAction =
|
||||
goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
/**
|
||||
* Safely assigns a URL to an input element's formaction property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* input's formaction property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setInputFormAction(inputEl, url);
|
||||
* which is a safe alternative to
|
||||
* inputEl.action = url;
|
||||
* The latter can result in XSS vulnerabilities if url is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {!Element} input The input element whose action property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setInputFormAction = function(input, url) {
|
||||
'use strict';
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
goog.dom.asserts.assertIsHTMLInputElement(input).formAction =
|
||||
goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the given element's style property to the contents of the provided
|
||||
* SafeStyle object.
|
||||
* @param {!Element} elem
|
||||
* @param {!goog.html.SafeStyle} style
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setStyle = function(elem, style) {
|
||||
'use strict';
|
||||
elem.style.cssText = goog.html.SafeStyle.unwrap(style);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Writes known-safe HTML to a document.
|
||||
* @param {!Document} doc The document to be written to.
|
||||
* @param {!goog.html.SafeHtml} html The known-safe HTML to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.documentWrite = function(doc, html) {
|
||||
'use strict';
|
||||
doc.write(goog.html.SafeHtml.unwrapTrustedHTML(html));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to an anchor element's href property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* anchor's href property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setAnchorHref(anchorEl, url);
|
||||
* which is a safe alternative to
|
||||
* anchorEl.href = url;
|
||||
* The latter can result in XSS vulnerabilities if url is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {!HTMLAnchorElement} anchor The anchor element whose href property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setAnchorHref = function(anchor, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLAnchorElement(anchor);
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
anchor.href = goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to an image element's src property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* image's src property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* @param {!HTMLImageElement} imageElement The image element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setImageSrc = function(imageElement, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLImageElement(imageElement);
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
var allowDataUrl = /^data:image\//i.test(url);
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url, allowDataUrl);
|
||||
}
|
||||
imageElement.src = goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to a audio element's src property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* audio's src property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* @param {!HTMLAudioElement} audioElement The audio element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setAudioSrc = function(audioElement, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLAudioElement(audioElement);
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
var allowDataUrl = /^data:audio\//i.test(url);
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url, allowDataUrl);
|
||||
}
|
||||
audioElement.src = goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to a video element's src property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* video's src property. If url is of type string however, it is first
|
||||
* sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* @param {!HTMLVideoElement} videoElement The video element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setVideoSrc = function(videoElement, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLVideoElement(videoElement);
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
var allowDataUrl = /^data:video\//i.test(url);
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url, allowDataUrl);
|
||||
}
|
||||
videoElement.src = goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to an embed element's src property.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setEmbedSrc(embedEl, url);
|
||||
* which is a safe alternative to
|
||||
* embedEl.src = url;
|
||||
* The latter can result in loading untrusted code unless it is ensured that
|
||||
* the URL refers to a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLEmbedElement} embed The embed element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {!goog.html.TrustedResourceUrl} url The URL to assign.
|
||||
*/
|
||||
goog.dom.safe.setEmbedSrc = function(embed, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLEmbedElement(embed);
|
||||
embed.src = goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to a frame element's src property.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setFrameSrc(frameEl, url);
|
||||
* which is a safe alternative to
|
||||
* frameEl.src = url;
|
||||
* The latter can result in loading untrusted code unless it is ensured that
|
||||
* the URL refers to a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLFrameElement} frame The frame element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {!goog.html.TrustedResourceUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setFrameSrc = function(frame, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLFrameElement(frame);
|
||||
frame.src = goog.html.TrustedResourceUrl.unwrap(url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to an iframe element's src property.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setIframeSrc(iframeEl, url);
|
||||
* which is a safe alternative to
|
||||
* iframeEl.src = url;
|
||||
* The latter can result in loading untrusted code unless it is ensured that
|
||||
* the URL refers to a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLIFrameElement} iframe The iframe element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {!goog.html.TrustedResourceUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setIframeSrc = function(iframe, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLIFrameElement(iframe);
|
||||
iframe.src = goog.html.TrustedResourceUrl.unwrap(url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns HTML to an iframe element's srcdoc property.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setIframeSrcdoc(iframeEl, safeHtml);
|
||||
* which is a safe alternative to
|
||||
* iframeEl.srcdoc = html;
|
||||
* The latter can result in loading untrusted code.
|
||||
*
|
||||
* @param {!HTMLIFrameElement} iframe The iframe element whose srcdoc property
|
||||
* is to be assigned to.
|
||||
* @param {!goog.html.SafeHtml} html The HTML to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setIframeSrcdoc = function(iframe, html) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLIFrameElement(iframe);
|
||||
iframe.srcdoc = goog.html.SafeHtml.unwrapTrustedHTML(html);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely sets a link element's href and rel properties. Whether or not
|
||||
* the URL assigned to href has to be a goog.html.TrustedResourceUrl
|
||||
* depends on the value of the rel property. If rel contains "stylesheet"
|
||||
* then a TrustedResourceUrl is required.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setLinkHrefAndRel(linkEl, url, 'stylesheet');
|
||||
* which is a safe alternative to
|
||||
* linkEl.rel = 'stylesheet';
|
||||
* linkEl.href = url;
|
||||
* The latter can result in loading untrusted code unless it is ensured that
|
||||
* the URL refers to a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLLinkElement} link The link element whose href property
|
||||
* is to be assigned to.
|
||||
* @param {string|!goog.html.SafeUrl|!goog.html.TrustedResourceUrl} url The URL
|
||||
* to assign to the href property. Must be a TrustedResourceUrl if the
|
||||
* value assigned to rel contains "stylesheet". A string value is
|
||||
* sanitized with goog.html.SafeUrl.sanitize.
|
||||
* @param {string} rel The value to assign to the rel property.
|
||||
* @return {void}
|
||||
* @throws {Error} if rel contains "stylesheet" and url is not a
|
||||
* TrustedResourceUrl
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.setLinkHrefAndRel = function(link, url, rel) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLLinkElement(link);
|
||||
link.rel = rel;
|
||||
if (goog.string.internal.caseInsensitiveContains(rel, 'stylesheet')) {
|
||||
goog.asserts.assert(
|
||||
url instanceof goog.html.TrustedResourceUrl,
|
||||
'URL must be TrustedResourceUrl because "rel" contains "stylesheet"');
|
||||
link.href = goog.html.TrustedResourceUrl.unwrap(url);
|
||||
const win = link.ownerDocument && link.ownerDocument.defaultView;
|
||||
const nonce = goog.dom.safe.getStyleNonce(win);
|
||||
if (nonce) {
|
||||
link.setAttribute('nonce', nonce);
|
||||
}
|
||||
} else if (url instanceof goog.html.TrustedResourceUrl) {
|
||||
link.href = goog.html.TrustedResourceUrl.unwrap(url);
|
||||
} else if (url instanceof goog.html.SafeUrl) {
|
||||
link.href = goog.html.SafeUrl.unwrap(url);
|
||||
} else { // string
|
||||
// SafeUrl.sanitize must return legitimate SafeUrl when passed a string.
|
||||
link.href = goog.html.SafeUrl.unwrap(
|
||||
goog.html.SafeUrl.sanitizeAssertUnchanged(url));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to an object element's data property.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setObjectData(objectEl, url);
|
||||
* which is a safe alternative to
|
||||
* objectEl.data = url;
|
||||
* The latter can result in loading untrusted code unless setit is ensured that
|
||||
* the URL refers to a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLObjectElement} object The object element whose data property
|
||||
* is to be assigned to.
|
||||
* @param {!goog.html.TrustedResourceUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setObjectData = function(object, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLObjectElement(object);
|
||||
object.data = goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to a script element's src property.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setScriptSrc(scriptEl, url);
|
||||
* which is a safe alternative to
|
||||
* scriptEl.src = url;
|
||||
* The latter can result in loading untrusted code unless it is ensured that
|
||||
* the URL refers to a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLScriptElement} script The script element whose src property
|
||||
* is to be assigned to.
|
||||
* @param {!goog.html.TrustedResourceUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setScriptSrc = function(script, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLScriptElement(script);
|
||||
script.src = goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(url);
|
||||
goog.dom.safe.setNonceForScriptElement_(script);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a value to a script element's content.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setScriptContent(scriptEl, content);
|
||||
* which is a safe alternative to
|
||||
* scriptEl.text = content;
|
||||
* The latter can result in executing untrusted code unless it is ensured that
|
||||
* the code is loaded from a trustworthy resource.
|
||||
*
|
||||
* @param {!HTMLScriptElement} script The script element whose content is being
|
||||
* set.
|
||||
* @param {!goog.html.SafeScript} content The content to assign.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.dom.safe.setScriptContent = function(script, content) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsHTMLScriptElement(script);
|
||||
script.textContent = goog.html.SafeScript.unwrapTrustedScript(content);
|
||||
goog.dom.safe.setNonceForScriptElement_(script);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set nonce-based CSPs to dynamically created scripts.
|
||||
* @param {!HTMLScriptElement} script The script element whose nonce value
|
||||
* is to be calculated
|
||||
* @private
|
||||
*/
|
||||
goog.dom.safe.setNonceForScriptElement_ = function(script) {
|
||||
'use strict';
|
||||
var win = script.ownerDocument && script.ownerDocument.defaultView;
|
||||
const nonce = goog.dom.safe.getScriptNonce(win);
|
||||
if (nonce) {
|
||||
script.setAttribute('nonce', nonce);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely assigns a URL to a Location object's href property.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
|
||||
* loc's href property. If url is of type string however, it is first sanitized
|
||||
* using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.setLocationHref(document.location, redirectUrl);
|
||||
* which is a safe alternative to
|
||||
* document.location.href = redirectUrl;
|
||||
* The latter can result in XSS vulnerabilities if redirectUrl is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {!Location} loc The Location object whose href property is to be
|
||||
* assigned to.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
|
||||
*/
|
||||
goog.dom.safe.setLocationHref = function(loc, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsLocation(loc);
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
loc.href = goog.html.SafeUrl.unwrap(safeUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely assigns the URL of a Location object.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and
|
||||
* passed to Location#assign. If url is of type string however, it is
|
||||
* first sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.assignLocation(document.location, newUrl);
|
||||
* which is a safe alternative to
|
||||
* document.location.assign(newUrl);
|
||||
* The latter can result in XSS vulnerabilities if newUrl is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* This has the same behaviour as setLocationHref, however some test
|
||||
* mock Location.assign instead of a property assignment.
|
||||
*
|
||||
* @param {!Location} loc The Location object which is to be assigned.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.assignLocation = function(loc, url) {
|
||||
'use strict';
|
||||
goog.dom.asserts.assertIsLocation(loc);
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
loc.assign(goog.html.SafeUrl.unwrap(safeUrl));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely replaces the URL of a Location object.
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and
|
||||
* passed to Location#replace. If url is of type string however, it is
|
||||
* first sanitized using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.replaceLocation(document.location, newUrl);
|
||||
* which is a safe alternative to
|
||||
* document.location.replace(newUrl);
|
||||
* The latter can result in XSS vulnerabilities if newUrl is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {!Location} loc The Location object which is to be replaced.
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to assign.
|
||||
* @return {void}
|
||||
* @see goog.html.SafeUrl#sanitize
|
||||
*/
|
||||
goog.dom.safe.replaceLocation = function(loc, url) {
|
||||
'use strict';
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
loc.replace(goog.html.SafeUrl.unwrap(safeUrl));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely opens a URL in a new window (via window.open).
|
||||
*
|
||||
* If url is of type goog.html.SafeUrl, its value is unwrapped and passed in to
|
||||
* window.open. If url is of type string however, it is first sanitized
|
||||
* using goog.html.SafeUrl.sanitize.
|
||||
*
|
||||
* Note that this function does not prevent leakages via the referer that is
|
||||
* sent by window.open. It is advised to only use this to open 1st party URLs.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.openInWindow(url);
|
||||
* which is a safe alternative to
|
||||
* window.open(url);
|
||||
* The latter can result in XSS vulnerabilities if url is a
|
||||
* user-/attacker-controlled value.
|
||||
*
|
||||
* @param {string|!goog.html.SafeUrl} url The URL to open.
|
||||
* @param {Window=} opt_openerWin Window of which to call the .open() method.
|
||||
* Defaults to the global window.
|
||||
* @param {!goog.string.Const|string=} opt_name Name of the window to open in.
|
||||
* Can be _top, etc as allowed by window.open(). This accepts string for
|
||||
* legacy reasons. Pass goog.string.Const if possible.
|
||||
* @param {string=} opt_specs Comma-separated list of specifications, same as
|
||||
* in window.open().
|
||||
* @return {Window} Window the url was opened in.
|
||||
*/
|
||||
goog.dom.safe.openInWindow = function(url, opt_openerWin, opt_name, opt_specs) {
|
||||
'use strict';
|
||||
/** @type {!goog.html.SafeUrl} */
|
||||
var safeUrl;
|
||||
if (url instanceof goog.html.SafeUrl) {
|
||||
safeUrl = url;
|
||||
} else {
|
||||
safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url);
|
||||
}
|
||||
var win = opt_openerWin || goog.global;
|
||||
// If opt_name is undefined, simply passing that in to open() causes IE to
|
||||
// reuse the current window instead of opening a new one. Thus we pass '' in
|
||||
// instead, which according to spec opens a new window. See
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#dom-open .
|
||||
var name = opt_name instanceof goog.string.Const ?
|
||||
goog.string.Const.unwrap(opt_name) :
|
||||
opt_name || '';
|
||||
// Do not pass opt_specs to window.open unless it was provided by the caller.
|
||||
// IE11 will use it as a signal to open a new window rather than a new tab
|
||||
// (even if it is undefined).
|
||||
if (opt_specs !== undefined) {
|
||||
return win.open(goog.html.SafeUrl.unwrap(safeUrl), name, opt_specs);
|
||||
} else {
|
||||
return win.open(goog.html.SafeUrl.unwrap(safeUrl), name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parses the HTML as 'text/html'.
|
||||
* @param {!DOMParser} parser
|
||||
* @param {!goog.html.SafeHtml} html The HTML to be parsed.
|
||||
* @return {!Document}
|
||||
*/
|
||||
goog.dom.safe.parseFromStringHtml = function(parser, html) {
|
||||
'use strict';
|
||||
return goog.dom.safe.parseFromString(parser, html, 'text/html');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parses the string.
|
||||
* @param {!DOMParser} parser
|
||||
* @param {!goog.html.SafeHtml} content Note: We don't have a special type for
|
||||
* XML or SVG supported by this function so we use SafeHtml.
|
||||
* @param {string} type
|
||||
* @return {!Document}
|
||||
*/
|
||||
goog.dom.safe.parseFromString = function(parser, content, type) {
|
||||
'use strict';
|
||||
return parser.parseFromString(
|
||||
goog.html.SafeHtml.unwrapTrustedHTML(content), type);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Safely creates an HTMLImageElement from a Blob.
|
||||
*
|
||||
* Example usage:
|
||||
* goog.dom.safe.createImageFromBlob(blob);
|
||||
* which is a safe alternative to
|
||||
* image.src = createObjectUrl(blob)
|
||||
* The latter can result in executing malicious same-origin scripts from a bad
|
||||
* Blob.
|
||||
* @param {!Blob} blob The blob to create the image from.
|
||||
* @return {!HTMLImageElement} The image element created from the blob.
|
||||
* @throws {!Error} If called with a Blob with a MIME type other than image/.*.
|
||||
*/
|
||||
goog.dom.safe.createImageFromBlob = function(blob) {
|
||||
'use strict';
|
||||
// Any image/* MIME type is accepted as safe.
|
||||
if (!/^image\/.*/g.test(blob.type)) {
|
||||
throw new Error(
|
||||
'goog.dom.safe.createImageFromBlob only accepts MIME type image/.*.');
|
||||
}
|
||||
var objectUrl = goog.global.URL.createObjectURL(blob);
|
||||
var image = new goog.global.Image();
|
||||
image.onload = function() {
|
||||
'use strict';
|
||||
goog.global.URL.revokeObjectURL(objectUrl);
|
||||
};
|
||||
goog.dom.safe.setImageSrc(
|
||||
image,
|
||||
goog.html.uncheckedconversions
|
||||
.safeUrlFromStringKnownToSatisfyTypeContract(
|
||||
goog.string.Const.from('Image blob URL.'), objectUrl));
|
||||
return image;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a DocumentFragment by parsing html in the context of a Range.
|
||||
* @param {!Range} range The Range object starting from the context node to
|
||||
* create a fragment in.
|
||||
* @param {!goog.html.SafeHtml} html HTML to create a fragment from.
|
||||
* @return {?DocumentFragment}
|
||||
*/
|
||||
goog.dom.safe.createContextualFragment = function(range, html) {
|
||||
'use strict';
|
||||
return range.createContextualFragment(
|
||||
goog.html.SafeHtml.unwrapTrustedHTML(html));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns CSP script nonce, if set for any <script> tag.
|
||||
* @param {?Window=} opt_window The window context used to retrieve the nonce.
|
||||
* Defaults to global context.
|
||||
* @return {string} CSP nonce or empty string if no nonce is present.
|
||||
*/
|
||||
goog.dom.safe.getScriptNonce = function(opt_window) {
|
||||
return goog.dom.safe.getNonce_('script[nonce]', opt_window);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns CSP style nonce, if set for any <style> or <link rel="stylesheet">
|
||||
* tag.
|
||||
* @param {?Window=} opt_window The window context used to retrieve the nonce.
|
||||
* Defaults to global context.
|
||||
* @return {string} CSP nonce or empty string if no nonce is present.
|
||||
*/
|
||||
goog.dom.safe.getStyleNonce = function(opt_window) {
|
||||
return goog.dom.safe.getNonce_(
|
||||
'style[nonce],link[rel="stylesheet"][nonce]', opt_window);
|
||||
};
|
||||
|
||||
/**
|
||||
* According to the CSP3 spec a nonce must be a valid base64 string.
|
||||
* @see https://www.w3.org/TR/CSP3/#grammardef-base64-value
|
||||
* @private @const
|
||||
*/
|
||||
goog.dom.safe.NONCE_PATTERN_ = /^[\w+/_-]+[=]{0,2}$/;
|
||||
|
||||
/**
|
||||
* Returns CSP nonce, if set for any tag of given type.
|
||||
* @param {string} selector Selector for locating the element with nonce.
|
||||
* @param {?Window=} win The window context used to retrieve the nonce.
|
||||
* @return {string} CSP nonce or empty string if no nonce is present.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.safe.getNonce_ = function(selector, win) {
|
||||
const doc = (win || goog.global).document;
|
||||
if (!doc.querySelector) {
|
||||
return '';
|
||||
}
|
||||
let el = doc.querySelector(selector);
|
||||
if (el) {
|
||||
// Try to get the nonce from the IDL property first, because browsers that
|
||||
// implement additional nonce protection features (currently only Chrome) to
|
||||
// prevent nonce stealing via CSS do not expose the nonce via attributes.
|
||||
// See https://github.com/whatwg/html/issues/2369
|
||||
const nonce = el['nonce'] || el.getAttribute('nonce');
|
||||
if (nonce && goog.dom.safe.NONCE_PATTERN_.test(nonce)) {
|
||||
return nonce;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
Executable
+457
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Defines the goog.dom.TagName class. Its constants enumerate
|
||||
* all HTML tag names specified in either the W3C HTML 4.01 index of elements
|
||||
* or the HTML5.1 specification.
|
||||
*
|
||||
* References:
|
||||
* https://www.w3.org/TR/html401/index/elements.html
|
||||
* https://www.w3.org/TR/html51/dom.html#elements
|
||||
*/
|
||||
goog.provide('goog.dom.TagName');
|
||||
|
||||
goog.require('goog.dom.HtmlElement');
|
||||
|
||||
/**
|
||||
* A tag name for an HTML element.
|
||||
*
|
||||
* This type is a lie. All instances are actually strings. Do not implement it.
|
||||
*
|
||||
* It exists because we need an object type to host the template type parameter,
|
||||
* and that's not possible with literal or enum types. It is a record type so
|
||||
* that runtime type checks don't try to validate the lie.
|
||||
*
|
||||
* @template T
|
||||
* @record
|
||||
*/
|
||||
goog.dom.TagName = class {
|
||||
/**
|
||||
* Cast a string into the tagname for the associated constructor.
|
||||
*
|
||||
* @template T
|
||||
* @param {string} name
|
||||
* @param {function(new:T, ...?)} type
|
||||
* @return {!goog.dom.TagName<T>}
|
||||
*/
|
||||
static cast(name, type) {
|
||||
return /** @type {?} */ (name);
|
||||
}
|
||||
|
||||
/** @suppress {unusedPrivateMembers} */
|
||||
constructor() {
|
||||
/** @private {null} */
|
||||
this.googDomTagName_doNotImplementThisTypeOrElse_;
|
||||
|
||||
/** @private {T} */
|
||||
this.ensureTypeScriptRemembersTypeT_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appease the compiler that instances are stringafiable for the
|
||||
* purpose of being a dictionary key.
|
||||
*
|
||||
* Never implemented; always backed by `String::toString`.
|
||||
*
|
||||
* @override
|
||||
* @return {string}
|
||||
*/
|
||||
toString() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLAnchorElement>} */
|
||||
goog.dom.TagName.A = /** @type {?} */ ('A');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.ABBR = /** @type {?} */ ('ABBR');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.ACRONYM = /** @type {?} */ ('ACRONYM');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.ADDRESS = /** @type {?} */ ('ADDRESS');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLAppletElement>} */
|
||||
goog.dom.TagName.APPLET = /** @type {?} */ ('APPLET');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLAreaElement>} */
|
||||
goog.dom.TagName.AREA = /** @type {?} */ ('AREA');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.ARTICLE = /** @type {?} */ ('ARTICLE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.ASIDE = /** @type {?} */ ('ASIDE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLAudioElement>} */
|
||||
goog.dom.TagName.AUDIO = /** @type {?} */ ('AUDIO');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.B = /** @type {?} */ ('B');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLBaseElement>} */
|
||||
goog.dom.TagName.BASE = /** @type {?} */ ('BASE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLBaseFontElement>} */
|
||||
goog.dom.TagName.BASEFONT = /** @type {?} */ ('BASEFONT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.BDI = /** @type {?} */ ('BDI');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.BDO = /** @type {?} */ ('BDO');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.BIG = /** @type {?} */ ('BIG');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLQuoteElement>} */
|
||||
goog.dom.TagName.BLOCKQUOTE = /** @type {?} */ ('BLOCKQUOTE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLBodyElement>} */
|
||||
goog.dom.TagName.BODY = /** @type {?} */ ('BODY');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLBRElement>} */
|
||||
goog.dom.TagName.BR = /** @type {?} */ ('BR');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLButtonElement>} */
|
||||
goog.dom.TagName.BUTTON = /** @type {?} */ ('BUTTON');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLCanvasElement>} */
|
||||
goog.dom.TagName.CANVAS = /** @type {?} */ ('CANVAS');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableCaptionElement>} */
|
||||
goog.dom.TagName.CAPTION = /** @type {?} */ ('CAPTION');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.CENTER = /** @type {?} */ ('CENTER');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.CITE = /** @type {?} */ ('CITE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.CODE = /** @type {?} */ ('CODE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableColElement>} */
|
||||
goog.dom.TagName.COL = /** @type {?} */ ('COL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableColElement>} */
|
||||
goog.dom.TagName.COLGROUP = /** @type {?} */ ('COLGROUP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.COMMAND = /** @type {?} */ ('COMMAND');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.DATA = /** @type {?} */ ('DATA');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLDataListElement>} */
|
||||
goog.dom.TagName.DATALIST = /** @type {?} */ ('DATALIST');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.DD = /** @type {?} */ ('DD');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLModElement>} */
|
||||
goog.dom.TagName.DEL = /** @type {?} */ ('DEL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLDetailsElement>} */
|
||||
goog.dom.TagName.DETAILS = /** @type {?} */ ('DETAILS');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.DFN = /** @type {?} */ ('DFN');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLDialogElement>} */
|
||||
goog.dom.TagName.DIALOG = /** @type {?} */ ('DIALOG');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLDirectoryElement>} */
|
||||
goog.dom.TagName.DIR = /** @type {?} */ ('DIR');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLDivElement>} */
|
||||
goog.dom.TagName.DIV = /** @type {?} */ ('DIV');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLDListElement>} */
|
||||
goog.dom.TagName.DL = /** @type {?} */ ('DL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.DT = /** @type {?} */ ('DT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.EM = /** @type {?} */ ('EM');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLEmbedElement>} */
|
||||
goog.dom.TagName.EMBED = /** @type {?} */ ('EMBED');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLFieldSetElement>} */
|
||||
goog.dom.TagName.FIELDSET = /** @type {?} */ ('FIELDSET');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.FIGCAPTION = /** @type {?} */ ('FIGCAPTION');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.FIGURE = /** @type {?} */ ('FIGURE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLFontElement>} */
|
||||
goog.dom.TagName.FONT = /** @type {?} */ ('FONT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.FOOTER = /** @type {?} */ ('FOOTER');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLFormElement>} */
|
||||
goog.dom.TagName.FORM = /** @type {?} */ ('FORM');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLFrameElement>} */
|
||||
goog.dom.TagName.FRAME = /** @type {?} */ ('FRAME');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLFrameSetElement>} */
|
||||
goog.dom.TagName.FRAMESET = /** @type {?} */ ('FRAMESET');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadingElement>} */
|
||||
goog.dom.TagName.H1 = /** @type {?} */ ('H1');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadingElement>} */
|
||||
goog.dom.TagName.H2 = /** @type {?} */ ('H2');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadingElement>} */
|
||||
goog.dom.TagName.H3 = /** @type {?} */ ('H3');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadingElement>} */
|
||||
goog.dom.TagName.H4 = /** @type {?} */ ('H4');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadingElement>} */
|
||||
goog.dom.TagName.H5 = /** @type {?} */ ('H5');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadingElement>} */
|
||||
goog.dom.TagName.H6 = /** @type {?} */ ('H6');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHeadElement>} */
|
||||
goog.dom.TagName.HEAD = /** @type {?} */ ('HEAD');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.HEADER = /** @type {?} */ ('HEADER');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.HGROUP = /** @type {?} */ ('HGROUP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHRElement>} */
|
||||
goog.dom.TagName.HR = /** @type {?} */ ('HR');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLHtmlElement>} */
|
||||
goog.dom.TagName.HTML = /** @type {?} */ ('HTML');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.I = /** @type {?} */ ('I');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLIFrameElement>} */
|
||||
goog.dom.TagName.IFRAME = /** @type {?} */ ('IFRAME');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLImageElement>} */
|
||||
goog.dom.TagName.IMG = /** @type {?} */ ('IMG');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLInputElement>} */
|
||||
goog.dom.TagName.INPUT = /** @type {?} */ ('INPUT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLModElement>} */
|
||||
goog.dom.TagName.INS = /** @type {?} */ ('INS');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLIsIndexElement>} */
|
||||
goog.dom.TagName.ISINDEX = /** @type {?} */ ('ISINDEX');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.KBD = /** @type {?} */ ('KBD');
|
||||
|
||||
// HTMLKeygenElement is deprecated.
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.KEYGEN = /** @type {?} */ ('KEYGEN');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLLabelElement>} */
|
||||
goog.dom.TagName.LABEL = /** @type {?} */ ('LABEL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLLegendElement>} */
|
||||
goog.dom.TagName.LEGEND = /** @type {?} */ ('LEGEND');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLLIElement>} */
|
||||
goog.dom.TagName.LI = /** @type {?} */ ('LI');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLLinkElement>} */
|
||||
goog.dom.TagName.LINK = /** @type {?} */ ('LINK');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.MAIN = /** @type {?} */ ('MAIN');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLMapElement>} */
|
||||
goog.dom.TagName.MAP = /** @type {?} */ ('MAP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.MARK = /** @type {?} */ ('MARK');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.MATH = /** @type {?} */ ('MATH');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLMenuElement>} */
|
||||
goog.dom.TagName.MENU = /** @type {?} */ ('MENU');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLMenuItemElement>} */
|
||||
goog.dom.TagName.MENUITEM = /** @type {?} */ ('MENUITEM');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLMetaElement>} */
|
||||
goog.dom.TagName.META = /** @type {?} */ ('META');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLMeterElement>} */
|
||||
goog.dom.TagName.METER = /** @type {?} */ ('METER');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.NAV = /** @type {?} */ ('NAV');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.NOFRAMES = /** @type {?} */ ('NOFRAMES');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.NOSCRIPT = /** @type {?} */ ('NOSCRIPT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLObjectElement>} */
|
||||
goog.dom.TagName.OBJECT = /** @type {?} */ ('OBJECT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLOListElement>} */
|
||||
goog.dom.TagName.OL = /** @type {?} */ ('OL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLOptGroupElement>} */
|
||||
goog.dom.TagName.OPTGROUP = /** @type {?} */ ('OPTGROUP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLOptionElement>} */
|
||||
goog.dom.TagName.OPTION = /** @type {?} */ ('OPTION');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLOutputElement>} */
|
||||
goog.dom.TagName.OUTPUT = /** @type {?} */ ('OUTPUT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLParagraphElement>} */
|
||||
goog.dom.TagName.P = /** @type {?} */ ('P');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLParamElement>} */
|
||||
goog.dom.TagName.PARAM = /** @type {?} */ ('PARAM');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLPictureElement>} */
|
||||
goog.dom.TagName.PICTURE = /** @type {?} */ ('PICTURE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLPreElement>} */
|
||||
goog.dom.TagName.PRE = /** @type {?} */ ('PRE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLProgressElement>} */
|
||||
goog.dom.TagName.PROGRESS = /** @type {?} */ ('PROGRESS');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLQuoteElement>} */
|
||||
goog.dom.TagName.Q = /** @type {?} */ ('Q');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.RP = /** @type {?} */ ('RP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.RT = /** @type {?} */ ('RT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.RTC = /** @type {?} */ ('RTC');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.RUBY = /** @type {?} */ ('RUBY');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.S = /** @type {?} */ ('S');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SAMP = /** @type {?} */ ('SAMP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLScriptElement>} */
|
||||
goog.dom.TagName.SCRIPT = /** @type {?} */ ('SCRIPT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SECTION = /** @type {?} */ ('SECTION');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLSelectElement>} */
|
||||
goog.dom.TagName.SELECT = /** @type {?} */ ('SELECT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SMALL = /** @type {?} */ ('SMALL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLSourceElement>} */
|
||||
goog.dom.TagName.SOURCE = /** @type {?} */ ('SOURCE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLSpanElement>} */
|
||||
goog.dom.TagName.SPAN = /** @type {?} */ ('SPAN');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.STRIKE = /** @type {?} */ ('STRIKE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.STRONG = /** @type {?} */ ('STRONG');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLStyleElement>} */
|
||||
goog.dom.TagName.STYLE = /** @type {?} */ ('STYLE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SUB = /** @type {?} */ ('SUB');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SUMMARY = /** @type {?} */ ('SUMMARY');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SUP = /** @type {?} */ ('SUP');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.SVG = /** @type {?} */ ('SVG');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableElement>} */
|
||||
goog.dom.TagName.TABLE = /** @type {?} */ ('TABLE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableSectionElement>} */
|
||||
goog.dom.TagName.TBODY = /** @type {?} */ ('TBODY');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableCellElement>} */
|
||||
goog.dom.TagName.TD = /** @type {?} */ ('TD');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTemplateElement>} */
|
||||
goog.dom.TagName.TEMPLATE = /** @type {?} */ ('TEMPLATE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTextAreaElement>} */
|
||||
goog.dom.TagName.TEXTAREA = /** @type {?} */ ('TEXTAREA');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableSectionElement>} */
|
||||
goog.dom.TagName.TFOOT = /** @type {?} */ ('TFOOT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableCellElement>} */
|
||||
goog.dom.TagName.TH = /** @type {?} */ ('TH');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableSectionElement>} */
|
||||
goog.dom.TagName.THEAD = /** @type {?} */ ('THEAD');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.TIME = /** @type {?} */ ('TIME');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTitleElement>} */
|
||||
goog.dom.TagName.TITLE = /** @type {?} */ ('TITLE');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTableRowElement>} */
|
||||
goog.dom.TagName.TR = /** @type {?} */ ('TR');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLTrackElement>} */
|
||||
goog.dom.TagName.TRACK = /** @type {?} */ ('TRACK');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.TT = /** @type {?} */ ('TT');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.U = /** @type {?} */ ('U');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLUListElement>} */
|
||||
goog.dom.TagName.UL = /** @type {?} */ ('UL');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.VAR = /** @type {?} */ ('VAR');
|
||||
|
||||
/** @const {!goog.dom.TagName<!HTMLVideoElement>} */
|
||||
goog.dom.TagName.VIDEO = /** @type {?} */ ('VIDEO');
|
||||
|
||||
/** @const {!goog.dom.TagName<!goog.dom.HtmlElement>} */
|
||||
goog.dom.TagName.WBR = /** @type {?} */ ('WBR');
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Utilities for HTML element tag names.
|
||||
*/
|
||||
goog.provide('goog.dom.tags');
|
||||
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
/**
|
||||
* The void elements specified by
|
||||
* http://www.w3.org/TR/html-markup/syntax.html#void-elements.
|
||||
* @const @private {!Object<string, boolean>}
|
||||
*/
|
||||
goog.dom.tags.VOID_TAGS_ = goog.object.createSet(
|
||||
'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',
|
||||
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr');
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the tag is void (with no contents allowed and no legal end
|
||||
* tag), for example 'br'.
|
||||
* @param {string} tagName The tag name in lower case.
|
||||
* @return {boolean}
|
||||
*/
|
||||
goog.dom.tags.isVoidTag = function(tagName) {
|
||||
'use strict';
|
||||
return goog.dom.tags.VOID_TAGS_[tagName] === true;
|
||||
};
|
||||
Executable
+447
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A patched, standardized event object for browser events.
|
||||
*
|
||||
* <pre>
|
||||
* The patched event object contains the following members:
|
||||
* - type {string} Event type, e.g. 'click'
|
||||
* - target {Object} The element that actually triggered the event
|
||||
* - currentTarget {Object} The element the listener is attached to
|
||||
* - relatedTarget {Object} For mouseover and mouseout, the previous object
|
||||
* - offsetX {number} X-coordinate relative to target
|
||||
* - offsetY {number} Y-coordinate relative to target
|
||||
* - clientX {number} X-coordinate relative to viewport
|
||||
* - clientY {number} Y-coordinate relative to viewport
|
||||
* - screenX {number} X-coordinate relative to the edge of the screen
|
||||
* - screenY {number} Y-coordinate relative to the edge of the screen
|
||||
* - button {number} Mouse button. Use isButton() to test.
|
||||
* - keyCode {number} Key-code
|
||||
* - ctrlKey {boolean} Was ctrl key depressed
|
||||
* - altKey {boolean} Was alt key depressed
|
||||
* - shiftKey {boolean} Was shift key depressed
|
||||
* - metaKey {boolean} Was meta key depressed
|
||||
* - pointerId {number} Pointer ID
|
||||
* - pointerType {string} Pointer type, e.g. 'mouse', 'pen', or 'touch'
|
||||
* - defaultPrevented {boolean} Whether the default action has been prevented
|
||||
* - state {Object} History state object
|
||||
*
|
||||
* NOTE: The keyCode member contains the raw browser keyCode. For normalized
|
||||
* key and character code use {@link goog.events.KeyHandler}.
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.BrowserEvent');
|
||||
goog.provide('goog.events.BrowserEvent.MouseButton');
|
||||
goog.provide('goog.events.BrowserEvent.PointerType');
|
||||
|
||||
goog.require('goog.debug');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.reflect');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
/**
|
||||
* @define {boolean} If true, use the layerX and layerY properties of a native
|
||||
* browser event over the offsetX and offsetY properties, which cause expensive
|
||||
* reflow. If layerX or layerY is not defined, offsetX and offsetY will be used
|
||||
* as usual.
|
||||
*/
|
||||
goog.events.USE_LAYER_XY_AS_OFFSET_XY =
|
||||
goog.define('goog.events.USE_LAYER_XY_AS_OFFSET_XY', false);
|
||||
|
||||
/**
|
||||
* Accepts a browser event object and creates a patched, cross browser event
|
||||
* object.
|
||||
* The content of this object will not be initialized if no event object is
|
||||
* provided. If this is the case, init() needs to be invoked separately.
|
||||
* @param {Event=} opt_e Browser event object.
|
||||
* @param {EventTarget=} opt_currentTarget Current target for event.
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
*/
|
||||
goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
|
||||
'use strict';
|
||||
goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');
|
||||
|
||||
/**
|
||||
* Target that fired the event.
|
||||
* @override
|
||||
* @type {?Node}
|
||||
*/
|
||||
this.target = null;
|
||||
|
||||
/**
|
||||
* Node that had the listener attached.
|
||||
* @override
|
||||
* @type {?Node|undefined}
|
||||
*/
|
||||
this.currentTarget = null;
|
||||
|
||||
/**
|
||||
* For mouseover and mouseout events, the related object for the event.
|
||||
* @type {?Node}
|
||||
*/
|
||||
this.relatedTarget = null;
|
||||
|
||||
/**
|
||||
* X-coordinate relative to target.
|
||||
* @type {number}
|
||||
*/
|
||||
this.offsetX = 0;
|
||||
|
||||
/**
|
||||
* Y-coordinate relative to target.
|
||||
* @type {number}
|
||||
*/
|
||||
this.offsetY = 0;
|
||||
|
||||
/**
|
||||
* X-coordinate relative to the window.
|
||||
* @type {number}
|
||||
*/
|
||||
this.clientX = 0;
|
||||
|
||||
/**
|
||||
* Y-coordinate relative to the window.
|
||||
* @type {number}
|
||||
*/
|
||||
this.clientY = 0;
|
||||
|
||||
/**
|
||||
* X-coordinate relative to the monitor.
|
||||
* @type {number}
|
||||
*/
|
||||
this.screenX = 0;
|
||||
|
||||
/**
|
||||
* Y-coordinate relative to the monitor.
|
||||
* @type {number}
|
||||
*/
|
||||
this.screenY = 0;
|
||||
|
||||
/**
|
||||
* Which mouse button was pressed.
|
||||
* @type {number}
|
||||
*/
|
||||
this.button = 0;
|
||||
|
||||
/**
|
||||
* Key of key press.
|
||||
* @type {string}
|
||||
*/
|
||||
this.key = '';
|
||||
|
||||
/**
|
||||
* Keycode of key press.
|
||||
* @type {number}
|
||||
*/
|
||||
this.keyCode = 0;
|
||||
|
||||
/**
|
||||
* Keycode of key press.
|
||||
* @type {number}
|
||||
*/
|
||||
this.charCode = 0;
|
||||
|
||||
/**
|
||||
* Whether control was pressed at time of event.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.ctrlKey = false;
|
||||
|
||||
/**
|
||||
* Whether alt was pressed at time of event.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.altKey = false;
|
||||
|
||||
/**
|
||||
* Whether shift was pressed at time of event.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.shiftKey = false;
|
||||
|
||||
/**
|
||||
* Whether the meta key was pressed at time of event.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.metaKey = false;
|
||||
|
||||
/**
|
||||
* History state object, only set for PopState events where it's a copy of the
|
||||
* state object provided to pushState or replaceState.
|
||||
* @type {?Object}
|
||||
*/
|
||||
this.state = null;
|
||||
|
||||
/**
|
||||
* Whether the default platform modifier key was pressed at time of event.
|
||||
* (This is control for all platforms except Mac, where it's Meta.)
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.platformModifierKey = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.pointerId = 0;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.pointerType = '';
|
||||
|
||||
/**
|
||||
* The browser event object.
|
||||
* @private {?Event}
|
||||
*/
|
||||
this.event_ = null;
|
||||
|
||||
if (opt_e) {
|
||||
this.init(opt_e, opt_currentTarget);
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.events.BrowserEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* Normalized button constants for the mouse.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.events.BrowserEvent.MouseButton = {
|
||||
LEFT: 0,
|
||||
MIDDLE: 1,
|
||||
RIGHT: 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalized pointer type constants for pointer events.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.events.BrowserEvent.PointerType = {
|
||||
MOUSE: 'mouse',
|
||||
PEN: 'pen',
|
||||
TOUCH: 'touch'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Static data for mapping mouse buttons.
|
||||
* @type {!Array<number>}
|
||||
* @deprecated Use `goog.events.BrowserEvent.IE_BUTTON_MAP` instead.
|
||||
*/
|
||||
goog.events.BrowserEvent.IEButtonMap = goog.debug.freeze([
|
||||
1, // LEFT
|
||||
4, // MIDDLE
|
||||
2 // RIGHT
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* Static data for mapping mouse buttons.
|
||||
* @const {!Array<number>}
|
||||
*/
|
||||
goog.events.BrowserEvent.IE_BUTTON_MAP = goog.events.BrowserEvent.IEButtonMap;
|
||||
|
||||
|
||||
/**
|
||||
* Static data for mapping MSPointerEvent types to PointerEvent types.
|
||||
* @const {!Object<number, goog.events.BrowserEvent.PointerType>}
|
||||
*/
|
||||
goog.events.BrowserEvent.IE_POINTER_TYPE_MAP = goog.debug.freeze({
|
||||
2: goog.events.BrowserEvent.PointerType.TOUCH,
|
||||
3: goog.events.BrowserEvent.PointerType.PEN,
|
||||
4: goog.events.BrowserEvent.PointerType.MOUSE
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a browser event object and creates a patched, cross browser event
|
||||
* object.
|
||||
* @param {Event} e Browser event object.
|
||||
* @param {EventTarget=} opt_currentTarget Current target for event.
|
||||
*/
|
||||
goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
|
||||
'use strict';
|
||||
var type = this.type = e.type;
|
||||
|
||||
/**
|
||||
* On touch devices use the first "changed touch" as the relevant touch.
|
||||
* @type {?Touch}
|
||||
*/
|
||||
var relevantTouch =
|
||||
e.changedTouches && e.changedTouches.length ? e.changedTouches[0] : null;
|
||||
|
||||
// TODO(nicksantos): Change this.target to type EventTarget.
|
||||
this.target = /** @type {Node} */ (e.target) || e.srcElement;
|
||||
|
||||
// TODO(nicksantos): Change this.currentTarget to type EventTarget.
|
||||
this.currentTarget = /** @type {Node} */ (opt_currentTarget);
|
||||
|
||||
var relatedTarget = /** @type {Node} */ (e.relatedTarget);
|
||||
if (relatedTarget) {
|
||||
// There's a bug in FireFox where sometimes, relatedTarget will be a
|
||||
// chrome element, and accessing any property of it will get a permission
|
||||
// denied exception. See:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=497780
|
||||
if (goog.userAgent.GECKO) {
|
||||
if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {
|
||||
relatedTarget = null;
|
||||
}
|
||||
}
|
||||
} else if (type == goog.events.EventType.MOUSEOVER) {
|
||||
relatedTarget = e.fromElement;
|
||||
} else if (type == goog.events.EventType.MOUSEOUT) {
|
||||
relatedTarget = e.toElement;
|
||||
}
|
||||
|
||||
this.relatedTarget = relatedTarget;
|
||||
|
||||
if (relevantTouch) {
|
||||
this.clientX = relevantTouch.clientX !== undefined ? relevantTouch.clientX :
|
||||
relevantTouch.pageX;
|
||||
this.clientY = relevantTouch.clientY !== undefined ? relevantTouch.clientY :
|
||||
relevantTouch.pageY;
|
||||
this.screenX = relevantTouch.screenX || 0;
|
||||
this.screenY = relevantTouch.screenY || 0;
|
||||
} else {
|
||||
if (goog.events.USE_LAYER_XY_AS_OFFSET_XY) {
|
||||
this.offsetX = (e.layerX !== undefined) ? e.layerX : e.offsetX;
|
||||
this.offsetY = (e.layerY !== undefined) ? e.layerY : e.offsetY;
|
||||
} else {
|
||||
// Webkit emits a lame warning whenever layerX/layerY is accessed.
|
||||
// http://code.google.com/p/chromium/issues/detail?id=101733
|
||||
this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?
|
||||
e.offsetX :
|
||||
e.layerX;
|
||||
this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?
|
||||
e.offsetY :
|
||||
e.layerY;
|
||||
}
|
||||
this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
|
||||
this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
|
||||
this.screenX = e.screenX || 0;
|
||||
this.screenY = e.screenY || 0;
|
||||
}
|
||||
|
||||
this.button = e.button;
|
||||
|
||||
this.keyCode = e.keyCode || 0;
|
||||
this.key = e.key || '';
|
||||
this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
|
||||
this.ctrlKey = e.ctrlKey;
|
||||
this.altKey = e.altKey;
|
||||
this.shiftKey = e.shiftKey;
|
||||
this.metaKey = e.metaKey;
|
||||
this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
|
||||
this.pointerId = e.pointerId || 0;
|
||||
this.pointerType = goog.events.BrowserEvent.getPointerType_(e);
|
||||
this.state = e.state;
|
||||
this.event_ = e;
|
||||
if (e.defaultPrevented) {
|
||||
// Sync native event state to internal state via super class, where default
|
||||
// prevention is implemented and managed.
|
||||
goog.events.BrowserEvent.superClass_.preventDefault.call(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests to see which button was pressed during the event. This is really only
|
||||
* useful in IE and Gecko browsers. And in IE, it's only useful for
|
||||
* mousedown/mouseup events, because click only fires for the left mouse button.
|
||||
*
|
||||
* Safari 2 only reports the left button being clicked, and uses the value '1'
|
||||
* instead of 0. Opera only reports a mousedown event for the middle button, and
|
||||
* no mouse events for the right button. Opera has default behavior for left and
|
||||
* middle click that can only be overridden via a configuration setting.
|
||||
*
|
||||
* There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent.MouseButton} button The button
|
||||
* to test for.
|
||||
* @return {boolean} True if button was pressed.
|
||||
*/
|
||||
goog.events.BrowserEvent.prototype.isButton = function(button) {
|
||||
'use strict';
|
||||
return this.event_.button == button;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether this has an "action"-producing mouse button.
|
||||
*
|
||||
* By definition, this includes left-click on windows/linux, and left-click
|
||||
* without the ctrl key on Macs.
|
||||
*
|
||||
* @return {boolean} The result.
|
||||
*/
|
||||
goog.events.BrowserEvent.prototype.isMouseActionButton = function() {
|
||||
'use strict';
|
||||
// Ctrl+click should never behave like a left-click on mac, regardless of
|
||||
// whether or not the browser will actually ever emit such an event. If
|
||||
// we see it, treat it like right-click always.
|
||||
return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&
|
||||
!(goog.userAgent.MAC && this.ctrlKey);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.events.BrowserEvent.prototype.stopPropagation = function() {
|
||||
'use strict';
|
||||
goog.events.BrowserEvent.superClass_.stopPropagation.call(this);
|
||||
if (this.event_.stopPropagation) {
|
||||
this.event_.stopPropagation();
|
||||
} else {
|
||||
this.event_.cancelBubble = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.events.BrowserEvent.prototype.preventDefault = function() {
|
||||
'use strict';
|
||||
goog.events.BrowserEvent.superClass_.preventDefault.call(this);
|
||||
var be = this.event_;
|
||||
if (!be.preventDefault) {
|
||||
be.returnValue = false;
|
||||
} else {
|
||||
be.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Event} The underlying browser event object.
|
||||
*/
|
||||
goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
|
||||
'use strict';
|
||||
return this.event_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the pointer type from the given event.
|
||||
* @param {!Event} e
|
||||
* @return {string} The pointer type, e.g. 'mouse', 'pen', or 'touch'.
|
||||
* @private
|
||||
*/
|
||||
goog.events.BrowserEvent.getPointerType_ = function(e) {
|
||||
'use strict';
|
||||
if (typeof (e.pointerType) === 'string') {
|
||||
return e.pointerType;
|
||||
}
|
||||
// IE10 uses integer codes for pointer type.
|
||||
// https://msdn.microsoft.com/en-us/library/hh772359(v=vs.85).aspx
|
||||
return goog.events.BrowserEvent.IE_POINTER_TYPE_MAP[e.pointerType] || '';
|
||||
};
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Browser capability checks for the events package.
|
||||
*/
|
||||
|
||||
goog.module('goog.events.BrowserFeature');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
|
||||
/**
|
||||
* Tricks Closure Compiler into believing that a function is pure. The compiler
|
||||
* assumes that any `valueOf` function is pure, without analyzing its contents.
|
||||
*
|
||||
* @param {function(): T} fn
|
||||
* @return {T}
|
||||
* @template T
|
||||
*/
|
||||
const purify = (fn) => {
|
||||
return ({valueOf: fn}).valueOf();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enum of browser capabilities.
|
||||
* @enum {boolean}
|
||||
*/
|
||||
exports = {
|
||||
/**
|
||||
* Whether the button attribute of the event is W3C compliant. False in
|
||||
* Internet Explorer prior to version 9; document-version dependent.
|
||||
*/
|
||||
HAS_W3C_BUTTON: true,
|
||||
|
||||
/**
|
||||
* Whether the browser supports full W3C event model.
|
||||
*/
|
||||
HAS_W3C_EVENT_SUPPORT: true,
|
||||
|
||||
/**
|
||||
* To prevent default in IE7-8 for certain keydown events we need set the
|
||||
* keyCode to -1.
|
||||
*/
|
||||
SET_KEY_CODE_TO_PREVENT_DEFAULT: false,
|
||||
|
||||
/**
|
||||
* Whether the `navigator.onLine` property is supported.
|
||||
*/
|
||||
HAS_NAVIGATOR_ONLINE_PROPERTY: true,
|
||||
|
||||
/**
|
||||
* Whether HTML5 network online/offline events are supported.
|
||||
*/
|
||||
HAS_HTML5_NETWORK_EVENT_SUPPORT: true,
|
||||
|
||||
/**
|
||||
* Whether HTML5 network events fire on document.body, or otherwise the
|
||||
* window.
|
||||
*/
|
||||
HTML5_NETWORK_EVENTS_FIRE_ON_BODY: false,
|
||||
|
||||
/**
|
||||
* Whether touch is enabled in the browser.
|
||||
*/
|
||||
TOUCH_ENABLED:
|
||||
('ontouchstart' in goog.global ||
|
||||
!!(goog.global['document'] && document.documentElement &&
|
||||
'ontouchstart' in document.documentElement) ||
|
||||
// IE10 uses non-standard touch events, so it has a different check.
|
||||
!!(goog.global['navigator'] &&
|
||||
(goog.global['navigator']['maxTouchPoints'] ||
|
||||
goog.global['navigator']['msMaxTouchPoints']))),
|
||||
|
||||
/**
|
||||
* Whether addEventListener supports W3C standard pointer events.
|
||||
* http://www.w3.org/TR/pointerevents/
|
||||
*/
|
||||
POINTER_EVENTS: ('PointerEvent' in goog.global),
|
||||
|
||||
/**
|
||||
* Whether addEventListener supports MSPointer events (only used in IE10).
|
||||
* http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx
|
||||
* http://msdn.microsoft.com/library/hh673557(v=vs.85).aspx
|
||||
*/
|
||||
MSPOINTER_EVENTS:
|
||||
('MSPointerEvent' in goog.global &&
|
||||
!!(goog.global['navigator'] &&
|
||||
goog.global['navigator']['msPointerEnabled'])),
|
||||
|
||||
/**
|
||||
* Whether addEventListener supports {passive: true}.
|
||||
* https://developers.google.com/web/updates/2016/06/passive-event-listeners
|
||||
*/
|
||||
PASSIVE_EVENTS: purify(function() {
|
||||
// If we're in a web worker or other custom environment, we can't tell.
|
||||
if (!goog.global.addEventListener || !Object.defineProperty) { // IE 8
|
||||
return false;
|
||||
}
|
||||
|
||||
var passive = false;
|
||||
var options = Object.defineProperty({}, 'passive', {
|
||||
get: function() {
|
||||
passive = true;
|
||||
}
|
||||
});
|
||||
try {
|
||||
goog.global.addEventListener('test', goog.nullFunction, options);
|
||||
goog.global.removeEventListener('test', goog.nullFunction, options);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
return passive;
|
||||
})
|
||||
};
|
||||
Executable
+125
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A base class for event objects.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.events.Event');
|
||||
|
||||
/**
|
||||
* goog.events.Event no longer depends on goog.Disposable. Keep requiring
|
||||
* goog.Disposable here to not break projects which assume this dependency.
|
||||
* @suppress {extraRequire}
|
||||
*/
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.events.EventId');
|
||||
|
||||
|
||||
/**
|
||||
* A base class for event objects, so that they can support preventDefault and
|
||||
* stopPropagation.
|
||||
*
|
||||
* @param {string|!goog.events.EventId} type Event Type.
|
||||
* @param {Object=} opt_target Reference to the object that is the target of
|
||||
* this event. It has to implement the `EventTarget` interface
|
||||
* declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.
|
||||
* @constructor
|
||||
*/
|
||||
goog.events.Event = function(type, opt_target) {
|
||||
'use strict';
|
||||
/**
|
||||
* Event type.
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type instanceof goog.events.EventId ? String(type) : type;
|
||||
|
||||
/**
|
||||
* TODO(tbreisacher): The type should probably be
|
||||
* EventTarget|goog.events.EventTarget.
|
||||
*
|
||||
* Target of the event.
|
||||
* @type {Object|undefined}
|
||||
*/
|
||||
this.target = opt_target;
|
||||
|
||||
/**
|
||||
* Object that had the listener attached.
|
||||
* @type {Object|undefined}
|
||||
*/
|
||||
this.currentTarget = this.target;
|
||||
|
||||
/**
|
||||
* Whether to cancel the event in internal capture/bubble processing for IE.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.propagationStopped_ = false;
|
||||
|
||||
/**
|
||||
* Whether the default action has been prevented.
|
||||
* This is a property to match the W3C specification at
|
||||
* {@link http://www.w3.org/TR/DOM-Level-3-Events/
|
||||
* #events-event-type-defaultPrevented}.
|
||||
* Must be treated as read-only outside the class.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.defaultPrevented = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean} true iff internal propagation has been stopped.
|
||||
*/
|
||||
goog.events.Event.prototype.hasPropagationStopped = function() {
|
||||
'use strict';
|
||||
return this.propagationStopped_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops event propagation.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.events.Event.prototype.stopPropagation = function() {
|
||||
'use strict';
|
||||
this.propagationStopped_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Prevents the default action, for example a link redirecting to a url.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.events.Event.prototype.preventDefault = function() {
|
||||
'use strict';
|
||||
this.defaultPrevented = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops the propagation of the event. It is equivalent to
|
||||
* `e.stopPropagation()`, but can be used as the callback argument of
|
||||
* {@link goog.events.listen} without declaring another function.
|
||||
* @param {!goog.events.Event} e An event.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.events.Event.stopPropagation = function(e) {
|
||||
'use strict';
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Prevents the default action. It is equivalent to
|
||||
* `e.preventDefault()`, but can be used as the callback argument of
|
||||
* {@link goog.events.listen} without declaring another function.
|
||||
* @param {!goog.events.Event} e An event.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.events.Event.preventDefault = function(e) {
|
||||
'use strict';
|
||||
e.preventDefault();
|
||||
};
|
||||
Executable
+488
@@ -0,0 +1,488 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Class to create objects which want to handle multiple events
|
||||
* and have their listeners easily cleaned up via a dispose method.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* function Something() {
|
||||
* Something.base(this);
|
||||
*
|
||||
* ... set up object ...
|
||||
*
|
||||
* // Add event listeners
|
||||
* this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);
|
||||
* this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);
|
||||
* this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);
|
||||
* this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);
|
||||
* this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);
|
||||
* }
|
||||
* goog.inherits(Something, goog.events.EventHandler);
|
||||
*
|
||||
* Something.prototype.disposeInternal = function() {
|
||||
* Something.base(this, 'disposeInternal');
|
||||
* goog.dom.removeNode(this.container);
|
||||
* };
|
||||
*
|
||||
*
|
||||
* // Then elsewhere:
|
||||
*
|
||||
* var activeSomething = null;
|
||||
* function openSomething() {
|
||||
* activeSomething = new Something();
|
||||
* }
|
||||
*
|
||||
* function closeSomething() {
|
||||
* if (activeSomething) {
|
||||
* activeSomething.dispose(); // Remove event listeners
|
||||
* activeSomething = null;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.EventHandler');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.object');
|
||||
goog.requireType('goog.events.Event');
|
||||
goog.requireType('goog.events.EventId');
|
||||
goog.requireType('goog.events.EventTarget');
|
||||
goog.requireType('goog.events.EventWrapper');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Super class for objects that want to easily manage a number of event
|
||||
* listeners. It allows a short cut to listen and also provides a quick way
|
||||
* to remove all events listeners belonging to this object.
|
||||
* @param {SCOPE=} opt_scope Object in whose scope to call the listeners.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @template SCOPE
|
||||
*/
|
||||
goog.events.EventHandler = function(opt_scope) {
|
||||
'use strict';
|
||||
goog.Disposable.call(this);
|
||||
// TODO(mknichel): Rename this to this.scope_ and fix the classes in google3
|
||||
// that access this private variable. :(
|
||||
this.handler_ = opt_scope;
|
||||
|
||||
/**
|
||||
* Keys for events that are being listened to.
|
||||
* @type {!Object<!goog.events.Key>}
|
||||
* @private
|
||||
*/
|
||||
this.keys_ = {};
|
||||
};
|
||||
goog.inherits(goog.events.EventHandler, goog.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* Utility array used to unify the cases of listening for an array of types
|
||||
* and listening for a single event, without using recursion or allocating
|
||||
* an array each time.
|
||||
* @type {!Array<string>}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventHandler.typeArray_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Listen to an event on a Listenable. If the function is omitted then the
|
||||
* EventHandler's handleEvent method will be used.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type to listen for or array of event types.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
|
||||
* opt_fn Optional callback function to be used as the listener or an object
|
||||
* with handleEvent function.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template EVENTOBJ, THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listen = function(
|
||||
src, type, opt_fn, opt_options) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
return self.listen_(src, type, opt_fn, opt_options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Listen to an event on a Listenable. If the function is omitted then the
|
||||
* EventHandler's handleEvent method will be used.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type to listen for or array of event types.
|
||||
* @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
|
||||
* null|undefined} fn Optional callback function to be used as the
|
||||
* listener or an object with handleEvent function.
|
||||
* @param {boolean|!AddEventListenerOptions|undefined} options
|
||||
* @param {T} scope Object in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template T, EVENTOBJ, THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenWithScope = function(
|
||||
src, type, fn, options, scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
// TODO(mknichel): Deprecate this function.
|
||||
return self.listen_(src, type, fn, options, scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Listen to an event on a Listenable. If the function is omitted then the
|
||||
* EventHandler's handleEvent method will be used.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type to listen for or array of event types.
|
||||
* @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
|
||||
* Optional callback function to be used as the listener or an object with
|
||||
* handleEvent function.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @param {Object=} opt_scope Object in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template EVENTOBJ, THIS
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listen_ = function(
|
||||
src, type, opt_fn, opt_options, opt_scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
if (!Array.isArray(type)) {
|
||||
if (type) {
|
||||
goog.events.EventHandler.typeArray_[0] = type.toString();
|
||||
}
|
||||
type = goog.events.EventHandler.typeArray_;
|
||||
}
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
var listenerObj = goog.events.listen(
|
||||
src, type[i], opt_fn || self.handleEvent, opt_options || false,
|
||||
opt_scope || self.handler_ || self);
|
||||
|
||||
if (!listenerObj) {
|
||||
// When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
|
||||
// (goog.events.CaptureSimulationMode) in IE8-, it will return null
|
||||
// value.
|
||||
return self;
|
||||
}
|
||||
|
||||
var key = listenerObj.key;
|
||||
self.keys_[key] = listenerObj;
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Listen to an event on a Listenable. If the function is omitted, then the
|
||||
* EventHandler's handleEvent method will be used. After the event has fired the
|
||||
* event listener is removed from the target. If an array of event types is
|
||||
* provided, each event type will be listened to once.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type to listen for or array of event types.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
|
||||
* opt_fn
|
||||
* Optional callback function to be used as the listener or an object with
|
||||
* handleEvent function.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template EVENTOBJ, THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenOnce = function(
|
||||
src, type, opt_fn, opt_options) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
return self.listenOnce_(src, type, opt_fn, opt_options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Listen to an event on a Listenable. If the function is omitted, then the
|
||||
* EventHandler's handleEvent method will be used. After the event has fired the
|
||||
* event listener is removed from the target. If an array of event types is
|
||||
* provided, each event type will be listened to once.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type to listen for or array of event types.
|
||||
* @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
|
||||
* null|undefined} fn Optional callback function to be used as the
|
||||
* listener or an object with handleEvent function.
|
||||
* @param {boolean|undefined} capture Optional whether to use capture phase.
|
||||
* @param {T} scope Object in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template T, EVENTOBJ, THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenOnceWithScope = function(
|
||||
src, type, fn, capture, scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
// TODO(mknichel): Deprecate this function.
|
||||
return self.listenOnce_(src, type, fn, capture, scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Listen to an event on a Listenable. If the function is omitted, then the
|
||||
* EventHandler's handleEvent method will be used. After the event has fired
|
||||
* the event listener is removed from the target. If an array of event types is
|
||||
* provided, each event type will be listened to once.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type to listen for or array of event types.
|
||||
* @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
|
||||
* Optional callback function to be used as the listener or an object with
|
||||
* handleEvent function.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @param {Object=} opt_scope Object in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template EVENTOBJ, THIS
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenOnce_ = function(
|
||||
src, type, opt_fn, opt_options, opt_scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
if (Array.isArray(type)) {
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
self.listenOnce_(src, type[i], opt_fn, opt_options, opt_scope);
|
||||
}
|
||||
} else {
|
||||
var listenerObj = goog.events.listenOnce(
|
||||
src, type, opt_fn || self.handleEvent, opt_options,
|
||||
opt_scope || self.handler_ || self);
|
||||
if (!listenerObj) {
|
||||
// When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
|
||||
// (goog.events.CaptureSimulationMode) in IE8-, it will return null
|
||||
// value.
|
||||
return self;
|
||||
}
|
||||
|
||||
var key = listenerObj.key;
|
||||
self.keys_[key] = listenerObj;
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener with a specific event wrapper on a DOM Node or an
|
||||
* object that has implemented {@link goog.events.EventTarget}. A listener can
|
||||
* only be added once to an object.
|
||||
*
|
||||
* @param {EventTarget|goog.events.EventTarget} src The node to listen to
|
||||
* events on.
|
||||
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
|
||||
* @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener
|
||||
* Callback method, or an object with a handleEvent function.
|
||||
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
|
||||
* false).
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenWithWrapper = function(
|
||||
src, wrapper, listener, opt_capt) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
// TODO(mknichel): Remove the opt_scope from this function and then
|
||||
// templatize it.
|
||||
return self.listenWithWrapper_(src, wrapper, listener, opt_capt);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener with a specific event wrapper on a DOM Node or an
|
||||
* object that has implemented {@link goog.events.EventTarget}. A listener can
|
||||
* only be added once to an object.
|
||||
*
|
||||
* @param {EventTarget|goog.events.EventTarget} src The node to listen to
|
||||
* events on.
|
||||
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
|
||||
* @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}
|
||||
* listener Optional callback function to be used as the
|
||||
* listener or an object with handleEvent function.
|
||||
* @param {boolean|undefined} capture Optional whether to use capture phase.
|
||||
* @param {T} scope Object in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template T, THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(
|
||||
src, wrapper, listener, capture, scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
// TODO(mknichel): Deprecate this function.
|
||||
return self.listenWithWrapper_(src, wrapper, listener, capture, scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener with a specific event wrapper on a DOM Node or an
|
||||
* object that has implemented {@link goog.events.EventTarget}. A listener can
|
||||
* only be added once to an object.
|
||||
*
|
||||
* @param {EventTarget|goog.events.EventTarget} src The node to listen to
|
||||
* events on.
|
||||
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
|
||||
* method, or an object with a handleEvent function.
|
||||
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
|
||||
* false).
|
||||
* @param {Object=} opt_scope Element in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template THIS
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventHandler.prototype.listenWithWrapper_ = function(
|
||||
src, wrapper, listener, opt_capt, opt_scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
wrapper.listen(
|
||||
src, listener, opt_capt, opt_scope || self.handler_ || self, self);
|
||||
return self;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Number of listeners registered by this handler.
|
||||
*/
|
||||
goog.events.EventHandler.prototype.getListenerCount = function() {
|
||||
'use strict';
|
||||
var count = 0;
|
||||
for (var key in this.keys_) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unlistens on an event.
|
||||
* @param {goog.events.ListenableType} src Event source.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type or array of event types to unlisten to.
|
||||
* @param {function(this:?, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
|
||||
* opt_fn Optional callback function to be used as the listener or an object
|
||||
* with handleEvent function.
|
||||
* @param {(boolean|!EventListenerOptions)=} opt_options
|
||||
* @param {Object=} opt_scope Object in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template EVENTOBJ, THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.unlisten = function(
|
||||
src, type, opt_fn, opt_options, opt_scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
if (Array.isArray(type)) {
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
self.unlisten(src, type[i], opt_fn, opt_options, opt_scope);
|
||||
}
|
||||
} else {
|
||||
var capture =
|
||||
goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
|
||||
var listener = goog.events.getListener(
|
||||
src, type, opt_fn || self.handleEvent, capture,
|
||||
opt_scope || self.handler_ || self);
|
||||
|
||||
if (listener) {
|
||||
goog.events.unlistenByKey(listener);
|
||||
delete self.keys_[listener.key];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener which was added with listenWithWrapper().
|
||||
*
|
||||
* @param {EventTarget|goog.events.EventTarget} src The target to stop
|
||||
* listening to events on.
|
||||
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} listener The
|
||||
* listener function to remove.
|
||||
* @param {boolean=} opt_capt In DOM-compliant browsers, this determines
|
||||
* whether the listener is fired during the capture or bubble phase of the
|
||||
* event.
|
||||
* @param {Object=} opt_scope Element in whose scope to call the listener.
|
||||
* @return {THIS} This object, allowing for chaining of calls.
|
||||
* @this {THIS}
|
||||
* @template THIS
|
||||
*/
|
||||
goog.events.EventHandler.prototype.unlistenWithWrapper = function(
|
||||
src, wrapper, listener, opt_capt, opt_scope) {
|
||||
'use strict';
|
||||
var self = /** @type {!goog.events.EventHandler} */ (this);
|
||||
wrapper.unlisten(
|
||||
src, listener, opt_capt, opt_scope || self.handler_ || self, self);
|
||||
return self;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unlistens to all events.
|
||||
*/
|
||||
goog.events.EventHandler.prototype.removeAll = function() {
|
||||
'use strict';
|
||||
goog.object.forEach(this.keys_, function(listenerObj, key) {
|
||||
'use strict';
|
||||
if (this.keys_.hasOwnProperty(key)) {
|
||||
goog.events.unlistenByKey(listenerObj);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.keys_ = {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of this EventHandler and removes all listeners that it registered.
|
||||
* @override
|
||||
* @protected
|
||||
*/
|
||||
goog.events.EventHandler.prototype.disposeInternal = function() {
|
||||
'use strict';
|
||||
goog.events.EventHandler.superClass_.disposeInternal.call(this);
|
||||
this.removeAll();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default event handler
|
||||
* @param {goog.events.Event} e Event object.
|
||||
*/
|
||||
goog.events.EventHandler.prototype.handleEvent = function(e) {
|
||||
'use strict';
|
||||
throw new Error('EventHandler.handleEvent not implemented');
|
||||
};
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.EventId');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A templated class that is used when registering for events. Typical usage:
|
||||
*
|
||||
* /** @type {goog.events.EventId<MyEventObj>} *\
|
||||
* var myEventId = new goog.events.EventId(
|
||||
* goog.events.getUniqueId(('someEvent'));
|
||||
*
|
||||
* // No need to cast or declare here since the compiler knows the
|
||||
* // correct type of 'evt' (MyEventObj).
|
||||
* something.listen(myEventId, function(evt) {});
|
||||
*
|
||||
* @param {string} eventId
|
||||
* @template T
|
||||
* @constructor
|
||||
* @struct
|
||||
* @final
|
||||
*/
|
||||
goog.events.EventId = function(eventId) {
|
||||
'use strict';
|
||||
/** @const */ this.id = eventId;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @return {string}
|
||||
*/
|
||||
goog.events.EventId.prototype.toString = function() {
|
||||
'use strict';
|
||||
return this.id;
|
||||
};
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A typedef for event like objects that are dispatchable via the
|
||||
* goog.events.dispatchEvent function.
|
||||
*/
|
||||
goog.provide('goog.events.EventLike');
|
||||
|
||||
goog.requireType('goog.events.Event');
|
||||
goog.requireType('goog.events.EventId');
|
||||
|
||||
/**
|
||||
* A typedef for event like objects that are dispatchable via the
|
||||
* goog.events.dispatchEvent function. strings are treated as the type for a
|
||||
* goog.events.Event. Objects are treated as an extension of a new
|
||||
* goog.events.Event with the type property of the object being used as the type
|
||||
* of the Event.
|
||||
* @typedef {string|Object|goog.events.Event|goog.events.EventId}
|
||||
*/
|
||||
goog.events.EventLike;
|
||||
Executable
+960
@@ -0,0 +1,960 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview An event manager for both native browser event
|
||||
* targets and custom JavaScript event targets
|
||||
* (`goog.events.Listenable`). This provides an abstraction
|
||||
* over browsers' event systems.
|
||||
*
|
||||
* It also provides a simulation of W3C event model's capture phase in
|
||||
* Internet Explorer (IE 8 and below). Caveat: the simulation does not
|
||||
* interact well with listeners registered directly on the elements
|
||||
* (bypassing goog.events) or even with listeners registered via
|
||||
* goog.events in a separate JS binary. In these cases, we provide
|
||||
* no ordering guarantees.
|
||||
*
|
||||
* The listeners will receive a "patched" event object. Such event object
|
||||
* contains normalized values for certain event properties that differs in
|
||||
* different browsers.
|
||||
*
|
||||
* Example usage:
|
||||
* <pre>
|
||||
* goog.events.listen(myNode, 'click', function(e) { alert('woo') });
|
||||
* goog.events.listen(myNode, 'mouseover', mouseHandler, true);
|
||||
* goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);
|
||||
* goog.events.removeAll(myNode);
|
||||
* </pre>
|
||||
*
|
||||
* in IE and event object patching]
|
||||
*
|
||||
* @see ../demos/events.html
|
||||
* @see ../demos/event-propagation.html
|
||||
* @see ../demos/stopevent.html
|
||||
*/
|
||||
|
||||
// IMPLEMENTATION NOTES:
|
||||
// goog.events stores an auxiliary data structure on each EventTarget
|
||||
// source being listened on. This allows us to take advantage of GC,
|
||||
// having the data structure GC'd when the EventTarget is GC'd. This
|
||||
// GC behavior is equivalent to using W3C DOM Events directly.
|
||||
|
||||
goog.provide('goog.events');
|
||||
goog.provide('goog.events.CaptureSimulationMode');
|
||||
goog.provide('goog.events.Key');
|
||||
goog.provide('goog.events.ListenableType');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug.entryPointRegistry');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.events.BrowserFeature');
|
||||
goog.require('goog.events.Listenable');
|
||||
goog.require('goog.events.ListenerMap');
|
||||
goog.requireType('goog.debug.ErrorHandler');
|
||||
goog.requireType('goog.events.EventId');
|
||||
goog.requireType('goog.events.EventLike');
|
||||
goog.requireType('goog.events.EventWrapper');
|
||||
goog.requireType('goog.events.ListenableKey');
|
||||
goog.requireType('goog.events.Listener');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {number|goog.events.ListenableKey}
|
||||
*/
|
||||
goog.events.Key;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {EventTarget|goog.events.Listenable}
|
||||
*/
|
||||
goog.events.ListenableType;
|
||||
|
||||
|
||||
/**
|
||||
* Property name on a native event target for the listener map
|
||||
* associated with the event target.
|
||||
* @private @const {string}
|
||||
*/
|
||||
goog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);
|
||||
|
||||
|
||||
/**
|
||||
* String used to prepend to IE event types.
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
goog.events.onString_ = 'on';
|
||||
|
||||
|
||||
/**
|
||||
* Map of computed "on<eventname>" strings for IE event types. Caching
|
||||
* this removes an extra object allocation in goog.events.listen which
|
||||
* improves IE6 performance.
|
||||
* @const
|
||||
* @dict
|
||||
* @private
|
||||
*/
|
||||
goog.events.onStringMap_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number} Different capture simulation mode for IE8-.
|
||||
*/
|
||||
goog.events.CaptureSimulationMode = {
|
||||
/**
|
||||
* Does not perform capture simulation. Will asserts in IE8- when you
|
||||
* add capture listeners.
|
||||
*/
|
||||
OFF_AND_FAIL: 0,
|
||||
|
||||
/**
|
||||
* Does not perform capture simulation, silently ignore capture
|
||||
* listeners.
|
||||
*/
|
||||
OFF_AND_SILENT: 1,
|
||||
|
||||
/**
|
||||
* Performs capture simulation.
|
||||
*/
|
||||
ON: 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} The capture simulation mode for IE8-. By default,
|
||||
* this is ON.
|
||||
*/
|
||||
goog.events.CAPTURE_SIMULATION_MODE =
|
||||
goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);
|
||||
|
||||
|
||||
/**
|
||||
* Estimated count of total native listeners.
|
||||
* @private {number}
|
||||
*/
|
||||
goog.events.listenerCountEstimate_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener for a specific event on a native event
|
||||
* target (such as a DOM element) or an object that has implemented
|
||||
* {@link goog.events.Listenable}. A listener can only be added once
|
||||
* to an object and if it is added again the key for the listener is
|
||||
* returned. Note that if the existing listener is a one-off listener
|
||||
* (registered via listenOnce), it will no longer be a one-off
|
||||
* listener after a call to listen().
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} src The node to listen
|
||||
* to events on.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type or array of event types.
|
||||
* @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
|
||||
* listener Callback method, or an object with a handleEvent function.
|
||||
* WARNING: passing an Object is now softly deprecated.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @param {T=} opt_handler Element in whose scope to call the listener.
|
||||
* @return {goog.events.Key} Unique key for the listener.
|
||||
* @template T,EVENTOBJ
|
||||
*/
|
||||
goog.events.listen = function(src, type, listener, opt_options, opt_handler) {
|
||||
'use strict';
|
||||
if (opt_options && opt_options.once) {
|
||||
return goog.events.listenOnce(
|
||||
src, type, listener, opt_options, opt_handler);
|
||||
}
|
||||
if (Array.isArray(type)) {
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
goog.events.listen(src, type[i], listener, opt_options, opt_handler);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
listener = goog.events.wrapListener(listener);
|
||||
if (goog.events.Listenable.isImplementedBy(src)) {
|
||||
var capture =
|
||||
goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
|
||||
return src.listen(
|
||||
/** @type {string|!goog.events.EventId} */ (type), listener, capture,
|
||||
opt_handler);
|
||||
} else {
|
||||
return goog.events.listen_(
|
||||
/** @type {!EventTarget} */ (src), type, listener,
|
||||
/* callOnce */ false, opt_options, opt_handler);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener for a specific event on a native event
|
||||
* target. A listener can only be added once to an object and if it
|
||||
* is added again the key for the listener is returned.
|
||||
*
|
||||
* Note that a one-off listener will not change an existing listener,
|
||||
* if any. On the other hand a normal listener will change existing
|
||||
* one-off listener to become a normal listener.
|
||||
*
|
||||
* @param {EventTarget} src The node to listen to events on.
|
||||
* @param {string|?goog.events.EventId<EVENTOBJ>} type Event type.
|
||||
* @param {!Function} listener Callback function.
|
||||
* @param {boolean} callOnce Whether the listener is a one-off
|
||||
* listener or otherwise.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @param {Object=} opt_handler Element in whose scope to call the listener.
|
||||
* @return {goog.events.ListenableKey} Unique key for the listener.
|
||||
* @template EVENTOBJ
|
||||
* @private
|
||||
*/
|
||||
goog.events.listen_ = function(
|
||||
src, type, listener, callOnce, opt_options, opt_handler) {
|
||||
'use strict';
|
||||
if (!type) {
|
||||
throw new Error('Invalid event type');
|
||||
}
|
||||
|
||||
var capture =
|
||||
goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(src);
|
||||
if (!listenerMap) {
|
||||
src[goog.events.LISTENER_MAP_PROP_] = listenerMap =
|
||||
new goog.events.ListenerMap(src);
|
||||
}
|
||||
|
||||
var listenerObj = /** @type {goog.events.Listener} */ (
|
||||
listenerMap.add(type, listener, callOnce, capture, opt_handler));
|
||||
|
||||
// If the listenerObj already has a proxy, it has been set up
|
||||
// previously. We simply return.
|
||||
if (listenerObj.proxy) {
|
||||
return listenerObj;
|
||||
}
|
||||
|
||||
var proxy = goog.events.getProxy();
|
||||
listenerObj.proxy = proxy;
|
||||
|
||||
proxy.src = src;
|
||||
proxy.listener = listenerObj;
|
||||
|
||||
// Attach the proxy through the browser's API
|
||||
if (src.addEventListener) {
|
||||
// Don't pass an object as `capture` if the browser doesn't support that.
|
||||
if (!goog.events.BrowserFeature.PASSIVE_EVENTS) {
|
||||
opt_options = capture;
|
||||
}
|
||||
// Don't break tests that expect a boolean.
|
||||
if (opt_options === undefined) opt_options = false;
|
||||
src.addEventListener(type.toString(), proxy, opt_options);
|
||||
} else if (src.attachEvent) {
|
||||
// The else if above used to be an unconditional else. It would call
|
||||
// attachEvent come gws or high water. This would sometimes throw an
|
||||
// exception on IE11, spoiling the day of some callers. The previous
|
||||
// incarnation of this code, from 2007, indicates that it replaced an
|
||||
// earlier still version that caused excess allocations on IE6.
|
||||
src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
|
||||
} else if (src.addListener && src.removeListener) {
|
||||
// In IE, MediaQueryList uses addListener() insteadd of addEventListener. In
|
||||
// Safari, there is no global for the MediaQueryList constructor, so we just
|
||||
// check whether the object "looks like" MediaQueryList.
|
||||
goog.asserts.assert(
|
||||
type === 'change', 'MediaQueryList only has a change event');
|
||||
src.addListener(proxy);
|
||||
} else {
|
||||
throw new Error('addEventListener and attachEvent are unavailable.');
|
||||
}
|
||||
|
||||
goog.events.listenerCountEstimate_++;
|
||||
return listenerObj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for returning a proxy function.
|
||||
* @return {!Function} A new or reused function object.
|
||||
*/
|
||||
goog.events.getProxy = function() {
|
||||
'use strict';
|
||||
const proxyCallbackFunction = goog.events.handleBrowserEvent_;
|
||||
const f = function(eventObject) {
|
||||
return proxyCallbackFunction.call(f.src, f.listener, eventObject);
|
||||
};
|
||||
return f;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener for a specific event on a native event
|
||||
* target (such as a DOM element) or an object that has implemented
|
||||
* {@link goog.events.Listenable}. After the event has fired the event
|
||||
* listener is removed from the target.
|
||||
*
|
||||
* If an existing listener already exists, listenOnce will do
|
||||
* nothing. In particular, if the listener was previously registered
|
||||
* via listen(), listenOnce() will not turn the listener into a
|
||||
* one-off listener. Similarly, if there is already an existing
|
||||
* one-off listener, listenOnce does not modify the listeners (it is
|
||||
* still a once listener).
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} src The node to listen
|
||||
* to events on.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type or array of event types.
|
||||
* @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
|
||||
* listener Callback method.
|
||||
* @param {(boolean|!AddEventListenerOptions)=} opt_options
|
||||
* @param {T=} opt_handler Element in whose scope to call the listener.
|
||||
* @return {goog.events.Key} Unique key for the listener.
|
||||
* @template T,EVENTOBJ
|
||||
*/
|
||||
goog.events.listenOnce = function(
|
||||
src, type, listener, opt_options, opt_handler) {
|
||||
'use strict';
|
||||
if (Array.isArray(type)) {
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
goog.events.listenOnce(src, type[i], listener, opt_options, opt_handler);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
listener = goog.events.wrapListener(listener);
|
||||
if (goog.events.Listenable.isImplementedBy(src)) {
|
||||
var capture =
|
||||
goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
|
||||
return src.listenOnce(
|
||||
/** @type {string|!goog.events.EventId} */ (type), listener, capture,
|
||||
opt_handler);
|
||||
} else {
|
||||
return goog.events.listen_(
|
||||
/** @type {!EventTarget} */ (src), type, listener,
|
||||
/* callOnce */ true, opt_options, opt_handler);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener with a specific event wrapper on a DOM Node or an
|
||||
* object that has implemented {@link goog.events.Listenable}. A listener can
|
||||
* only be added once to an object.
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} src The target to
|
||||
* listen to events on.
|
||||
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
|
||||
* @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener
|
||||
* Callback method, or an object with a handleEvent function.
|
||||
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
|
||||
* false).
|
||||
* @param {T=} opt_handler Element in whose scope to call the listener.
|
||||
* @template T
|
||||
*/
|
||||
goog.events.listenWithWrapper = function(
|
||||
src, wrapper, listener, opt_capt, opt_handler) {
|
||||
'use strict';
|
||||
wrapper.listen(src, listener, opt_capt, opt_handler);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener which was added with listen().
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} src The target to stop
|
||||
* listening to events on.
|
||||
* @param {string|Array<string>|
|
||||
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
|
||||
* type Event type or array of event types to unlisten to.
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} listener The
|
||||
* listener function to remove.
|
||||
* @param {(boolean|!EventListenerOptions)=} opt_options
|
||||
* whether the listener is fired during the capture or bubble phase of the
|
||||
* event.
|
||||
* @param {Object=} opt_handler Element in whose scope to call the listener.
|
||||
* @return {?boolean} indicating whether the listener was there to remove.
|
||||
* @template EVENTOBJ
|
||||
*/
|
||||
goog.events.unlisten = function(src, type, listener, opt_options, opt_handler) {
|
||||
'use strict';
|
||||
if (Array.isArray(type)) {
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
goog.events.unlisten(src, type[i], listener, opt_options, opt_handler);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var capture =
|
||||
goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
|
||||
|
||||
listener = goog.events.wrapListener(listener);
|
||||
if (goog.events.Listenable.isImplementedBy(src)) {
|
||||
return src.unlisten(
|
||||
/** @type {string|!goog.events.EventId} */ (type), listener, capture,
|
||||
opt_handler);
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
// TODO(chrishenry): We should tighten the API to only accept
|
||||
// non-null objects, or add an assertion here.
|
||||
return false;
|
||||
}
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {!EventTarget} */ (src));
|
||||
if (listenerMap) {
|
||||
var listenerObj = listenerMap.getListener(
|
||||
/** @type {string|!goog.events.EventId} */ (type), listener, capture,
|
||||
opt_handler);
|
||||
if (listenerObj) {
|
||||
return goog.events.unlistenByKey(listenerObj);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener which was added with listen() by the key
|
||||
* returned by listen().
|
||||
*
|
||||
* @param {goog.events.Key} key The key returned by listen() for this
|
||||
* event listener.
|
||||
* @return {boolean} indicating whether the listener was there to remove.
|
||||
*/
|
||||
goog.events.unlistenByKey = function(key) {
|
||||
'use strict';
|
||||
// TODO(chrishenry): Remove this check when tests that rely on this
|
||||
// are fixed.
|
||||
if (typeof key === 'number') {
|
||||
return false;
|
||||
}
|
||||
|
||||
var listener = key;
|
||||
if (!listener || listener.removed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var src = listener.src;
|
||||
if (goog.events.Listenable.isImplementedBy(src)) {
|
||||
return /** @type {!goog.events.Listenable} */ (src).unlistenByKey(listener);
|
||||
}
|
||||
|
||||
var type = listener.type;
|
||||
var proxy = listener.proxy;
|
||||
if (src.removeEventListener) {
|
||||
src.removeEventListener(type, proxy, listener.capture);
|
||||
} else if (src.detachEvent) {
|
||||
src.detachEvent(goog.events.getOnString_(type), proxy);
|
||||
} else if (src.addListener && src.removeListener) {
|
||||
src.removeListener(proxy);
|
||||
}
|
||||
goog.events.listenerCountEstimate_--;
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {!EventTarget} */ (src));
|
||||
// TODO(chrishenry): Try to remove this conditional and execute the
|
||||
// first branch always. This should be safe.
|
||||
if (listenerMap) {
|
||||
listenerMap.removeByKey(listener);
|
||||
if (listenerMap.getTypeCount() == 0) {
|
||||
// Null the src, just because this is simple to do (and useful
|
||||
// for IE <= 7).
|
||||
listenerMap.src = null;
|
||||
// We don't use delete here because IE does not allow delete
|
||||
// on a window object.
|
||||
src[goog.events.LISTENER_MAP_PROP_] = null;
|
||||
}
|
||||
} else {
|
||||
/** @type {!goog.events.Listener} */ (listener).markAsRemoved();
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener which was added with listenWithWrapper().
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} src The target to stop
|
||||
* listening to events on.
|
||||
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} listener The
|
||||
* listener function to remove.
|
||||
* @param {boolean=} opt_capt In DOM-compliant browsers, this determines
|
||||
* whether the listener is fired during the capture or bubble phase of the
|
||||
* event.
|
||||
* @param {Object=} opt_handler Element in whose scope to call the listener.
|
||||
*/
|
||||
goog.events.unlistenWithWrapper = function(
|
||||
src, wrapper, listener, opt_capt, opt_handler) {
|
||||
'use strict';
|
||||
wrapper.unlisten(src, listener, opt_capt, opt_handler);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all listeners from an object. You can also optionally
|
||||
* remove listeners of a particular type.
|
||||
*
|
||||
* @param {Object|undefined} obj Object to remove listeners from. Must be an
|
||||
* EventTarget or a goog.events.Listenable.
|
||||
* @param {string|!goog.events.EventId=} opt_type Type of event to remove.
|
||||
* Default is all types.
|
||||
* @return {number} Number of listeners removed.
|
||||
*/
|
||||
goog.events.removeAll = function(obj, opt_type) {
|
||||
'use strict';
|
||||
// TODO(chrishenry): Change the type of obj to
|
||||
// (!EventTarget|!goog.events.Listenable).
|
||||
|
||||
if (!obj) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (goog.events.Listenable.isImplementedBy(obj)) {
|
||||
return /** @type {?} */ (obj).removeAllListeners(opt_type);
|
||||
}
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {!EventTarget} */ (obj));
|
||||
if (!listenerMap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var typeStr = opt_type && opt_type.toString();
|
||||
for (var type in listenerMap.listeners) {
|
||||
if (!typeStr || type == typeStr) {
|
||||
// Clone so that we don't need to worry about unlistenByKey
|
||||
// changing the content of the ListenerMap.
|
||||
var listeners = listenerMap.listeners[type].concat();
|
||||
for (var i = 0; i < listeners.length; ++i) {
|
||||
if (goog.events.unlistenByKey(listeners[i])) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the listeners for a given object, type and capture phase.
|
||||
*
|
||||
* @param {Object} obj Object to get listeners for.
|
||||
* @param {string|!goog.events.EventId} type Event type.
|
||||
* @param {boolean} capture Capture phase?.
|
||||
* @return {!Array<!goog.events.Listener>} Array of listener objects.
|
||||
*/
|
||||
goog.events.getListeners = function(obj, type, capture) {
|
||||
'use strict';
|
||||
if (goog.events.Listenable.isImplementedBy(obj)) {
|
||||
return /** @type {!goog.events.Listenable} */ (obj).getListeners(
|
||||
type, capture);
|
||||
} else {
|
||||
if (!obj) {
|
||||
// TODO(chrishenry): We should tighten the API to accept
|
||||
// !EventTarget|goog.events.Listenable, and add an assertion here.
|
||||
return [];
|
||||
}
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {!EventTarget} */ (obj));
|
||||
return listenerMap ? listenerMap.getListeners(type, capture) : [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the goog.events.Listener for the event or null if no such listener is
|
||||
* in use.
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} src The target from
|
||||
* which to get listeners.
|
||||
* @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.
|
||||
* @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The
|
||||
* listener function to get.
|
||||
* @param {boolean=} opt_capt In DOM-compliant browsers, this determines
|
||||
* whether the listener is fired during the
|
||||
* capture or bubble phase of the event.
|
||||
* @param {Object=} opt_handler Element in whose scope to call the listener.
|
||||
* @return {goog.events.ListenableKey} the found listener or null if not found.
|
||||
* @template EVENTOBJ
|
||||
*/
|
||||
goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {
|
||||
'use strict';
|
||||
// TODO(chrishenry): Change type from ?string to string, or add assertion.
|
||||
type = /** @type {string} */ (type);
|
||||
listener = goog.events.wrapListener(listener);
|
||||
var capture = !!opt_capt;
|
||||
if (goog.events.Listenable.isImplementedBy(src)) {
|
||||
return src.getListener(type, listener, capture, opt_handler);
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
// TODO(chrishenry): We should tighten the API to only accept
|
||||
// non-null objects, or add an assertion here.
|
||||
return null;
|
||||
}
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {!EventTarget} */ (src));
|
||||
if (listenerMap) {
|
||||
return listenerMap.getListener(type, listener, capture, opt_handler);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether an event target has any active listeners matching the
|
||||
* specified signature. If either the type or capture parameters are
|
||||
* unspecified, the function will match on the remaining criteria.
|
||||
*
|
||||
* @param {EventTarget|goog.events.Listenable} obj Target to get
|
||||
* listeners for.
|
||||
* @param {string|!goog.events.EventId=} opt_type Event type.
|
||||
* @param {boolean=} opt_capture Whether to check for capture or bubble-phase
|
||||
* listeners.
|
||||
* @return {boolean} Whether an event target has one or more listeners matching
|
||||
* the requested type and/or capture phase.
|
||||
*/
|
||||
goog.events.hasListener = function(obj, opt_type, opt_capture) {
|
||||
'use strict';
|
||||
if (goog.events.Listenable.isImplementedBy(obj)) {
|
||||
return obj.hasListener(opt_type, opt_capture);
|
||||
}
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {!EventTarget} */ (obj));
|
||||
return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Provides a nice string showing the normalized event objects public members
|
||||
* @param {Object} e Event Object.
|
||||
* @return {string} String of the public members of the normalized event object.
|
||||
*/
|
||||
goog.events.expose = function(e) {
|
||||
'use strict';
|
||||
var str = [];
|
||||
for (var key in e) {
|
||||
if (e[key] && e[key].id) {
|
||||
str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');
|
||||
} else {
|
||||
str.push(key + ' = ' + e[key]);
|
||||
}
|
||||
}
|
||||
return str.join('\n');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string with on prepended to the specified type. This is used for IE
|
||||
* which expects "on" to be prepended. This function caches the string in order
|
||||
* to avoid extra allocations in steady state.
|
||||
* @param {string} type Event type.
|
||||
* @return {string} The type string with 'on' prepended.
|
||||
* @private
|
||||
*/
|
||||
goog.events.getOnString_ = function(type) {
|
||||
'use strict';
|
||||
if (type in goog.events.onStringMap_) {
|
||||
return goog.events.onStringMap_[type];
|
||||
}
|
||||
return goog.events.onStringMap_[type] = goog.events.onString_ + type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires an object's listeners of a particular type and phase
|
||||
*
|
||||
* @param {Object} obj Object whose listeners to call.
|
||||
* @param {string|!goog.events.EventId} type Event type.
|
||||
* @param {boolean} capture Which event phase.
|
||||
* @param {Object} eventObject Event object to be passed to listener.
|
||||
* @return {boolean} True if all listeners returned true else false.
|
||||
*/
|
||||
goog.events.fireListeners = function(obj, type, capture, eventObject) {
|
||||
'use strict';
|
||||
if (goog.events.Listenable.isImplementedBy(obj)) {
|
||||
return /** @type {!goog.events.Listenable} */ (obj).fireListeners(
|
||||
type, capture, eventObject);
|
||||
}
|
||||
|
||||
return goog.events.fireListeners_(obj, type, capture, eventObject);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires an object's listeners of a particular type and phase.
|
||||
* @param {Object} obj Object whose listeners to call.
|
||||
* @param {string|!goog.events.EventId} type Event type.
|
||||
* @param {boolean} capture Which event phase.
|
||||
* @param {Object} eventObject Event object to be passed to listener.
|
||||
* @return {boolean} True if all listeners returned true else false.
|
||||
* @private
|
||||
*/
|
||||
goog.events.fireListeners_ = function(obj, type, capture, eventObject) {
|
||||
'use strict';
|
||||
/** @type {boolean} */
|
||||
var retval = true;
|
||||
|
||||
var listenerMap = goog.events.getListenerMap_(
|
||||
/** @type {EventTarget} */ (obj));
|
||||
if (listenerMap) {
|
||||
// TODO(chrishenry): Original code avoids array creation when there
|
||||
// is no listener, so we do the same. If this optimization turns
|
||||
// out to be not required, we can replace this with
|
||||
// listenerMap.getListeners(type, capture) instead, which is simpler.
|
||||
var listenerArray = listenerMap.listeners[type.toString()];
|
||||
if (listenerArray) {
|
||||
listenerArray = listenerArray.concat();
|
||||
for (var i = 0; i < listenerArray.length; i++) {
|
||||
var listener = listenerArray[i];
|
||||
// We might not have a listener if the listener was removed.
|
||||
if (listener && listener.capture == capture && !listener.removed) {
|
||||
var result = goog.events.fireListener(listener, eventObject);
|
||||
retval = retval && (result !== false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires a listener with a set of arguments
|
||||
*
|
||||
* @param {goog.events.Listener} listener The listener object to call.
|
||||
* @param {Object} eventObject The event object to pass to the listener.
|
||||
* @return {*} Result of listener.
|
||||
*/
|
||||
goog.events.fireListener = function(listener, eventObject) {
|
||||
'use strict';
|
||||
var listenerFn = listener.listener;
|
||||
var listenerHandler = listener.handler || listener.src;
|
||||
|
||||
if (listener.callOnce) {
|
||||
goog.events.unlistenByKey(listener);
|
||||
}
|
||||
return listenerFn.call(listenerHandler, eventObject);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the total number of listeners currently in the system.
|
||||
* @return {number} Number of listeners.
|
||||
* @deprecated This returns estimated count, now that Closure no longer
|
||||
* stores a central listener registry. We still return an estimation
|
||||
* to keep existing listener-related tests passing. In the near future,
|
||||
* this function will be removed.
|
||||
*/
|
||||
goog.events.getTotalListenerCount = function() {
|
||||
'use strict';
|
||||
return goog.events.listenerCountEstimate_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches an event (or event like object) and calls all listeners
|
||||
* listening for events of this type. The type of the event is decided by the
|
||||
* type property on the event object.
|
||||
*
|
||||
* If any of the listeners returns false OR calls preventDefault then this
|
||||
* function will return false. If one of the capture listeners calls
|
||||
* stopPropagation, then the bubble listeners won't fire.
|
||||
*
|
||||
* @param {goog.events.Listenable} src The event target.
|
||||
* @param {goog.events.EventLike} e Event object.
|
||||
* @return {boolean} If anyone called preventDefault on the event object (or
|
||||
* if any of the handlers returns false) this will also return false.
|
||||
* If there are no handlers, or if all handlers return true, this returns
|
||||
* true.
|
||||
*/
|
||||
goog.events.dispatchEvent = function(src, e) {
|
||||
'use strict';
|
||||
goog.asserts.assert(
|
||||
goog.events.Listenable.isImplementedBy(src),
|
||||
'Can not use goog.events.dispatchEvent with ' +
|
||||
'non-goog.events.Listenable instance.');
|
||||
return src.dispatchEvent(e);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Installs exception protection for the browser event entry point using the
|
||||
* given error handler.
|
||||
*
|
||||
* @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
|
||||
* protect the entry point.
|
||||
*/
|
||||
goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
|
||||
'use strict';
|
||||
goog.events.handleBrowserEvent_ =
|
||||
errorHandler.protectEntryPoint(goog.events.handleBrowserEvent_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles an event and dispatches it to the correct listeners. This
|
||||
* function is a proxy for the real listener the user specified.
|
||||
*
|
||||
* @param {goog.events.Listener} listener The listener object.
|
||||
* @param {Event=} opt_evt Optional event object that gets passed in via the
|
||||
* native event handlers.
|
||||
* @return {*} Result of the event handler.
|
||||
* @this {EventTarget} The object or Element that fired the event.
|
||||
* @private
|
||||
*/
|
||||
goog.events.handleBrowserEvent_ = function(listener, opt_evt) {
|
||||
'use strict';
|
||||
if (listener.removed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, simply fire the listener.
|
||||
return goog.events.fireListener(
|
||||
listener, new goog.events.BrowserEvent(opt_evt, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is used to mark the IE event object so we do not do the Closure pass
|
||||
* twice for a bubbling event.
|
||||
* @param {Event} e The IE browser event.
|
||||
* @private
|
||||
*/
|
||||
goog.events.markIeEvent_ = function(e) {
|
||||
'use strict';
|
||||
// Only the keyCode and the returnValue can be changed. We use keyCode for
|
||||
// non keyboard events.
|
||||
// event.returnValue is a bit more tricky. It is undefined by default. A
|
||||
// boolean false prevents the default action. In a window.onbeforeunload and
|
||||
// the returnValue is non undefined it will be alerted. However, we will only
|
||||
// modify the returnValue for keyboard events. We can get a problem if non
|
||||
// closure events sets the keyCode or the returnValue
|
||||
|
||||
var useReturnValue = false;
|
||||
|
||||
if (e.keyCode == 0) {
|
||||
// We cannot change the keyCode in case that srcElement is input[type=file].
|
||||
// We could test that that is the case but that would allocate 3 objects.
|
||||
// If we use try/catch we will only allocate extra objects in the case of a
|
||||
// failure.
|
||||
|
||||
try {
|
||||
e.keyCode = -1;
|
||||
return;
|
||||
} catch (ex) {
|
||||
useReturnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (useReturnValue ||
|
||||
/** @type {boolean|undefined} */ (e.returnValue) == undefined) {
|
||||
e.returnValue = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is used to check if an IE event has already been handled by the Closure
|
||||
* system so we do not do the Closure pass twice for a bubbling event.
|
||||
* @param {Event} e The IE browser event.
|
||||
* @return {boolean} True if the event object has been marked.
|
||||
* @private
|
||||
*/
|
||||
goog.events.isMarkedIeEvent_ = function(e) {
|
||||
'use strict';
|
||||
return e.keyCode < 0 || e.returnValue != undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Counter to create unique event ids.
|
||||
* @private {number}
|
||||
*/
|
||||
goog.events.uniqueIdCounter_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a unique event id.
|
||||
*
|
||||
* @param {string} identifier The identifier.
|
||||
* @return {string} A unique identifier.
|
||||
* @idGenerator {unique}
|
||||
*/
|
||||
goog.events.getUniqueId = function(identifier) {
|
||||
'use strict';
|
||||
return identifier + '_' + goog.events.uniqueIdCounter_++;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {EventTarget} src The source object.
|
||||
* @return {goog.events.ListenerMap} A listener map for the given
|
||||
* source object, or null if none exists.
|
||||
* @private
|
||||
*/
|
||||
goog.events.getListenerMap_ = function(src) {
|
||||
'use strict';
|
||||
var listenerMap = src[goog.events.LISTENER_MAP_PROP_];
|
||||
// IE serializes the property as well (e.g. when serializing outer
|
||||
// HTML). So we must check that the value is of the correct type.
|
||||
return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Expando property for listener function wrapper for Object with
|
||||
* handleEvent.
|
||||
* @private @const {string}
|
||||
*/
|
||||
goog.events.LISTENER_WRAPPER_PROP_ =
|
||||
'__closure_events_fn_' + ((Math.random() * 1e9) >>> 0);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object|Function} listener The listener function or an
|
||||
* object that contains handleEvent method.
|
||||
* @return {!Function} Either the original function or a function that
|
||||
* calls obj.handleEvent. If the same listener is passed to this
|
||||
* function more than once, the same function is guaranteed to be
|
||||
* returned.
|
||||
*/
|
||||
goog.events.wrapListener = function(listener) {
|
||||
'use strict';
|
||||
goog.asserts.assert(listener, 'Listener can not be null.');
|
||||
|
||||
if (typeof listener === 'function') {
|
||||
return listener;
|
||||
}
|
||||
|
||||
goog.asserts.assert(
|
||||
listener.handleEvent, 'An object listener must have handleEvent method.');
|
||||
if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {
|
||||
listener[goog.events.LISTENER_WRAPPER_PROP_] = function(e) {
|
||||
'use strict';
|
||||
return /** @type {?} */ (listener).handleEvent(e);
|
||||
};
|
||||
}
|
||||
return listener[goog.events.LISTENER_WRAPPER_PROP_];
|
||||
};
|
||||
|
||||
|
||||
// Register the browser event handler as an entry point, so that
|
||||
// it can be monitored for exception handling, etc.
|
||||
goog.debug.entryPointRegistry.register(
|
||||
/**
|
||||
* @param {function(!Function): !Function} transformer The transforming
|
||||
* function.
|
||||
*/
|
||||
function(transformer) {
|
||||
'use strict';
|
||||
goog.events.handleBrowserEvent_ =
|
||||
transformer(goog.events.handleBrowserEvent_);
|
||||
});
|
||||
Executable
+495
@@ -0,0 +1,495 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A disposable implementation of a custom
|
||||
* listenable/event target. See also: documentation for
|
||||
* `goog.events.Listenable`.
|
||||
*
|
||||
* @see ../demos/eventtarget.html
|
||||
* @see goog.events.Listenable
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.EventTarget');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.Listenable');
|
||||
goog.require('goog.events.ListenerMap');
|
||||
goog.require('goog.object');
|
||||
goog.requireType('goog.events.EventId');
|
||||
goog.requireType('goog.events.EventLike');
|
||||
goog.requireType('goog.events.ListenableKey');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of `goog.events.Listenable` with full W3C
|
||||
* EventTarget-like support (capture/bubble mechanism, stopping event
|
||||
* propagation, preventing default actions).
|
||||
*
|
||||
* You may subclass this class to turn your class into a Listenable.
|
||||
*
|
||||
* Unless propagation is stopped, an event dispatched by an
|
||||
* EventTarget will bubble to the parent returned by
|
||||
* `getParentEventTarget`. To set the parent, call
|
||||
* `setParentEventTarget`. Subclasses that don't support
|
||||
* changing the parent can override the setter to throw an error.
|
||||
*
|
||||
* Example usage:
|
||||
* <pre>
|
||||
* var source = new goog.events.EventTarget();
|
||||
* function handleEvent(e) {
|
||||
* alert('Type: ' + e.type + '; Target: ' + e.target);
|
||||
* }
|
||||
* source.listen('foo', handleEvent);
|
||||
* // Or: goog.events.listen(source, 'foo', handleEvent);
|
||||
* ...
|
||||
* source.dispatchEvent('foo'); // will call handleEvent
|
||||
* ...
|
||||
* source.unlisten('foo', handleEvent);
|
||||
* // Or: goog.events.unlisten(source, 'foo', handleEvent);
|
||||
* </pre>
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @implements {goog.events.Listenable}
|
||||
*/
|
||||
goog.events.EventTarget = function() {
|
||||
'use strict';
|
||||
goog.Disposable.call(this);
|
||||
|
||||
/**
|
||||
* Maps of event type to an array of listeners.
|
||||
* @private {!goog.events.ListenerMap}
|
||||
*/
|
||||
this.eventTargetListeners_ = new goog.events.ListenerMap(this);
|
||||
|
||||
/**
|
||||
* The object to use for event.target. Useful when mixing in an
|
||||
* EventTarget to another object.
|
||||
* @private {!Object}
|
||||
*/
|
||||
this.actualEventTarget_ = this;
|
||||
|
||||
/**
|
||||
* Parent event target, used during event bubbling.
|
||||
*
|
||||
* TODO(chrishenry): Change this to goog.events.Listenable. This
|
||||
* currently breaks people who expect getParentEventTarget to return
|
||||
* goog.events.EventTarget.
|
||||
*
|
||||
* @private {?goog.events.EventTarget}
|
||||
*/
|
||||
this.parentEventTarget_ = null;
|
||||
};
|
||||
goog.inherits(goog.events.EventTarget, goog.Disposable);
|
||||
goog.events.Listenable.addImplementation(goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* An artificial cap on the number of ancestors you can have. This is mainly
|
||||
* for loop detection.
|
||||
* @const {number}
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parent of this event target to use for bubbling.
|
||||
*
|
||||
* @return {goog.events.EventTarget} The parent EventTarget or null if
|
||||
* there is no parent.
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.getParentEventTarget = function() {
|
||||
'use strict';
|
||||
return this.parentEventTarget_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the parent of this event target to use for capture/bubble
|
||||
* mechanism.
|
||||
* @param {goog.events.EventTarget} parent Parent listenable (null if none).
|
||||
*/
|
||||
goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
|
||||
'use strict';
|
||||
this.parentEventTarget_ = parent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener to the event target. The same handler can only be
|
||||
* added once per the type. Even if you add the same handler multiple times
|
||||
* using the same type then it will only be called once when the event is
|
||||
* dispatched.
|
||||
*
|
||||
* @param {string|!goog.events.EventId} type The type of the event to listen for
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
|
||||
* to handle the event. The handler can also be an object that implements
|
||||
* the handleEvent method which takes the event object as argument.
|
||||
* @param {boolean=} opt_capture In DOM-compliant browsers, this determines
|
||||
* whether the listener is fired during the capture or bubble phase
|
||||
* of the event.
|
||||
* @param {Object=} opt_handlerScope Object in whose scope to call
|
||||
* the listener.
|
||||
* @deprecated Use `#listen` instead, when possible. Otherwise, use
|
||||
* `goog.events.listen` if you are passing Object
|
||||
* (instead of Function) as handler.
|
||||
*/
|
||||
goog.events.EventTarget.prototype.addEventListener = function(
|
||||
type, handler, opt_capture, opt_handlerScope) {
|
||||
'use strict';
|
||||
goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener from the event target. The handler must be the
|
||||
* same object as the one added. If the handler has not been added then
|
||||
* nothing is done.
|
||||
*
|
||||
* @param {string|!goog.events.EventId} type The type of the event to listen for
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
|
||||
* to handle the event. The handler can also be an object that implements
|
||||
* the handleEvent method which takes the event object as argument.
|
||||
* @param {boolean=} opt_capture In DOM-compliant browsers, this determines
|
||||
* whether the listener is fired during the capture or bubble phase
|
||||
* of the event.
|
||||
* @param {Object=} opt_handlerScope Object in whose scope to call
|
||||
* the listener.
|
||||
* @deprecated Use `#unlisten` instead, when possible. Otherwise, use
|
||||
* `goog.events.unlisten` if you are passing Object
|
||||
* (instead of Function) as handler.
|
||||
*/
|
||||
goog.events.EventTarget.prototype.removeEventListener = function(
|
||||
type, handler, opt_capture, opt_handlerScope) {
|
||||
'use strict';
|
||||
goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?goog.events.EventLike} e Event object.
|
||||
* @return {boolean} If anyone called preventDefault on the event object (or
|
||||
* if any of the listeners returns false) this will also return false.
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.dispatchEvent = function(e) {
|
||||
'use strict';
|
||||
this.assertInitialized_();
|
||||
|
||||
var ancestorsTree, ancestor = this.getParentEventTarget();
|
||||
if (ancestor) {
|
||||
ancestorsTree = [];
|
||||
var ancestorCount = 1;
|
||||
for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
|
||||
ancestorsTree.push(ancestor);
|
||||
goog.asserts.assert(
|
||||
(++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),
|
||||
'infinite loop');
|
||||
}
|
||||
}
|
||||
|
||||
return goog.events.EventTarget.dispatchEventInternal_(
|
||||
this.actualEventTarget_, e, ancestorsTree);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes listeners from this object. Classes that extend EventTarget may
|
||||
* need to override this method in order to remove references to DOM Elements
|
||||
* and additional listeners.
|
||||
* @override
|
||||
* @protected
|
||||
*/
|
||||
goog.events.EventTarget.prototype.disposeInternal = function() {
|
||||
'use strict';
|
||||
goog.events.EventTarget.superClass_.disposeInternal.call(this);
|
||||
|
||||
this.removeAllListeners();
|
||||
this.parentEventTarget_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
|
||||
* method.
|
||||
* @param {boolean=} opt_useCapture Whether to fire in capture phase
|
||||
* (defaults to false).
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {!goog.events.ListenableKey} Unique key for the listener.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.listen = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {
|
||||
'use strict';
|
||||
this.assertInitialized_();
|
||||
return this.eventTargetListeners_.add(
|
||||
String(type), listener, false /* callOnce */, opt_useCapture,
|
||||
opt_listenerScope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
|
||||
* method.
|
||||
* @param {boolean=} opt_useCapture Whether to fire in capture phase
|
||||
* (defaults to false).
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {!goog.events.ListenableKey} Unique key for the listener.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.listenOnce = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {
|
||||
'use strict';
|
||||
return this.eventTargetListeners_.add(
|
||||
String(type), listener, true /* callOnce */, opt_useCapture,
|
||||
opt_listenerScope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
|
||||
* method.
|
||||
* @param {boolean=} opt_useCapture Whether to fire in capture phase
|
||||
* (defaults to false).
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call
|
||||
* the listener.
|
||||
* @return {boolean} Whether any listener was removed.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.unlisten = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {
|
||||
'use strict';
|
||||
return this.eventTargetListeners_.remove(
|
||||
String(type), listener, opt_useCapture, opt_listenerScope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.events.ListenableKey} key The key returned by
|
||||
* listen() or listenOnce().
|
||||
* @return {boolean} Whether any listener was removed.
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.unlistenByKey = function(key) {
|
||||
'use strict';
|
||||
return this.eventTargetListeners_.removeByKey(key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId=} opt_type Type of event to remove,
|
||||
* default is to remove all types.
|
||||
* @return {number} Number of listeners removed.
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
|
||||
'use strict';
|
||||
// TODO(chrishenry): Previously, removeAllListeners can be called on
|
||||
// uninitialized EventTarget, so we preserve that behavior. We
|
||||
// should remove this when usages that rely on that fact are purged.
|
||||
if (!this.eventTargetListeners_) {
|
||||
return 0;
|
||||
}
|
||||
return this.eventTargetListeners_.removeAll(opt_type);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
|
||||
* listeners to fire.
|
||||
* @param {boolean} capture The capture mode of the listeners to fire.
|
||||
* @param {EVENTOBJ} eventObject The event object to fire.
|
||||
* @return {boolean} Whether all listeners succeeded without
|
||||
* attempting to prevent default behavior. If any listener returns
|
||||
* false or called goog.events.Event#preventDefault, this returns
|
||||
* false.
|
||||
* @template EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.fireListeners = function(
|
||||
type, capture, eventObject) {
|
||||
'use strict';
|
||||
// TODO(chrishenry): Original code avoids array creation when there
|
||||
// is no listener, so we do the same. If this optimization turns
|
||||
// out to be not required, we can replace this with
|
||||
// getListeners(type, capture) instead, which is simpler.
|
||||
var listenerArray = this.eventTargetListeners_.listeners[String(type)];
|
||||
if (!listenerArray) {
|
||||
return true;
|
||||
}
|
||||
listenerArray = listenerArray.concat();
|
||||
|
||||
var rv = true;
|
||||
for (var i = 0; i < listenerArray.length; ++i) {
|
||||
var listener = listenerArray[i];
|
||||
// We might not have a listener if the listener was removed.
|
||||
if (listener && !listener.removed && listener.capture == capture) {
|
||||
var listenerFn = listener.listener;
|
||||
var listenerHandler = listener.handler || listener.src;
|
||||
|
||||
if (listener.callOnce) {
|
||||
this.unlistenByKey(listener);
|
||||
}
|
||||
rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
|
||||
}
|
||||
}
|
||||
|
||||
return rv && !eventObject.defaultPrevented;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId} type The type of the listeners to fire.
|
||||
* @param {boolean} capture The capture mode of the listeners to fire.
|
||||
* @return {!Array<!goog.events.ListenableKey>} An array of registered
|
||||
* listeners.
|
||||
* @template EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.getListeners = function(type, capture) {
|
||||
'use strict';
|
||||
return this.eventTargetListeners_.getListeners(String(type), capture);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event
|
||||
* without the 'on' prefix.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The
|
||||
* listener function to get.
|
||||
* @param {boolean} capture Whether the listener is a capturing listener.
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {?goog.events.ListenableKey} the found listener or null if not found.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.getListener = function(
|
||||
type, listener, capture, opt_listenerScope) {
|
||||
'use strict';
|
||||
return this.eventTargetListeners_.getListener(
|
||||
String(type), listener, capture, opt_listenerScope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.
|
||||
* @param {boolean=} opt_capture Whether to check for capture or bubble
|
||||
* listeners.
|
||||
* @return {boolean} Whether there is any active listeners matching
|
||||
* the requested type and/or capture phase.
|
||||
* @template EVENTOBJ
|
||||
* @override
|
||||
*/
|
||||
goog.events.EventTarget.prototype.hasListener = function(
|
||||
opt_type, opt_capture) {
|
||||
'use strict';
|
||||
var id = (opt_type !== undefined) ? String(opt_type) : undefined;
|
||||
return this.eventTargetListeners_.hasListener(id, opt_capture);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the target to be used for `event.target` when firing
|
||||
* event. Mainly used for testing. For example, see
|
||||
* `goog.testing.events.mixinListenable`.
|
||||
* @param {!Object} target The target.
|
||||
*/
|
||||
goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
|
||||
'use strict';
|
||||
this.actualEventTarget_ = target;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that the event target instance is initialized properly.
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventTarget.prototype.assertInitialized_ = function() {
|
||||
'use strict';
|
||||
goog.asserts.assert(
|
||||
this.eventTargetListeners_,
|
||||
'Event target is not initialized. Did you call the superclass ' +
|
||||
'(goog.events.EventTarget) constructor?');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches the given event on the ancestorsTree.
|
||||
*
|
||||
* @param {!Object} target The target to dispatch on.
|
||||
* @param {goog.events.Event|Object|string} e The event object.
|
||||
* @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors
|
||||
* tree of the target, in reverse order from the closest ancestor
|
||||
* to the root event target. May be null if the target has no ancestor.
|
||||
* @return {boolean} If anyone called preventDefault on the event object (or
|
||||
* if any of the listeners returns false) this will also return false.
|
||||
* @private
|
||||
*/
|
||||
goog.events.EventTarget.dispatchEventInternal_ = function(
|
||||
target, e, opt_ancestorsTree) {
|
||||
'use strict';
|
||||
/** @suppress {missingProperties} */
|
||||
var type = e.type || /** @type {string} */ (e);
|
||||
|
||||
// If accepting a string or object, create a custom event object so that
|
||||
// preventDefault and stopPropagation work with the event.
|
||||
if (typeof e === 'string') {
|
||||
e = new goog.events.Event(e, target);
|
||||
} else if (!(e instanceof goog.events.Event)) {
|
||||
var oldEvent = e;
|
||||
e = new goog.events.Event(type, target);
|
||||
goog.object.extend(e, oldEvent);
|
||||
} else {
|
||||
e.target = e.target || target;
|
||||
}
|
||||
|
||||
var rv = true, currentTarget;
|
||||
|
||||
// Executes all capture listeners on the ancestors, if any.
|
||||
if (opt_ancestorsTree) {
|
||||
for (var i = opt_ancestorsTree.length - 1;
|
||||
!e.hasPropagationStopped() && i >= 0; i--) {
|
||||
currentTarget = e.currentTarget = opt_ancestorsTree[i];
|
||||
rv = currentTarget.fireListeners(type, true, e) && rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Executes capture and bubble listeners on the target.
|
||||
if (!e.hasPropagationStopped()) {
|
||||
currentTarget = /** @type {?} */ (e.currentTarget = target);
|
||||
rv = currentTarget.fireListeners(type, true, e) && rv;
|
||||
if (!e.hasPropagationStopped()) {
|
||||
rv = currentTarget.fireListeners(type, false, e) && rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Executes all bubble listeners on the ancestors, if any.
|
||||
if (opt_ancestorsTree) {
|
||||
for (i = 0; !e.hasPropagationStopped() && i < opt_ancestorsTree.length;
|
||||
i++) {
|
||||
currentTarget = e.currentTarget = opt_ancestorsTree[i];
|
||||
rv = currentTarget.fireListeners(type, false, e) && rv;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
};
|
||||
Executable
+437
@@ -0,0 +1,437 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Event Types.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.events.EventType');
|
||||
goog.provide('goog.events.MouseAsMouseEventType');
|
||||
goog.provide('goog.events.MouseEvents');
|
||||
goog.provide('goog.events.PointerAsMouseEventType');
|
||||
goog.provide('goog.events.PointerAsTouchEventType');
|
||||
goog.provide('goog.events.PointerFallbackEventType');
|
||||
goog.provide('goog.events.PointerTouchFallbackEventType');
|
||||
|
||||
goog.require('goog.events.BrowserFeature');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Returns a prefixed event name for the current browser.
|
||||
* @param {string} eventName The name of the event.
|
||||
* @return {string} The prefixed event name.
|
||||
* @private
|
||||
*/
|
||||
goog.events.getVendorPrefixedName_ = function(eventName) {
|
||||
'use strict';
|
||||
return goog.userAgent.WEBKIT ? 'webkit' + eventName : eventName.toLowerCase();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constants for event names.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.events.EventType = {
|
||||
// Mouse events
|
||||
CLICK: 'click',
|
||||
RIGHTCLICK: 'rightclick',
|
||||
DBLCLICK: 'dblclick',
|
||||
AUXCLICK: 'auxclick',
|
||||
MOUSEDOWN: 'mousedown',
|
||||
MOUSEUP: 'mouseup',
|
||||
MOUSEOVER: 'mouseover',
|
||||
MOUSEOUT: 'mouseout',
|
||||
MOUSEMOVE: 'mousemove',
|
||||
MOUSEENTER: 'mouseenter',
|
||||
MOUSELEAVE: 'mouseleave',
|
||||
|
||||
// Non-existent event; will never fire. This exists as a mouse counterpart to
|
||||
// POINTERCANCEL.
|
||||
MOUSECANCEL: 'mousecancel',
|
||||
|
||||
// Selection events.
|
||||
// https://www.w3.org/TR/selection-api/
|
||||
SELECTIONCHANGE: 'selectionchange',
|
||||
SELECTSTART: 'selectstart', // IE, Safari, Chrome
|
||||
|
||||
// Wheel events
|
||||
// http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents
|
||||
WHEEL: 'wheel',
|
||||
|
||||
// Key events
|
||||
KEYPRESS: 'keypress',
|
||||
KEYDOWN: 'keydown',
|
||||
KEYUP: 'keyup',
|
||||
|
||||
// Focus
|
||||
BLUR: 'blur',
|
||||
FOCUS: 'focus',
|
||||
DEACTIVATE: 'deactivate', // IE only
|
||||
FOCUSIN: 'focusin',
|
||||
FOCUSOUT: 'focusout',
|
||||
|
||||
// Forms
|
||||
CHANGE: 'change',
|
||||
RESET: 'reset',
|
||||
SELECT: 'select',
|
||||
SUBMIT: 'submit',
|
||||
INPUT: 'input',
|
||||
PROPERTYCHANGE: 'propertychange', // IE only
|
||||
|
||||
// Drag and drop
|
||||
DRAGSTART: 'dragstart',
|
||||
DRAG: 'drag',
|
||||
DRAGENTER: 'dragenter',
|
||||
DRAGOVER: 'dragover',
|
||||
DRAGLEAVE: 'dragleave',
|
||||
DROP: 'drop',
|
||||
DRAGEND: 'dragend',
|
||||
|
||||
// Touch events
|
||||
// Note that other touch events exist, but we should follow the W3C list here.
|
||||
// http://www.w3.org/TR/touch-events/#list-of-touchevent-types
|
||||
TOUCHSTART: 'touchstart',
|
||||
TOUCHMOVE: 'touchmove',
|
||||
TOUCHEND: 'touchend',
|
||||
TOUCHCANCEL: 'touchcancel',
|
||||
|
||||
// Misc
|
||||
BEFOREUNLOAD: 'beforeunload',
|
||||
CONSOLEMESSAGE: 'consolemessage',
|
||||
CONTEXTMENU: 'contextmenu',
|
||||
DEVICECHANGE: 'devicechange',
|
||||
DEVICEMOTION: 'devicemotion',
|
||||
DEVICEORIENTATION: 'deviceorientation',
|
||||
DOMCONTENTLOADED: 'DOMContentLoaded',
|
||||
ERROR: 'error',
|
||||
HELP: 'help',
|
||||
LOAD: 'load',
|
||||
LOSECAPTURE: 'losecapture',
|
||||
ORIENTATIONCHANGE: 'orientationchange',
|
||||
READYSTATECHANGE: 'readystatechange',
|
||||
RESIZE: 'resize',
|
||||
SCROLL: 'scroll',
|
||||
UNLOAD: 'unload',
|
||||
|
||||
// Media events
|
||||
CANPLAY: 'canplay',
|
||||
CANPLAYTHROUGH: 'canplaythrough',
|
||||
DURATIONCHANGE: 'durationchange',
|
||||
EMPTIED: 'emptied',
|
||||
ENDED: 'ended',
|
||||
LOADEDDATA: 'loadeddata',
|
||||
LOADEDMETADATA: 'loadedmetadata',
|
||||
PAUSE: 'pause',
|
||||
PLAY: 'play',
|
||||
PLAYING: 'playing',
|
||||
PROGRESS: 'progress',
|
||||
RATECHANGE: 'ratechange',
|
||||
SEEKED: 'seeked',
|
||||
SEEKING: 'seeking',
|
||||
STALLED: 'stalled',
|
||||
SUSPEND: 'suspend',
|
||||
TIMEUPDATE: 'timeupdate',
|
||||
VOLUMECHANGE: 'volumechange',
|
||||
WAITING: 'waiting',
|
||||
|
||||
// Media Source Extensions events
|
||||
// https://www.w3.org/TR/media-source/#mediasource-events
|
||||
SOURCEOPEN: 'sourceopen',
|
||||
SOURCEENDED: 'sourceended',
|
||||
SOURCECLOSED: 'sourceclosed',
|
||||
// https://www.w3.org/TR/media-source/#sourcebuffer-events
|
||||
ABORT: 'abort',
|
||||
UPDATE: 'update',
|
||||
UPDATESTART: 'updatestart',
|
||||
UPDATEEND: 'updateend',
|
||||
|
||||
// HTML 5 History events
|
||||
// See http://www.w3.org/TR/html5/browsers.html#event-definitions-0
|
||||
HASHCHANGE: 'hashchange',
|
||||
PAGEHIDE: 'pagehide',
|
||||
PAGESHOW: 'pageshow',
|
||||
POPSTATE: 'popstate',
|
||||
|
||||
// Copy and Paste
|
||||
// Support is limited. Make sure it works on your favorite browser
|
||||
// before using.
|
||||
// http://www.quirksmode.org/dom/events/cutcopypaste.html
|
||||
COPY: 'copy',
|
||||
PASTE: 'paste',
|
||||
CUT: 'cut',
|
||||
BEFORECOPY: 'beforecopy',
|
||||
BEFORECUT: 'beforecut',
|
||||
BEFOREPASTE: 'beforepaste',
|
||||
|
||||
// HTML5 online/offline events.
|
||||
// http://www.w3.org/TR/offline-webapps/#related
|
||||
ONLINE: 'online',
|
||||
OFFLINE: 'offline',
|
||||
|
||||
// HTML 5 worker events
|
||||
MESSAGE: 'message',
|
||||
CONNECT: 'connect',
|
||||
|
||||
// Service Worker Events - ServiceWorkerGlobalScope context
|
||||
// See https://w3c.github.io/ServiceWorker/#execution-context-events
|
||||
// Note: message event defined in worker events section
|
||||
INSTALL: 'install',
|
||||
ACTIVATE: 'activate',
|
||||
FETCH: 'fetch',
|
||||
FOREIGNFETCH: 'foreignfetch',
|
||||
MESSAGEERROR: 'messageerror',
|
||||
|
||||
// Service Worker Events - Document context
|
||||
// See https://w3c.github.io/ServiceWorker/#document-context-events
|
||||
STATECHANGE: 'statechange',
|
||||
UPDATEFOUND: 'updatefound',
|
||||
CONTROLLERCHANGE: 'controllerchange',
|
||||
|
||||
// CSS animation events.
|
||||
ANIMATIONSTART: goog.events.getVendorPrefixedName_('AnimationStart'),
|
||||
ANIMATIONEND: goog.events.getVendorPrefixedName_('AnimationEnd'),
|
||||
ANIMATIONITERATION: goog.events.getVendorPrefixedName_('AnimationIteration'),
|
||||
|
||||
// CSS transition events. Based on the browser support described at:
|
||||
// https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility
|
||||
TRANSITIONEND: goog.events.getVendorPrefixedName_('TransitionEnd'),
|
||||
|
||||
// W3C Pointer Events
|
||||
// http://www.w3.org/TR/pointerevents/
|
||||
POINTERDOWN: 'pointerdown',
|
||||
POINTERUP: 'pointerup',
|
||||
POINTERCANCEL: 'pointercancel',
|
||||
POINTERMOVE: 'pointermove',
|
||||
POINTEROVER: 'pointerover',
|
||||
POINTEROUT: 'pointerout',
|
||||
POINTERENTER: 'pointerenter',
|
||||
POINTERLEAVE: 'pointerleave',
|
||||
GOTPOINTERCAPTURE: 'gotpointercapture',
|
||||
LOSTPOINTERCAPTURE: 'lostpointercapture',
|
||||
|
||||
// IE specific events.
|
||||
// See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx
|
||||
// Note: these events will be supplanted in IE11.
|
||||
MSGESTURECHANGE: 'MSGestureChange',
|
||||
MSGESTUREEND: 'MSGestureEnd',
|
||||
MSGESTUREHOLD: 'MSGestureHold',
|
||||
MSGESTURESTART: 'MSGestureStart',
|
||||
MSGESTURETAP: 'MSGestureTap',
|
||||
MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',
|
||||
MSINERTIASTART: 'MSInertiaStart',
|
||||
MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',
|
||||
MSPOINTERCANCEL: 'MSPointerCancel',
|
||||
MSPOINTERDOWN: 'MSPointerDown',
|
||||
MSPOINTERENTER: 'MSPointerEnter',
|
||||
MSPOINTERHOVER: 'MSPointerHover',
|
||||
MSPOINTERLEAVE: 'MSPointerLeave',
|
||||
MSPOINTERMOVE: 'MSPointerMove',
|
||||
MSPOINTEROUT: 'MSPointerOut',
|
||||
MSPOINTEROVER: 'MSPointerOver',
|
||||
MSPOINTERUP: 'MSPointerUp',
|
||||
|
||||
// Native IMEs/input tools events.
|
||||
TEXT: 'text',
|
||||
// The textInput event is supported in IE9+, but only in lower case. All other
|
||||
// browsers use the camel-case event name.
|
||||
TEXTINPUT: goog.userAgent.IE ? 'textinput' : 'textInput',
|
||||
COMPOSITIONSTART: 'compositionstart',
|
||||
COMPOSITIONUPDATE: 'compositionupdate',
|
||||
COMPOSITIONEND: 'compositionend',
|
||||
|
||||
// The beforeinput event is initially only supported in Safari. See
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=342670 for Chrome
|
||||
// implementation tracking.
|
||||
BEFOREINPUT: 'beforeinput',
|
||||
|
||||
// Webview tag events
|
||||
// See https://developer.chrome.com/apps/tags/webview
|
||||
EXIT: 'exit',
|
||||
LOADABORT: 'loadabort',
|
||||
LOADCOMMIT: 'loadcommit',
|
||||
LOADREDIRECT: 'loadredirect',
|
||||
LOADSTART: 'loadstart',
|
||||
LOADSTOP: 'loadstop',
|
||||
RESPONSIVE: 'responsive',
|
||||
SIZECHANGED: 'sizechanged',
|
||||
UNRESPONSIVE: 'unresponsive',
|
||||
|
||||
// HTML5 Page Visibility API. See details at
|
||||
// `goog.labs.dom.PageVisibilityMonitor`.
|
||||
VISIBILITYCHANGE: 'visibilitychange',
|
||||
|
||||
// LocalStorage event.
|
||||
STORAGE: 'storage',
|
||||
|
||||
// DOM Level 2 mutation events (deprecated).
|
||||
DOMSUBTREEMODIFIED: 'DOMSubtreeModified',
|
||||
DOMNODEINSERTED: 'DOMNodeInserted',
|
||||
DOMNODEREMOVED: 'DOMNodeRemoved',
|
||||
DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument',
|
||||
DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument',
|
||||
DOMATTRMODIFIED: 'DOMAttrModified',
|
||||
DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified',
|
||||
|
||||
// Print events.
|
||||
BEFOREPRINT: 'beforeprint',
|
||||
AFTERPRINT: 'afterprint',
|
||||
|
||||
// Web app manifest events.
|
||||
BEFOREINSTALLPROMPT: 'beforeinstallprompt',
|
||||
APPINSTALLED: 'appinstalled'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns one of the given pointer fallback event names in order of preference:
|
||||
* 1. pointerEventName
|
||||
* 2. msPointerEventName
|
||||
* 3. fallbackEventName
|
||||
* @param {string} pointerEventName
|
||||
* @param {string} msPointerEventName
|
||||
* @param {string} fallbackEventName
|
||||
* @return {string} The supported pointer or fallback (mouse or touch) event
|
||||
* name.
|
||||
* @private
|
||||
*/
|
||||
goog.events.getPointerFallbackEventName_ = function(
|
||||
pointerEventName, msPointerEventName, fallbackEventName) {
|
||||
'use strict';
|
||||
if (goog.events.BrowserFeature.POINTER_EVENTS) {
|
||||
return pointerEventName;
|
||||
}
|
||||
if (goog.events.BrowserFeature.MSPOINTER_EVENTS) {
|
||||
return msPointerEventName;
|
||||
}
|
||||
return fallbackEventName;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constants for pointer event names that fall back to corresponding mouse event
|
||||
* names on unsupported platforms. These are intended to be drop-in replacements
|
||||
* for corresponding values in `goog.events.EventType`.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.events.PointerFallbackEventType = {
|
||||
POINTERDOWN: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,
|
||||
goog.events.EventType.MOUSEDOWN),
|
||||
POINTERUP: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,
|
||||
goog.events.EventType.MOUSEUP),
|
||||
POINTERCANCEL: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERCANCEL,
|
||||
goog.events.EventType.MSPOINTERCANCEL,
|
||||
// When falling back to mouse events, there is no MOUSECANCEL equivalent
|
||||
// of POINTERCANCEL. In this case POINTERUP already falls back to MOUSEUP
|
||||
// which represents both UP and CANCEL. POINTERCANCEL does not fall back
|
||||
// to MOUSEUP to prevent listening twice on the same event.
|
||||
goog.events.EventType.MOUSECANCEL),
|
||||
POINTERMOVE: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,
|
||||
goog.events.EventType.MOUSEMOVE),
|
||||
POINTEROVER: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTEROVER, goog.events.EventType.MSPOINTEROVER,
|
||||
goog.events.EventType.MOUSEOVER),
|
||||
POINTEROUT: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTEROUT, goog.events.EventType.MSPOINTEROUT,
|
||||
goog.events.EventType.MOUSEOUT),
|
||||
POINTERENTER: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERENTER, goog.events.EventType.MSPOINTERENTER,
|
||||
goog.events.EventType.MOUSEENTER),
|
||||
POINTERLEAVE: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERLEAVE, goog.events.EventType.MSPOINTERLEAVE,
|
||||
goog.events.EventType.MOUSELEAVE)
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constants for pointer event names that fall back to corresponding touch event
|
||||
* names on unsupported platforms. These are intended to be drop-in replacements
|
||||
* for corresponding values in `goog.events.EventType`.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.events.PointerTouchFallbackEventType = {
|
||||
POINTERDOWN: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,
|
||||
goog.events.EventType.TOUCHSTART),
|
||||
POINTERUP: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,
|
||||
goog.events.EventType.TOUCHEND),
|
||||
POINTERCANCEL: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERCANCEL,
|
||||
goog.events.EventType.MSPOINTERCANCEL, goog.events.EventType.TOUCHCANCEL),
|
||||
POINTERMOVE: goog.events.getPointerFallbackEventName_(
|
||||
goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,
|
||||
goog.events.EventType.TOUCHMOVE)
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mapping of mouse event names to underlying browser event names.
|
||||
* @typedef {{
|
||||
* MOUSEDOWN: string,
|
||||
* MOUSEUP: string,
|
||||
* MOUSECANCEL:string,
|
||||
* MOUSEMOVE:string,
|
||||
* MOUSEOVER:string,
|
||||
* MOUSEOUT:string,
|
||||
* MOUSEENTER:string,
|
||||
* MOUSELEAVE: string,
|
||||
* }}
|
||||
*/
|
||||
goog.events.MouseEvents;
|
||||
|
||||
|
||||
/**
|
||||
* An alias for `goog.events.EventType.MOUSE*` event types that is overridden by
|
||||
* corresponding `POINTER*` event types.
|
||||
* @const {!goog.events.MouseEvents}
|
||||
*/
|
||||
goog.events.PointerAsMouseEventType = {
|
||||
MOUSEDOWN: goog.events.PointerFallbackEventType.POINTERDOWN,
|
||||
MOUSEUP: goog.events.PointerFallbackEventType.POINTERUP,
|
||||
MOUSECANCEL: goog.events.PointerFallbackEventType.POINTERCANCEL,
|
||||
MOUSEMOVE: goog.events.PointerFallbackEventType.POINTERMOVE,
|
||||
MOUSEOVER: goog.events.PointerFallbackEventType.POINTEROVER,
|
||||
MOUSEOUT: goog.events.PointerFallbackEventType.POINTEROUT,
|
||||
MOUSEENTER: goog.events.PointerFallbackEventType.POINTERENTER,
|
||||
MOUSELEAVE: goog.events.PointerFallbackEventType.POINTERLEAVE
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An alias for `goog.events.EventType.MOUSE*` event types that continue to use
|
||||
* mouse events.
|
||||
* @const {!goog.events.MouseEvents}
|
||||
*/
|
||||
goog.events.MouseAsMouseEventType = {
|
||||
MOUSEDOWN: goog.events.EventType.MOUSEDOWN,
|
||||
MOUSEUP: goog.events.EventType.MOUSEUP,
|
||||
MOUSECANCEL: goog.events.EventType.MOUSECANCEL,
|
||||
MOUSEMOVE: goog.events.EventType.MOUSEMOVE,
|
||||
MOUSEOVER: goog.events.EventType.MOUSEOVER,
|
||||
MOUSEOUT: goog.events.EventType.MOUSEOUT,
|
||||
MOUSEENTER: goog.events.EventType.MOUSEENTER,
|
||||
MOUSELEAVE: goog.events.EventType.MOUSELEAVE
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An alias for `goog.events.EventType.TOUCH*` event types that is overridden by
|
||||
* corresponding `POINTER*` event types.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.events.PointerAsTouchEventType = {
|
||||
TOUCHCANCEL: goog.events.PointerTouchFallbackEventType.POINTERCANCEL,
|
||||
TOUCHEND: goog.events.PointerTouchFallbackEventType.POINTERUP,
|
||||
TOUCHMOVE: goog.events.PointerTouchFallbackEventType.POINTERMOVE,
|
||||
TOUCHSTART: goog.events.PointerTouchFallbackEventType.POINTERDOWN
|
||||
};
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Definition of the goog.events.EventWrapper interface.
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.EventWrapper');
|
||||
|
||||
goog.requireType('goog.events.EventHandler');
|
||||
goog.requireType('goog.events.ListenableType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for event wrappers.
|
||||
* @interface
|
||||
*/
|
||||
goog.events.EventWrapper = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener using the wrapper on a DOM Node or an object that has
|
||||
* implemented {@link goog.events.EventTarget}. A listener can only be added
|
||||
* once to an object.
|
||||
*
|
||||
* @param {goog.events.ListenableType} src The node to listen to events on.
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
|
||||
* method, or an object with a handleEvent function.
|
||||
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
|
||||
* false).
|
||||
* @param {Object=} opt_scope Element in whose scope to call the listener.
|
||||
* @param {goog.events.EventHandler=} opt_eventHandler Event handler to add
|
||||
* listener to.
|
||||
*/
|
||||
goog.events.EventWrapper.prototype.listen = function(
|
||||
src, listener, opt_capt, opt_scope, opt_eventHandler) {};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener added using goog.events.EventWrapper.listen.
|
||||
*
|
||||
* @param {goog.events.ListenableType} src The node to remove listener from.
|
||||
* @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
|
||||
* method, or an object with a handleEvent function.
|
||||
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
|
||||
* false).
|
||||
* @param {Object=} opt_scope Element in whose scope to call the listener.
|
||||
* @param {goog.events.EventHandler=} opt_eventHandler Event handler to remove
|
||||
* listener from.
|
||||
*/
|
||||
goog.events.EventWrapper.prototype.unlisten = function(
|
||||
src, listener, opt_capt, opt_scope, opt_eventHandler) {};
|
||||
Executable
+265
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview An interface for a listenable JavaScript object.
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.Listenable');
|
||||
|
||||
goog.requireType('goog.events.EventId');
|
||||
goog.requireType('goog.events.EventLike');
|
||||
goog.requireType('goog.events.ListenableKey');
|
||||
|
||||
|
||||
/**
|
||||
* A listenable interface. A listenable is an object with the ability
|
||||
* to dispatch/broadcast events to "event listeners" registered via
|
||||
* listen/listenOnce.
|
||||
*
|
||||
* The interface allows for an event propagation mechanism similar
|
||||
* to one offered by native browser event targets, such as
|
||||
* capture/bubble mechanism, stopping propagation, and preventing
|
||||
* default actions. Capture/bubble mechanism depends on the ancestor
|
||||
* tree constructed via `#getParentEventTarget`; this tree
|
||||
* must be directed acyclic graph. The meaning of default action(s)
|
||||
* in preventDefault is specific to a particular use case.
|
||||
*
|
||||
* Implementations that do not support capture/bubble or can not have
|
||||
* a parent listenable can simply not implement any ability to set the
|
||||
* parent listenable (and have `#getParentEventTarget` return
|
||||
* null).
|
||||
*
|
||||
* Implementation of this class can be used with or independently from
|
||||
* goog.events.
|
||||
*
|
||||
* Implementation must call `#addImplementation(implClass)`.
|
||||
*
|
||||
* @interface
|
||||
* @see goog.events
|
||||
* @see http://www.w3.org/TR/DOM-Level-2-Events/events.html
|
||||
*/
|
||||
goog.events.Listenable = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* An expando property to indicate that an object implements
|
||||
* goog.events.Listenable.
|
||||
*
|
||||
* See addImplementation/isImplementedBy.
|
||||
*
|
||||
* @type {string}
|
||||
* @const
|
||||
*/
|
||||
goog.events.Listenable.IMPLEMENTED_BY_PROP =
|
||||
'closure_listenable_' + ((Math.random() * 1e6) | 0);
|
||||
|
||||
|
||||
/**
|
||||
* Marks a given class (constructor) as an implementation of
|
||||
* Listenable, so that we can query that fact at runtime. The class
|
||||
* must have already implemented the interface.
|
||||
* @param {function(new:goog.events.Listenable,...)} cls The class constructor.
|
||||
* The corresponding class must have already implemented the interface.
|
||||
*/
|
||||
goog.events.Listenable.addImplementation = function(cls) {
|
||||
'use strict';
|
||||
cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?Object} obj The object to check.
|
||||
* @return {boolean} Whether a given instance implements Listenable. The
|
||||
* class/superclass of the instance must call addImplementation.
|
||||
*/
|
||||
goog.events.Listenable.isImplementedBy = function(obj) {
|
||||
'use strict';
|
||||
return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener. A listener can only be added once to an
|
||||
* object and if it is added again the key for the listener is
|
||||
* returned. Note that if the existing listener is a one-off listener
|
||||
* (registered via listenOnce), it will no longer be a one-off
|
||||
* listener after a call to listen().
|
||||
*
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
|
||||
* method.
|
||||
* @param {boolean=} opt_useCapture Whether to fire in capture phase
|
||||
* (defaults to false).
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {!goog.events.ListenableKey} Unique key for the listener.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.listen = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener that is removed automatically after the
|
||||
* listener fired once.
|
||||
*
|
||||
* If an existing listener already exists, listenOnce will do
|
||||
* nothing. In particular, if the listener was previously registered
|
||||
* via listen(), listenOnce() will not turn the listener into a
|
||||
* one-off listener. Similarly, if there is already an existing
|
||||
* one-off listener, listenOnce does not modify the listeners (it is
|
||||
* still a once listener).
|
||||
*
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
|
||||
* method.
|
||||
* @param {boolean=} opt_useCapture Whether to fire in capture phase
|
||||
* (defaults to false).
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {!goog.events.ListenableKey} Unique key for the listener.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.listenOnce = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener which was added with listen() or listenOnce().
|
||||
*
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
|
||||
* method.
|
||||
* @param {boolean=} opt_useCapture Whether to fire in capture phase
|
||||
* (defaults to false).
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call
|
||||
* the listener.
|
||||
* @return {boolean} Whether any listener was removed.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.unlisten = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an event listener which was added with listen() by the key
|
||||
* returned by listen().
|
||||
*
|
||||
* @param {!goog.events.ListenableKey} key The key returned by
|
||||
* listen() or listenOnce().
|
||||
* @return {boolean} Whether any listener was removed.
|
||||
*/
|
||||
goog.events.Listenable.prototype.unlistenByKey = function(key) {};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches an event (or event like object) and calls all listeners
|
||||
* listening for events of this type. The type of the event is decided by the
|
||||
* type property on the event object.
|
||||
*
|
||||
* If any of the listeners returns false OR calls preventDefault then this
|
||||
* function will return false. If one of the capture listeners calls
|
||||
* stopPropagation, then the bubble listeners won't fire.
|
||||
*
|
||||
* @param {?goog.events.EventLike} e Event object.
|
||||
* @return {boolean} If anyone called preventDefault on the event object (or
|
||||
* if any of the listeners returns false) this will also return false.
|
||||
*/
|
||||
goog.events.Listenable.prototype.dispatchEvent = function(e) {};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all listeners from this listenable. If type is specified,
|
||||
* it will only remove listeners of the particular type. otherwise all
|
||||
* registered listeners will be removed.
|
||||
*
|
||||
* @param {string|!goog.events.EventId=} opt_type Type of event to remove,
|
||||
* default is to remove all types.
|
||||
* @return {number} Number of listeners removed.
|
||||
*/
|
||||
goog.events.Listenable.prototype.removeAllListeners = function(opt_type) {};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parent of this event target to use for capture/bubble
|
||||
* mechanism.
|
||||
*
|
||||
* NOTE(chrishenry): The name reflects the original implementation of
|
||||
* custom event target (`goog.events.EventTarget`). We decided
|
||||
* that changing the name is not worth it.
|
||||
*
|
||||
* @return {?goog.events.Listenable} The parent EventTarget or null if
|
||||
* there is no parent.
|
||||
*/
|
||||
goog.events.Listenable.prototype.getParentEventTarget = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Fires all registered listeners in this listenable for the given
|
||||
* type and capture mode, passing them the given eventObject. This
|
||||
* does not perform actual capture/bubble. Only implementors of the
|
||||
* interface should be using this.
|
||||
*
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
|
||||
* listeners to fire.
|
||||
* @param {boolean} capture The capture mode of the listeners to fire.
|
||||
* @param {EVENTOBJ} eventObject The event object to fire.
|
||||
* @return {boolean} Whether all listeners succeeded without
|
||||
* attempting to prevent default behavior. If any listener returns
|
||||
* false or called goog.events.Event#preventDefault, this returns
|
||||
* false.
|
||||
* @template EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.fireListeners = function(
|
||||
type, capture, eventObject) {};
|
||||
|
||||
|
||||
/**
|
||||
* Gets all listeners in this listenable for the given type and
|
||||
* capture mode.
|
||||
*
|
||||
* @param {string|!goog.events.EventId} type The type of the listeners to fire.
|
||||
* @param {boolean} capture The capture mode of the listeners to fire.
|
||||
* @return {!Array<!goog.events.ListenableKey>} An array of registered
|
||||
* listeners.
|
||||
* @template EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.getListeners = function(type, capture) {};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the goog.events.ListenableKey for the event or null if no such
|
||||
* listener is in use.
|
||||
*
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event
|
||||
* without the 'on' prefix.
|
||||
* @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The
|
||||
* listener function to get.
|
||||
* @param {boolean} capture Whether the listener is a capturing listener.
|
||||
* @param {SCOPE=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {?goog.events.ListenableKey} the found listener or null if not found.
|
||||
* @template SCOPE,EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.getListener = function(
|
||||
type, listener, capture, opt_listenerScope) {};
|
||||
|
||||
|
||||
/**
|
||||
* Whether there is any active listeners matching the specified
|
||||
* signature. If either the type or capture parameters are
|
||||
* unspecified, the function will match on the remaining criteria.
|
||||
*
|
||||
* @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.
|
||||
* @param {boolean=} opt_capture Whether to check for capture or bubble
|
||||
* listeners.
|
||||
* @return {boolean} Whether there is any active listeners matching
|
||||
* the requested type and/or capture phase.
|
||||
* @template EVENTOBJ
|
||||
*/
|
||||
goog.events.Listenable.prototype.hasListener = function(
|
||||
opt_type, opt_capture) {};
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview An interface that describes a single registered listener.
|
||||
*/
|
||||
goog.provide('goog.events.ListenableKey');
|
||||
|
||||
goog.requireType('goog.events.Listenable');
|
||||
|
||||
|
||||
/**
|
||||
* An interface that describes a single registered listener.
|
||||
* @interface
|
||||
*/
|
||||
goog.events.ListenableKey = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Counter used to create a unique key
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.events.ListenableKey.counter_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Reserves a key to be used for ListenableKey#key field.
|
||||
* @return {number} A number to be used to fill ListenableKey#key
|
||||
* field.
|
||||
*/
|
||||
goog.events.ListenableKey.reserveKey = function() {
|
||||
'use strict';
|
||||
return ++goog.events.ListenableKey.counter_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The source event target.
|
||||
* @type {?Object|?goog.events.Listenable}
|
||||
*/
|
||||
goog.events.ListenableKey.prototype.src;
|
||||
|
||||
|
||||
/**
|
||||
* The event type the listener is listening to.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.events.ListenableKey.prototype.type;
|
||||
|
||||
|
||||
/**
|
||||
* The listener function.
|
||||
* @type {function(?):?|{handleEvent:function(?):?}|null}
|
||||
*/
|
||||
goog.events.ListenableKey.prototype.listener;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the listener works on capture phase.
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.events.ListenableKey.prototype.capture;
|
||||
|
||||
|
||||
/**
|
||||
* The 'this' object for the listener function's scope.
|
||||
* @type {?Object|undefined}
|
||||
*/
|
||||
goog.events.ListenableKey.prototype.handler;
|
||||
|
||||
|
||||
/**
|
||||
* A globally unique number to identify the key.
|
||||
* @type {number}
|
||||
*/
|
||||
goog.events.ListenableKey.prototype.key;
|
||||
Executable
+124
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Listener object.
|
||||
* @see ../demos/events.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.Listener');
|
||||
|
||||
goog.require('goog.events.ListenableKey');
|
||||
goog.requireType('goog.events.Listenable');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simple class that stores information about a listener
|
||||
* @param {function(?):?} listener Callback function.
|
||||
* @param {Function} proxy Wrapper for the listener that patches the event.
|
||||
* @param {EventTarget|goog.events.Listenable} src Source object for
|
||||
* the event.
|
||||
* @param {string} type Event type.
|
||||
* @param {boolean} capture Whether in capture or bubble phase.
|
||||
* @param {Object=} opt_handler Object in whose context to execute the callback.
|
||||
* @implements {goog.events.ListenableKey}
|
||||
* @constructor
|
||||
*/
|
||||
goog.events.Listener = function(
|
||||
listener, proxy, src, type, capture, opt_handler) {
|
||||
'use strict';
|
||||
if (goog.events.Listener.ENABLE_MONITORING) {
|
||||
this.creationStack = new Error().stack;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
this.listener = listener;
|
||||
|
||||
/**
|
||||
* A wrapper over the original listener. This is used solely to
|
||||
* handle native browser events (it is used to simulate the capture
|
||||
* phase and to patch the event object).
|
||||
* @type {Function}
|
||||
*/
|
||||
this.proxy = proxy;
|
||||
|
||||
/**
|
||||
* Object or node that callback is listening to
|
||||
* @type {EventTarget|goog.events.Listenable}
|
||||
*/
|
||||
this.src = src;
|
||||
|
||||
/**
|
||||
* The event type.
|
||||
* @const {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* Whether the listener is being called in the capture or bubble phase
|
||||
* @const {boolean}
|
||||
*/
|
||||
this.capture = !!capture;
|
||||
|
||||
/**
|
||||
* Optional object whose context to execute the listener in
|
||||
* @type {Object|undefined}
|
||||
*/
|
||||
this.handler = opt_handler;
|
||||
|
||||
/**
|
||||
* The key of the listener.
|
||||
* @const {number}
|
||||
* @override
|
||||
*/
|
||||
this.key = goog.events.ListenableKey.reserveKey();
|
||||
|
||||
/**
|
||||
* Whether to remove the listener after it has been called.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.callOnce = false;
|
||||
|
||||
/**
|
||||
* Whether the listener has been removed.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.removed = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable the monitoring of the
|
||||
* goog.events.Listener instances. Switching on the monitoring is only
|
||||
* recommended for debugging because it has a significant impact on
|
||||
* performance and memory usage. If switched off, the monitoring code
|
||||
* compiles down to 0 bytes.
|
||||
*/
|
||||
goog.events.Listener.ENABLE_MONITORING =
|
||||
goog.define('goog.events.Listener.ENABLE_MONITORING', false);
|
||||
|
||||
|
||||
/**
|
||||
* If monitoring the goog.events.Listener instances is enabled, stores the
|
||||
* creation stack trace of the Disposable instance.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.events.Listener.prototype.creationStack;
|
||||
|
||||
|
||||
/**
|
||||
* Marks this listener as removed. This also remove references held by
|
||||
* this listener object (such as listener and event source).
|
||||
*/
|
||||
goog.events.Listener.prototype.markAsRemoved = function() {
|
||||
'use strict';
|
||||
this.removed = true;
|
||||
this.listener = null;
|
||||
this.proxy = null;
|
||||
this.src = null;
|
||||
this.handler = null;
|
||||
};
|
||||
Executable
+310
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview A map of listeners that provides utility functions to
|
||||
* deal with listeners on an event target. Used by
|
||||
* `goog.events.EventTarget`.
|
||||
*
|
||||
* WARNING: Do not use this class from outside goog.events package.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.events.ListenerMap');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events.Listener');
|
||||
goog.require('goog.object');
|
||||
goog.requireType('goog.events.EventId');
|
||||
goog.requireType('goog.events.Listenable');
|
||||
goog.requireType('goog.events.ListenableKey');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new listener map.
|
||||
* @param {EventTarget|goog.events.Listenable} src The src object.
|
||||
* @constructor
|
||||
* @final
|
||||
*/
|
||||
goog.events.ListenerMap = function(src) {
|
||||
'use strict';
|
||||
/** @type {EventTarget|goog.events.Listenable} */
|
||||
this.src = src;
|
||||
|
||||
/**
|
||||
* Maps of event type to an array of listeners.
|
||||
* @type {!Object<string, !Array<!goog.events.Listener>>}
|
||||
*/
|
||||
this.listeners = {};
|
||||
|
||||
/**
|
||||
* The count of types in this map that have registered listeners.
|
||||
* @private {number}
|
||||
*/
|
||||
this.typeCount_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The count of event types in this map that actually
|
||||
* have registered listeners.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.getTypeCount = function() {
|
||||
'use strict';
|
||||
return this.typeCount_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Total number of registered listeners.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.getListenerCount = function() {
|
||||
'use strict';
|
||||
var count = 0;
|
||||
for (var type in this.listeners) {
|
||||
count += this.listeners[type].length;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an event listener. A listener can only be added once to an
|
||||
* object and if it is added again the key for the listener is
|
||||
* returned.
|
||||
*
|
||||
* Note that a one-off listener will not change an existing listener,
|
||||
* if any. On the other hand a normal listener will change existing
|
||||
* one-off listener to become a normal listener.
|
||||
*
|
||||
* @param {string|!goog.events.EventId} type The listener event type.
|
||||
* @param {!Function} listener This listener callback method.
|
||||
* @param {boolean} callOnce Whether the listener is a one-off
|
||||
* listener.
|
||||
* @param {boolean=} opt_useCapture The capture mode of the listener.
|
||||
* @param {Object=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {!goog.events.ListenableKey} Unique key for the listener.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.add = function(
|
||||
type, listener, callOnce, opt_useCapture, opt_listenerScope) {
|
||||
'use strict';
|
||||
var typeStr = type.toString();
|
||||
var listenerArray = this.listeners[typeStr];
|
||||
if (!listenerArray) {
|
||||
listenerArray = this.listeners[typeStr] = [];
|
||||
this.typeCount_++;
|
||||
}
|
||||
|
||||
var listenerObj;
|
||||
var index = goog.events.ListenerMap.findListenerIndex_(
|
||||
listenerArray, listener, opt_useCapture, opt_listenerScope);
|
||||
if (index > -1) {
|
||||
listenerObj = listenerArray[index];
|
||||
if (!callOnce) {
|
||||
// Ensure that, if there is an existing callOnce listener, it is no
|
||||
// longer a callOnce listener.
|
||||
listenerObj.callOnce = false;
|
||||
}
|
||||
} else {
|
||||
listenerObj = new goog.events.Listener(
|
||||
listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope);
|
||||
listenerObj.callOnce = callOnce;
|
||||
listenerArray.push(listenerObj);
|
||||
}
|
||||
return listenerObj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a matching listener.
|
||||
* @param {string|!goog.events.EventId} type The listener event type.
|
||||
* @param {!Function} listener This listener callback method.
|
||||
* @param {boolean=} opt_useCapture The capture mode of the listener.
|
||||
* @param {Object=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {boolean} Whether any listener was removed.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.remove = function(
|
||||
type, listener, opt_useCapture, opt_listenerScope) {
|
||||
'use strict';
|
||||
var typeStr = type.toString();
|
||||
if (!(typeStr in this.listeners)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var listenerArray = this.listeners[typeStr];
|
||||
var index = goog.events.ListenerMap.findListenerIndex_(
|
||||
listenerArray, listener, opt_useCapture, opt_listenerScope);
|
||||
if (index > -1) {
|
||||
var listenerObj = listenerArray[index];
|
||||
listenerObj.markAsRemoved();
|
||||
goog.array.removeAt(listenerArray, index);
|
||||
if (listenerArray.length == 0) {
|
||||
delete this.listeners[typeStr];
|
||||
this.typeCount_--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the given listener object.
|
||||
* @param {!goog.events.ListenableKey} listener The listener to remove.
|
||||
* @return {boolean} Whether the listener is removed.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.removeByKey = function(listener) {
|
||||
'use strict';
|
||||
var type = listener.type;
|
||||
if (!(type in this.listeners)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var removed = goog.array.remove(this.listeners[type], listener);
|
||||
if (removed) {
|
||||
/** @type {!goog.events.Listener} */ (listener).markAsRemoved();
|
||||
if (this.listeners[type].length == 0) {
|
||||
delete this.listeners[type];
|
||||
this.typeCount_--;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all listeners from this map. If opt_type is provided, only
|
||||
* listeners that match the given type are removed.
|
||||
* @param {string|!goog.events.EventId=} opt_type Type of event to remove.
|
||||
* @return {number} Number of listeners removed.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.removeAll = function(opt_type) {
|
||||
'use strict';
|
||||
var typeStr = opt_type && opt_type.toString();
|
||||
var count = 0;
|
||||
for (var type in this.listeners) {
|
||||
if (!typeStr || type == typeStr) {
|
||||
var listenerArray = this.listeners[type];
|
||||
for (var i = 0; i < listenerArray.length; i++) {
|
||||
++count;
|
||||
listenerArray[i].markAsRemoved();
|
||||
}
|
||||
delete this.listeners[type];
|
||||
this.typeCount_--;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets all listeners that match the given type and capture mode. The
|
||||
* returned array is a copy (but the listener objects are not).
|
||||
* @param {string|!goog.events.EventId} type The type of the listeners
|
||||
* to retrieve.
|
||||
* @param {boolean} capture The capture mode of the listeners to retrieve.
|
||||
* @return {!Array<!goog.events.ListenableKey>} An array of matching
|
||||
* listeners.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.getListeners = function(type, capture) {
|
||||
'use strict';
|
||||
var listenerArray = this.listeners[type.toString()];
|
||||
var rv = [];
|
||||
if (listenerArray) {
|
||||
for (var i = 0; i < listenerArray.length; ++i) {
|
||||
var listenerObj = listenerArray[i];
|
||||
if (listenerObj.capture == capture) {
|
||||
rv.push(listenerObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the goog.events.ListenableKey for the event or null if no such
|
||||
* listener is in use.
|
||||
*
|
||||
* @param {string|!goog.events.EventId} type The type of the listener
|
||||
* to retrieve.
|
||||
* @param {!Function} listener The listener function to get.
|
||||
* @param {boolean} capture Whether the listener is a capturing listener.
|
||||
* @param {Object=} opt_listenerScope Object in whose scope to call the
|
||||
* listener.
|
||||
* @return {goog.events.ListenableKey} the found listener or null if not found.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.getListener = function(
|
||||
type, listener, capture, opt_listenerScope) {
|
||||
'use strict';
|
||||
var listenerArray = this.listeners[type.toString()];
|
||||
var i = -1;
|
||||
if (listenerArray) {
|
||||
i = goog.events.ListenerMap.findListenerIndex_(
|
||||
listenerArray, listener, capture, opt_listenerScope);
|
||||
}
|
||||
return i > -1 ? listenerArray[i] : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether there is a matching listener. If either the type or capture
|
||||
* parameters are unspecified, the function will match on the
|
||||
* remaining criteria.
|
||||
*
|
||||
* @param {string|!goog.events.EventId=} opt_type The type of the listener.
|
||||
* @param {boolean=} opt_capture The capture mode of the listener.
|
||||
* @return {boolean} Whether there is an active listener matching
|
||||
* the requested type and/or capture phase.
|
||||
*/
|
||||
goog.events.ListenerMap.prototype.hasListener = function(
|
||||
opt_type, opt_capture) {
|
||||
'use strict';
|
||||
var hasType = (opt_type !== undefined);
|
||||
var typeStr = hasType ? opt_type.toString() : '';
|
||||
var hasCapture = (opt_capture !== undefined);
|
||||
|
||||
return goog.object.some(this.listeners, function(listenerArray, type) {
|
||||
'use strict';
|
||||
for (var i = 0; i < listenerArray.length; ++i) {
|
||||
if ((!hasType || listenerArray[i].type == typeStr) &&
|
||||
(!hasCapture || listenerArray[i].capture == opt_capture)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Finds the index of a matching goog.events.Listener in the given
|
||||
* listenerArray.
|
||||
* @param {!Array<!goog.events.Listener>} listenerArray Array of listener.
|
||||
* @param {!Function} listener The listener function.
|
||||
* @param {boolean=} opt_useCapture The capture flag for the listener.
|
||||
* @param {Object=} opt_listenerScope The listener scope.
|
||||
* @return {number} The index of the matching listener within the
|
||||
* listenerArray.
|
||||
* @private
|
||||
*/
|
||||
goog.events.ListenerMap.findListenerIndex_ = function(
|
||||
listenerArray, listener, opt_useCapture, opt_listenerScope) {
|
||||
'use strict';
|
||||
for (var i = 0; i < listenerArray.length; ++i) {
|
||||
var listenerObj = listenerArray[i];
|
||||
if (!listenerObj.removed && listenerObj.listener == listener &&
|
||||
listenerObj.capture == !!opt_useCapture &&
|
||||
listenerObj.handler == opt_listenerScope) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Wrappers for the HTML5 File API. These wrappers closely mirror
|
||||
* the underlying APIs, but use Closure-style events and Deferred return values.
|
||||
* Their existence also makes it possible to mock the FileSystem API for testing
|
||||
* in browsers that don't support it natively.
|
||||
*
|
||||
* When adding public functions to anything under this namespace, be sure to add
|
||||
* its mock counterpart to goog.testing.fs.
|
||||
*/
|
||||
|
||||
goog.provide('goog.fs.blob');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Concatenates one or more values together and converts them to a Blob.
|
||||
*
|
||||
* @param {...(string|!Blob|!ArrayBuffer)} var_args The values that will make up
|
||||
* the resulting blob.
|
||||
* @return {!Blob} The blob.
|
||||
*/
|
||||
goog.fs.blob.getBlob = function(var_args) {
|
||||
'use strict';
|
||||
const BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
|
||||
|
||||
if (BlobBuilder !== undefined) {
|
||||
const bb = new BlobBuilder();
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
bb.append(arguments[i]);
|
||||
}
|
||||
return bb.getBlob();
|
||||
} else {
|
||||
return goog.fs.blob.getBlobWithProperties(
|
||||
Array.prototype.slice.call(arguments));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a blob with the given properties.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/Blob for more details.
|
||||
*
|
||||
* @param {!Array<string|!Blob|!ArrayBuffer>} parts The values that will make up
|
||||
* the resulting blob (subset supported by both BlobBuilder.append() and
|
||||
* Blob constructor).
|
||||
* @param {string=} opt_type The MIME type of the Blob.
|
||||
* @param {string=} opt_endings Specifies how strings containing newlines are to
|
||||
* be written out.
|
||||
* @return {!Blob} The blob.
|
||||
*/
|
||||
goog.fs.blob.getBlobWithProperties = function(parts, opt_type, opt_endings) {
|
||||
'use strict';
|
||||
const BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
|
||||
|
||||
if (BlobBuilder !== undefined) {
|
||||
const bb = new BlobBuilder();
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
bb.append(parts[i], opt_endings);
|
||||
}
|
||||
return bb.getBlob(opt_type);
|
||||
} else if (goog.global.Blob !== undefined) {
|
||||
const properties = {};
|
||||
if (opt_type) {
|
||||
properties['type'] = opt_type;
|
||||
}
|
||||
if (opt_endings) {
|
||||
properties['endings'] = opt_endings;
|
||||
}
|
||||
return new Blob(parts, properties);
|
||||
} else {
|
||||
throw new Error('This browser doesn\'t seem to support creating Blobs');
|
||||
}
|
||||
};
|
||||
Executable
+112
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Wrapper for URL and its createObjectUrl and revokeObjectUrl
|
||||
* methods that are part of the HTML5 File API.
|
||||
*/
|
||||
|
||||
goog.provide('goog.fs.url');
|
||||
|
||||
|
||||
/**
|
||||
* Creates a blob URL for a blob object.
|
||||
* Throws an error if the browser does not support Object Urls.
|
||||
*
|
||||
* @param {!File|!Blob|!MediaSource|!MediaStream} obj The object for which
|
||||
* to create the URL.
|
||||
* @return {string} The URL for the object.
|
||||
*/
|
||||
goog.fs.url.createObjectUrl = function(obj) {
|
||||
'use strict';
|
||||
return goog.fs.url.getUrlObject_().createObjectURL(obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Revokes a URL created by {@link goog.fs.url.createObjectUrl}.
|
||||
* Throws an error if the browser does not support Object Urls.
|
||||
*
|
||||
* @param {string} url The URL to revoke.
|
||||
* @return {void}
|
||||
*/
|
||||
goog.fs.url.revokeObjectUrl = function(url) {
|
||||
'use strict';
|
||||
goog.fs.url.getUrlObject_().revokeObjectURL(url);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @record
|
||||
* @private
|
||||
*/
|
||||
goog.fs.url.UrlObject_ = function() {};
|
||||
|
||||
/**
|
||||
* @param {!File|!Blob|!MediaSource|!MediaStream} arg
|
||||
* @return {string}
|
||||
*/
|
||||
goog.fs.url.UrlObject_.prototype.createObjectURL = function(arg) {};
|
||||
|
||||
/**
|
||||
* @param {string} s
|
||||
* @return {void}
|
||||
*/
|
||||
goog.fs.url.UrlObject_.prototype.revokeObjectURL = function(s) {};
|
||||
|
||||
|
||||
/**
|
||||
* Get the object that has the createObjectURL and revokeObjectURL functions for
|
||||
* this browser.
|
||||
*
|
||||
* @return {!goog.fs.url.UrlObject_} The object for this browser.
|
||||
* @private
|
||||
*/
|
||||
goog.fs.url.getUrlObject_ = function() {
|
||||
'use strict';
|
||||
const urlObject = goog.fs.url.findUrlObject_();
|
||||
if (urlObject != null) {
|
||||
return urlObject;
|
||||
} else {
|
||||
throw new Error('This browser doesn\'t seem to support blob URLs');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Finds the object that has the createObjectURL and revokeObjectURL functions
|
||||
* for this browser.
|
||||
*
|
||||
* @return {?goog.fs.url.UrlObject_} The object for this browser or null if the
|
||||
* browser does not support Object Urls.
|
||||
* @private
|
||||
*/
|
||||
goog.fs.url.findUrlObject_ = function() {
|
||||
'use strict';
|
||||
// This is what the spec says to do
|
||||
// http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL
|
||||
if (goog.global.URL !== undefined &&
|
||||
goog.global.URL.createObjectURL !== undefined) {
|
||||
return /** @type {!goog.fs.url.UrlObject_} */ (goog.global.URL);
|
||||
// This is what the spec used to say to do
|
||||
} else if (goog.global.createObjectURL !== undefined) {
|
||||
return /** @type {!goog.fs.url.UrlObject_} */ (goog.global);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether this browser supports Object Urls. If not, calls to
|
||||
* createObjectUrl and revokeObjectUrl will result in an error.
|
||||
*
|
||||
* @return {boolean} True if this browser supports Object Urls.
|
||||
*/
|
||||
goog.fs.url.browserSupportsObjectUrls = function() {
|
||||
'use strict';
|
||||
return goog.fs.url.findUrlObject_() != null;
|
||||
};
|
||||
Executable
+584
@@ -0,0 +1,584 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright The Closure Library Authors.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Utilities for creating functions. Loosely inspired by these
|
||||
* java classes from the Guava library:
|
||||
* com.google.common.base.Functions
|
||||
* https://google.github.io/guava/releases/snapshot-jre/api/docs/index.html?com/google/common/base/Functions.html
|
||||
*
|
||||
* com.google.common.base.Predicates
|
||||
* https://google.github.io/guava/releases/snapshot-jre/api/docs/index.html?com/google/common/base/Predicates.html
|
||||
*
|
||||
* More about these can be found at
|
||||
* https://github.com/google/guava/wiki/FunctionalExplained
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.functions');
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that always returns the same value.
|
||||
* @param {T} retValue The value to return.
|
||||
* @return {function():T} The new function.
|
||||
* @template T
|
||||
*/
|
||||
goog.functions.constant = function(retValue) {
|
||||
'use strict';
|
||||
return function() {
|
||||
'use strict';
|
||||
return retValue;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Always returns false.
|
||||
* @type {function(...): boolean}
|
||||
*/
|
||||
goog.functions.FALSE = function() {
|
||||
'use strict';
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Always returns true.
|
||||
* @type {function(...): boolean}
|
||||
*/
|
||||
goog.functions.TRUE = function() {
|
||||
'use strict';
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Always returns `null`.
|
||||
* @type {function(...): null}
|
||||
*/
|
||||
goog.functions.NULL = function() {
|
||||
'use strict';
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Always returns `undefined`.
|
||||
* @type {function(...): undefined}
|
||||
*/
|
||||
goog.functions.UNDEFINED = function() {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Always returns `undefined` (loosely-typed version).
|
||||
* @type {!Function}
|
||||
*/
|
||||
goog.functions.EMPTY = /** @type {?} */ (goog.functions.UNDEFINED);
|
||||
|
||||
|
||||
/**
|
||||
* A simple function that returns the first argument of whatever is passed
|
||||
* into it.
|
||||
* @param {T=} opt_returnValue The single value that will be returned.
|
||||
* @param {...*} var_args Optional trailing arguments. These are ignored.
|
||||
* @return {T} The first argument passed in, or undefined if nothing was passed.
|
||||
* @template T
|
||||
*/
|
||||
goog.functions.identity = function(opt_returnValue, var_args) {
|
||||
'use strict';
|
||||
return opt_returnValue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that always throws an error with the given message.
|
||||
* @param {string} message The error message.
|
||||
* @return {!Function} The error-throwing function.
|
||||
*/
|
||||
goog.functions.error = function(message) {
|
||||
'use strict';
|
||||
return function() {
|
||||
'use strict';
|
||||
throw new Error(message);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that throws the given object.
|
||||
* @param {*} err An object to be thrown.
|
||||
* @return {!Function} The error-throwing function.
|
||||
*/
|
||||
goog.functions.fail = function(err) {
|
||||
'use strict';
|
||||
return function() {
|
||||
'use strict';
|
||||
throw err;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a function, create a function that keeps opt_numArgs arguments and
|
||||
* silently discards all additional arguments.
|
||||
* @param {Function} f The original function.
|
||||
* @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
|
||||
* @return {!Function} A version of f that only keeps the first opt_numArgs
|
||||
* arguments.
|
||||
*/
|
||||
goog.functions.lock = function(f, opt_numArgs) {
|
||||
'use strict';
|
||||
opt_numArgs = opt_numArgs || 0;
|
||||
return function() {
|
||||
'use strict';
|
||||
const self = /** @type {*} */ (this);
|
||||
return f.apply(self, Array.prototype.slice.call(arguments, 0, opt_numArgs));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that returns its nth argument.
|
||||
* @param {number} n The position of the return argument.
|
||||
* @return {!Function} A new function.
|
||||
*/
|
||||
goog.functions.nth = function(n) {
|
||||
'use strict';
|
||||
return function() {
|
||||
'use strict';
|
||||
return arguments[n];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Like goog.partial(), except that arguments are added after arguments to the
|
||||
* returned function.
|
||||
*
|
||||
* Usage:
|
||||
* function f(arg1, arg2, arg3, arg4) { ... }
|
||||
* var g = goog.functions.partialRight(f, arg3, arg4);
|
||||
* g(arg1, arg2);
|
||||
*
|
||||
* @param {!Function} fn A function to partially apply.
|
||||
* @param {...*} var_args Additional arguments that are partially applied to fn
|
||||
* at the end.
|
||||
* @return {!Function} A partially-applied form of the function goog.partial()
|
||||
* was invoked as a method of.
|
||||
*/
|
||||
goog.functions.partialRight = function(fn, var_args) {
|
||||
'use strict';
|
||||
const rightArgs = Array.prototype.slice.call(arguments, 1);
|
||||
return function() {
|
||||
'use strict';
|
||||
// Even in strict mode, IE10/11 and Edge (non-Chromium) use global context
|
||||
// when free-calling functions. To catch cases where people were using this
|
||||
// erroneously, we explicitly change the context to undefined to match
|
||||
// strict mode specifications.
|
||||
let self = /** @type {*} */ (this);
|
||||
if (self === goog.global) {
|
||||
self = undefined;
|
||||
}
|
||||
const newArgs = Array.prototype.slice.call(arguments);
|
||||
newArgs.push.apply(newArgs, rightArgs);
|
||||
return fn.apply(self, newArgs);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a function, create a new function that swallows its return value
|
||||
* and replaces it with a new one.
|
||||
* @param {Function} f A function.
|
||||
* @param {T} retValue A new return value.
|
||||
* @return {function(...?):T} A new function.
|
||||
* @template T
|
||||
*/
|
||||
goog.functions.withReturnValue = function(f, retValue) {
|
||||
'use strict';
|
||||
return goog.functions.sequence(f, goog.functions.constant(retValue));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that returns whether its argument equals the given value.
|
||||
*
|
||||
* Example:
|
||||
* var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
|
||||
*
|
||||
* @param {*} value The value to compare to.
|
||||
* @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
|
||||
* comparison rather than a strict (===) one. Defaults to false.
|
||||
* @return {function(*):boolean} The new function.
|
||||
*/
|
||||
goog.functions.equalTo = function(value, opt_useLooseComparison) {
|
||||
'use strict';
|
||||
return function(other) {
|
||||
'use strict';
|
||||
return opt_useLooseComparison ? (value == other) : (value === other);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the composition of the functions passed in.
|
||||
* For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
|
||||
* @param {function(...?):T} fn The final function.
|
||||
* @param {...Function} var_args A list of functions.
|
||||
* @return {function(...?):T} The composition of all inputs.
|
||||
* @template T
|
||||
*/
|
||||
goog.functions.compose = function(fn, var_args) {
|
||||
'use strict';
|
||||
const functions = arguments;
|
||||
const length = functions.length;
|
||||
return function() {
|
||||
'use strict';
|
||||
const self = /** @type {*} */ (this);
|
||||
let result;
|
||||
if (length) {
|
||||
result = functions[length - 1].apply(self, arguments);
|
||||
}
|
||||
|
||||
for (let i = length - 2; i >= 0; i--) {
|
||||
result = functions[i].call(self, result);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that calls the functions passed in in sequence, and
|
||||
* returns the value of the last function. For example,
|
||||
* (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
|
||||
* @param {...Function} var_args A list of functions.
|
||||
* @return {!Function} A function that calls all inputs in sequence.
|
||||
*/
|
||||
goog.functions.sequence = function(var_args) {
|
||||
'use strict';
|
||||
const functions = arguments;
|
||||
const length = functions.length;
|
||||
return function() {
|
||||
'use strict';
|
||||
const self = /** @type {*} */ (this);
|
||||
let result;
|
||||
for (let i = 0; i < length; i++) {
|
||||
result = functions[i].apply(self, arguments);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that returns true if each of its components evaluates
|
||||
* to true. The components are evaluated in order, and the evaluation will be
|
||||
* short-circuited as soon as a function returns false.
|
||||
* For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
|
||||
* @param {...Function} var_args A list of functions.
|
||||
* @return {function(...?):boolean} A function that ANDs its component
|
||||
* functions.
|
||||
*/
|
||||
goog.functions.and = function(var_args) {
|
||||
'use strict';
|
||||
const functions = arguments;
|
||||
const length = functions.length;
|
||||
return function() {
|
||||
'use strict';
|
||||
const self = /** @type {*} */ (this);
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (!functions[i].apply(self, arguments)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that returns true if any of its components evaluates
|
||||
* to true. The components are evaluated in order, and the evaluation will be
|
||||
* short-circuited as soon as a function returns true.
|
||||
* For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
|
||||
* @param {...Function} var_args A list of functions.
|
||||
* @return {function(...?):boolean} A function that ORs its component
|
||||
* functions.
|
||||
*/
|
||||
goog.functions.or = function(var_args) {
|
||||
'use strict';
|
||||
const functions = arguments;
|
||||
const length = functions.length;
|
||||
return function() {
|
||||
'use strict';
|
||||
const self = /** @type {*} */ (this);
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (functions[i].apply(self, arguments)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that returns the Boolean opposite of a provided function.
|
||||
* For example, (goog.functions.not(f))(x) is equivalent to !f(x).
|
||||
* @param {!Function} f The original function.
|
||||
* @return {function(...?):boolean} A function that delegates to f and returns
|
||||
* opposite.
|
||||
*/
|
||||
goog.functions.not = function(f) {
|
||||
'use strict';
|
||||
return function() {
|
||||
'use strict';
|
||||
const self = /** @type {*} */ (this);
|
||||
return !f.apply(self, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generic factory function to construct an object given the constructor
|
||||
* and the arguments. Intended to be bound to create object factories.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var factory = goog.partial(goog.functions.create, Class);
|
||||
*
|
||||
* @param {function(new:T, ...)} constructor The constructor for the Object.
|
||||
* @param {...*} var_args The arguments to be passed to the constructor.
|
||||
* @return {T} A new instance of the class given in `constructor`.
|
||||
* @template T
|
||||
* @deprecated This function does not work with ES6 class constructors. Use
|
||||
* arrow functions + spread args instead.
|
||||
*/
|
||||
goog.functions.create = function(constructor, var_args) {
|
||||
'use strict';
|
||||
/**
|
||||
* @constructor
|
||||
* @final
|
||||
*/
|
||||
const temp = function() {};
|
||||
temp.prototype = constructor.prototype;
|
||||
|
||||
// obj will have constructor's prototype in its chain and
|
||||
// 'obj instanceof constructor' will be true.
|
||||
const obj = new temp();
|
||||
|
||||
// obj is initialized by constructor.
|
||||
// arguments is only array-like so lacks shift(), but can be used with
|
||||
// the Array prototype function.
|
||||
constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether the return value cache should be used.
|
||||
* This should only be used to disable caches when testing.
|
||||
*/
|
||||
goog.functions.CACHE_RETURN_VALUE =
|
||||
goog.define('goog.functions.CACHE_RETURN_VALUE', true);
|
||||
|
||||
|
||||
/**
|
||||
* Gives a wrapper function that caches the return value of a parameterless
|
||||
* function when first called.
|
||||
*
|
||||
* When called for the first time, the given function is called and its
|
||||
* return value is cached (thus this is only appropriate for idempotent
|
||||
* functions). Subsequent calls will return the cached return value. This
|
||||
* allows the evaluation of expensive functions to be delayed until first used.
|
||||
*
|
||||
* To cache the return values of functions with parameters, see goog.memoize.
|
||||
*
|
||||
* @param {function():T} fn A function to lazily evaluate.
|
||||
* @return {function():T} A wrapped version the function.
|
||||
* @template T
|
||||
*/
|
||||
goog.functions.cacheReturnValue = function(fn) {
|
||||
'use strict';
|
||||
let called = false;
|
||||
let value;
|
||||
|
||||
return function() {
|
||||
'use strict';
|
||||
if (!goog.functions.CACHE_RETURN_VALUE) {
|
||||
return fn();
|
||||
}
|
||||
|
||||
if (!called) {
|
||||
value = fn();
|
||||
called = true;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a function to allow it to be called, at most, once. All
|
||||
* additional calls are no-ops.
|
||||
*
|
||||
* This is particularly useful for initialization functions
|
||||
* that should be called, at most, once.
|
||||
*
|
||||
* @param {function():*} f Function to call.
|
||||
* @return {function():undefined} Wrapped function.
|
||||
*/
|
||||
goog.functions.once = function(f) {
|
||||
'use strict';
|
||||
// Keep a reference to the function that we null out when we're done with
|
||||
// it -- that way, the function can be GC'd when we're done with it.
|
||||
let inner = f;
|
||||
return function() {
|
||||
'use strict';
|
||||
if (inner) {
|
||||
const tmp = inner;
|
||||
inner = null;
|
||||
tmp();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a function to allow it to be called, at most, once per interval
|
||||
* (specified in milliseconds). If the wrapper function is called N times within
|
||||
* that interval, only the Nth call will go through.
|
||||
*
|
||||
* This is particularly useful for batching up repeated actions where the
|
||||
* last action should win. This can be used, for example, for refreshing an
|
||||
* autocomplete pop-up every so often rather than updating with every keystroke,
|
||||
* since the final text typed by the user is the one that should produce the
|
||||
* final autocomplete results. For more stateful debouncing with support for
|
||||
* pausing, resuming, and canceling debounced actions, use
|
||||
* `goog.async.Debouncer`.
|
||||
*
|
||||
* @param {function(this:SCOPE, ...?)} f Function to call.
|
||||
* @param {number} interval Interval over which to debounce. The function will
|
||||
* only be called after the full interval has elapsed since the last call.
|
||||
* @param {SCOPE=} opt_scope Object in whose scope to call the function.
|
||||
* @return {function(...?): undefined} Wrapped function.
|
||||
* @template SCOPE
|
||||
*/
|
||||
goog.functions.debounce = function(f, interval, opt_scope) {
|
||||
'use strict';
|
||||
let timeout = 0;
|
||||
return /** @type {function(...?)} */ (function(var_args) {
|
||||
'use strict';
|
||||
goog.global.clearTimeout(timeout);
|
||||
const args = arguments;
|
||||
timeout = goog.global.setTimeout(function() {
|
||||
'use strict';
|
||||
f.apply(opt_scope, args);
|
||||
}, interval);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a function to allow it to be called, at most, once per interval
|
||||
* (specified in milliseconds). If the wrapper function is called N times in
|
||||
* that interval, both the 1st and the Nth calls will go through.
|
||||
*
|
||||
* This is particularly useful for limiting repeated user requests where the
|
||||
* the last action should win, but you also don't want to wait until the end of
|
||||
* the interval before sending a request out, as it leads to a perception of
|
||||
* slowness for the user.
|
||||
*
|
||||
* @param {function(this:SCOPE, ...?)} f Function to call.
|
||||
* @param {number} interval Interval over which to throttle. The function can
|
||||
* only be called once per interval.
|
||||
* @param {SCOPE=} opt_scope Object in whose scope to call the function.
|
||||
* @return {function(...?): undefined} Wrapped function.
|
||||
* @template SCOPE
|
||||
*/
|
||||
goog.functions.throttle = function(f, interval, opt_scope) {
|
||||
'use strict';
|
||||
let timeout = 0;
|
||||
let shouldFire = false;
|
||||
let storedArgs = [];
|
||||
|
||||
const handleTimeout = function() {
|
||||
'use strict';
|
||||
timeout = 0;
|
||||
if (shouldFire) {
|
||||
shouldFire = false;
|
||||
fire();
|
||||
}
|
||||
};
|
||||
|
||||
const fire = function() {
|
||||
'use strict';
|
||||
timeout = goog.global.setTimeout(handleTimeout, interval);
|
||||
let args = storedArgs;
|
||||
storedArgs = []; // Avoid a space leak by clearing stored arguments.
|
||||
f.apply(opt_scope, args);
|
||||
};
|
||||
|
||||
return /** @type {function(...?)} */ (function(var_args) {
|
||||
'use strict';
|
||||
storedArgs = arguments;
|
||||
if (!timeout) {
|
||||
fire();
|
||||
} else {
|
||||
shouldFire = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a function to allow it to be called, at most, once per interval
|
||||
* (specified in milliseconds). If the wrapper function is called N times within
|
||||
* that interval, only the 1st call will go through.
|
||||
*
|
||||
* This is particularly useful for limiting repeated user requests where the
|
||||
* first request is guaranteed to have all the data required to perform the
|
||||
* final action, so there's no need to wait until the end of the interval before
|
||||
* sending the request out.
|
||||
*
|
||||
* @param {function(this:SCOPE, ...?)} f Function to call.
|
||||
* @param {number} interval Interval over which to rate-limit. The function will
|
||||
* only be called once per interval, and ignored for the remainer of the
|
||||
* interval.
|
||||
* @param {SCOPE=} opt_scope Object in whose scope to call the function.
|
||||
* @return {function(...?): undefined} Wrapped function.
|
||||
* @template SCOPE
|
||||
*/
|
||||
goog.functions.rateLimit = function(f, interval, opt_scope) {
|
||||
'use strict';
|
||||
let timeout = 0;
|
||||
|
||||
const handleTimeout = function() {
|
||||
'use strict';
|
||||
timeout = 0;
|
||||
};
|
||||
|
||||
return /** @type {function(...?)} */ (function(var_args) {
|
||||
'use strict';
|
||||
if (!timeout) {
|
||||
timeout = goog.global.setTimeout(handleTimeout, interval);
|
||||
f.apply(opt_scope, arguments);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the specified value is a function.
|
||||
* @param {*} val Variable to test.
|
||||
* @return {boolean} Whether variable is a function.
|
||||
*/
|
||||
goog.functions.isFunction = (val) => {
|
||||
return typeof val === 'function';
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user