|
1132 | 1132 |
|
1133 | 1133 | (-freeze-without-meta! (into {} x) out))) |
1134 | 1134 |
|
1135 | | -(let [munged-name (enc/fmemoize #(munge (name %))) |
1136 | | - get-basis |
1137 | | - (do #_enc/fmemoize ; Small perf benefit not worth the loss of dynamism |
1138 | | - (fn [^java.lang.Class aclass] |
1139 | | - (let [basis-method (.getMethod aclass "getBasis" nil)] |
1140 | | - (.invoke basis-method nil nil))))] |
1141 | | - |
1142 | | - (freezer IType nil true |
1143 | | - (let [aclass (class x) |
1144 | | - class-name (.getName aclass)] |
1145 | | - (write-id out id-type) |
1146 | | - (write-str out class-name) |
1147 | | - (-run! |
1148 | | - (fn [b] |
1149 | | - (let [^Field cfield (.getField aclass (munged-name b))] |
1150 | | - (-freeze-without-meta! (.get cfield x) out))) |
1151 | | - (get-basis aclass))))) |
1152 | | - |
1153 | | -(comment (do (deftype T1 [x]) (.invoke (.getMethod (class (T1. :x)) "getBasis" nil) nil nil))) |
| 1135 | +(def ^:private get-basis-fields |
| 1136 | + "Returns [`java.lang.reflect.Field` ...] for given class." |
| 1137 | + (enc/fmemoize |
| 1138 | + (fn [^Class c] ; Auto invalidated on `deftype` redef, etc. |
| 1139 | + (let [basis (.invoke (.getMethod c "getBasis" nil) nil nil)] |
| 1140 | + (mapv |
| 1141 | + (fn [f] |
| 1142 | + (let [field (.getDeclaredField c (munge (name f)))] |
| 1143 | + (.setAccessible field true) |
| 1144 | + (do field))) |
| 1145 | + basis))))) |
| 1146 | + |
| 1147 | +(freezer IType nil true |
| 1148 | + (let [c (class x)] |
| 1149 | + (write-id out id-type) |
| 1150 | + (write-str out (.getName c)) |
| 1151 | + (-run! (fn [^java.lang.reflect.Field f] (-freeze-without-meta! (.get f x) out)) |
| 1152 | + (get-basis-fields c)))) |
| 1153 | + |
| 1154 | +(comment |
| 1155 | + (do (deftype T1 [x]) (let [t1 (T1. :x)] (get-basis-fields (class t1)))) |
| 1156 | + (do (deftype T2 [^:unsynchronized-mutable x]) (let [t2 (T2. :x)] (get-basis-fields (class t2))))) |
1154 | 1157 |
|
1155 | 1158 | (enc/compile-if java.time.Instant |
1156 | 1159 | (freezer java.time.Instant id-time-instant true |
|
1404 | 1407 |
|
1405 | 1408 | (defn- read-kvs-depr [to ^DataInput in] (read-kvs-into to in (quot (.readInt in) 2))) |
1406 | 1409 |
|
1407 | | -(def ^:private class-method-sig (into-array Class [IPersistentMap])) |
1408 | | - |
1409 | 1410 | (defn- read-custom! [in prefixed? type-id] |
1410 | 1411 | (if-let [custom-reader (get *custom-readers* type-id)] |
1411 | 1412 | (try |
|
1497 | 1498 | "Cannot thaw object: `taoensso.nippy/*thaw-serializable-allowlist*` check failed. This is a security feature. See `*thaw-serializable-allowlist*` docstring or https://github.com/ptaoussanis/nippy/issues/130 for details!" |
1498 | 1499 | {:class-name class-name}))) |
1499 | 1500 |
|
1500 | | -(defn- read-record [in class-name] |
1501 | | - (let [content (thaw-from-in! in)] |
1502 | | - (try |
1503 | | - (let [class (clojure.lang.RT/classForName class-name) |
1504 | | - method (.getMethod class "create" class-method-sig)] |
1505 | | - (.invoke method class (into-array Object [content]))) |
1506 | | - (catch Exception e |
1507 | | - {:nippy/unthawable |
1508 | | - {:type :record |
1509 | | - :cause :exception |
| 1501 | +(let [class-method-sig (into-array Class [IPersistentMap])] |
| 1502 | + (defn- read-record [in class-name] |
| 1503 | + (let [content (thaw-from-in! in)] |
| 1504 | + (try |
| 1505 | + (let [c (clojure.lang.RT/classForName class-name) |
| 1506 | + ctr (.getMethod c "create" class-method-sig)] |
| 1507 | + (.invoke ctr c (into-array Object [content]))) |
| 1508 | + (catch Exception e |
| 1509 | + {:nippy/unthawable |
| 1510 | + {:type :record |
| 1511 | + :cause :exception |
1510 | 1512 |
|
1511 | | - :class-name class-name |
1512 | | - :content content |
1513 | | - :exception e}})))) |
| 1513 | + :class-name class-name |
| 1514 | + :content content |
| 1515 | + :exception e}}))))) |
1514 | 1516 |
|
1515 | 1517 | (defn- read-type [in class-name] |
1516 | 1518 | (try |
1517 | | - (let [aclass (clojure.lang.RT/classForName class-name) |
1518 | | - nbasis |
1519 | | - (let [basis-method (.getMethod aclass "getBasis" nil) |
1520 | | - basis (.invoke basis-method nil nil)] |
1521 | | - (count basis)) |
| 1519 | + (let [c (clojure.lang.RT/classForName class-name) |
| 1520 | + num-fields (count (get-basis-fields c)) |
| 1521 | + field-vals (object-array num-fields) |
1522 | 1522 |
|
1523 | | - cvalues (object-array nbasis)] |
| 1523 | + ;; Ref. <https://github.com/clojure/clojure/blob/e78519c174fb506afa70e236af509e73160f022a/src/jvm/clojure/lang/Compiler.java#L4799> |
| 1524 | + ^Constructor ctr (aget (.getConstructors c) 0)] |
1524 | 1525 |
|
1525 | 1526 | (enc/reduce-n |
1526 | | - (fn [_ i] (aset cvalues i (thaw-from-in! in))) |
1527 | | - nil nbasis) |
| 1527 | + (fn [_ i] (aset field-vals i (thaw-from-in! in))) |
| 1528 | + nil num-fields) |
1528 | 1529 |
|
1529 | | - (let [ctors (.getConstructors aclass) |
1530 | | - ^Constructor ctor (aget ctors 0) ; Impl. detail? Ref. <https://goo.gl/XWmckR> |
1531 | | - ] |
1532 | | - (.newInstance ctor cvalues))) |
| 1530 | + (.newInstance ctr field-vals)) |
1533 | 1531 |
|
1534 | 1532 | (catch Exception e |
1535 | 1533 | {:nippy/unthawable |
|
1997 | 1995 |
|
1998 | 1996 | ;;;; Stress data |
1999 | 1997 |
|
2000 | | -(defrecord StressRecord [my-data]) |
2001 | | -(deftype StressType [my-data] |
2002 | | - Object (equals [a b] (and (instance? StressType b) (= (.-my-data a) |
2003 | | - (.-my-data ^StressType b))))) |
| 1998 | +(defrecord StressRecord [x]) |
| 1999 | +(deftype StressType [x ^:unsynchronized-mutable y] |
| 2000 | + clojure.lang.IDeref (deref [_] [x y]) |
| 2001 | + Object (equals [_ other] (and (instance? StressType other) (= [x y] @other)))) |
2004 | 2002 |
|
2005 | 2003 | (defn stress-data |
2006 | 2004 | "Returns map of reference stress data for use by tests, benchmarks, etc." |
|
2054 | 2052 | :uuid (java.util.UUID. 7232453380187312026 -7067939076204274491) |
2055 | 2053 | :uri (java.net.URI. "https://clojure.org") |
2056 | 2054 | :defrecord (StressRecord. "data") |
2057 | | - :deftype (StressType. "data") |
| 2055 | + :deftype (StressType. "normal field" "private field") |
2058 | 2056 |
|
2059 | 2057 | :util-date (java.util.Date. 1577884455500) |
2060 | 2058 | :sql-date (java.sql.Date. 1577884455500) |
|
0 commit comments