aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoam Postavsky2019-05-27 19:05:56 -0400
committerNoam Postavsky2019-05-30 18:46:07 -0400
commit5f01af6c8e0f7355f7a99a80ff32369071f65eda (patch)
treef65280a7140425f0db5ad19782c699a0def2bed5
parent4b24b0185d910d756e85ecdc30f49c414577050e (diff)
downloademacs-5f01af6c8e0f7355f7a99a80ff32369071f65eda.tar.gz
emacs-5f01af6c8e0f7355f7a99a80ff32369071f65eda.zip
Use plain symbols for eieio type descriptors (Bug#29220)
Since Emacs 26, eieio objects use a class record (with circular references) as the type descriptor of the object record. This causes problems when reading back an object from a string, because the class record is not `eq' to the canonical one (which means that read objects don't satisfy the foo-p predicate). * lisp/emacs-lisp/eieio.el (make-instance): As a (partial) fix, set the record's type descriptor to a plain symbol for the type descriptor when eieio-backward-compatibility is non-nil (the default). * lisp/emacs-lisp/eieio-core.el (eieio--object-class): Call eieio--class-object on the type tag when eieio-backward-compatibility is non-nil. (eieio-object-p): Use eieio--object-class instead of eieio--object-class-tag. * test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el (eieio-test-persist-hash-and-vector) (eieio-test-persist-interior-lists): Make into functions. (eieio-persist-hash-and-vector-backward-compatibility) (eieio-persist-hash-and-vector-no-backward-compatibility) (eieio-test-persist-interior-lists-backward-compatibility) (eieio-test-persist-interior-lists-no-backward-compatibility): New tests which call them, eieio-backward-compatibility let-bound.
-rw-r--r--lisp/emacs-lisp/eieio-core.el11
-rw-r--r--lisp/emacs-lisp/eieio.el3
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el28
3 files changed, 32 insertions, 10 deletions
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index f879a3999fb..4d55ed6e1d1 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -117,9 +117,6 @@ Currently under control of this var:
117(defsubst eieio--object-class-tag (obj) 117(defsubst eieio--object-class-tag (obj)
118 (aref obj 0)) 118 (aref obj 0))
119 119
120(defsubst eieio--object-class (obj)
121 (eieio--object-class-tag obj))
122
123 120
124;;; Important macros used internally in eieio. 121;;; Important macros used internally in eieio.
125 122
@@ -132,6 +129,12 @@ Currently under control of this var:
132 (or (cl--find-class class) class) 129 (or (cl--find-class class) class)
133 class)) 130 class))
134 131
132(defsubst eieio--object-class (obj)
133 (let ((tag (eieio--object-class-tag obj)))
134 (if eieio-backward-compatibility
135 (eieio--class-object tag)
136 tag)))
137
135(defun class-p (x) 138(defun class-p (x)
136 "Return non-nil if X is a valid class vector. 139 "Return non-nil if X is a valid class vector.
137X can also be is a symbol." 140X can also be is a symbol."
@@ -163,7 +166,7 @@ Return nil if that option doesn't exist."
163(defun eieio-object-p (obj) 166(defun eieio-object-p (obj)
164 "Return non-nil if OBJ is an EIEIO object." 167 "Return non-nil if OBJ is an EIEIO object."
165 (and (recordp obj) 168 (and (recordp obj)
166 (eieio--class-p (eieio--object-class-tag obj)))) 169 (eieio--class-p (eieio--object-class obj))))
167 170
168(define-obsolete-function-alias 'object-p 'eieio-object-p "25.1") 171(define-obsolete-function-alias 'object-p 'eieio-object-p "25.1")
169 172
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 38436d1f944..864ac2616b9 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -710,6 +710,9 @@ calls `initialize-instance' on that object."
710 ;; Call the initialize method on the new object with the slots 710 ;; Call the initialize method on the new object with the slots
711 ;; that were passed down to us. 711 ;; that were passed down to us.
712 (initialize-instance new-object slots) 712 (initialize-instance new-object slots)
713 (when eieio-backward-compatibility
714 ;; Use symbol as type descriptor, for backwards compatibility.
715 (aset new-object 0 class))
713 ;; Return the created object. 716 ;; Return the created object.
714 new-object)) 717 new-object))
715 718
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
index dfaa031844f..b87914c75e7 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
@@ -277,7 +277,7 @@ persistent class.")
277 :type vector 277 :type vector
278 :initarg :random-vector))) 278 :initarg :random-vector)))
279 279
280(ert-deftest eieio-test-persist-hash-and-vector () 280(defun eieio-test-persist-hash-and-vector ()
281 (let* ((jane (make-instance 'person :name "Jane")) 281 (let* ((jane (make-instance 'person :name "Jane"))
282 (bob (make-instance 'person :name "Bob")) 282 (bob (make-instance 'person :name "Bob"))
283 (hans (make-instance 'person :name "Hans")) 283 (hans (make-instance 'person :name "Hans"))
@@ -297,10 +297,18 @@ persistent class.")
297 (aset (car (slot-value class 'janitors)) 1 hans) 297 (aset (car (slot-value class 'janitors)) 1 hans)
298 (aset (nth 1 (slot-value class 'janitors)) 1 dierdre) 298 (aset (nth 1 (slot-value class 'janitors)) 1 dierdre)
299 (unwind-protect 299 (unwind-protect
300 ;; FIXME: This should not error. 300 (persist-test-save-and-compare class)
301 (should-error (persist-test-save-and-compare class))
302 (delete-file (oref class file))))) 301 (delete-file (oref class file)))))
303 302
303(ert-deftest eieio-persist-hash-and-vector-backward-compatibility ()
304 (let ((eieio-backward-compatibility t)) ; The default.
305 (eieio-test-persist-hash-and-vector)))
306
307(ert-deftest eieio-persist-hash-and-vector-no-backward-compatibility ()
308 :expected-result :failed ;; Bug#29220.
309 (let ((eieio-backward-compatibility nil))
310 (eieio-test-persist-hash-and-vector)))
311
304;; Extra quotation of lists inside other objects (Gnus registry), also 312;; Extra quotation of lists inside other objects (Gnus registry), also
305;; bug#29220. 313;; bug#29220.
306 314
@@ -315,7 +323,7 @@ persistent class.")
315 :initarg :htab 323 :initarg :htab
316 :type hash-table))) 324 :type hash-table)))
317 325
318(ert-deftest eieio-test-persist-interior-lists () 326(defun eieio-test-persist-interior-lists ()
319 (let* ((thing (make-instance 327 (let* ((thing (make-instance
320 'eieio-container 328 'eieio-container
321 :vec [nil] 329 :vec [nil]
@@ -335,8 +343,16 @@ persistent class.")
335 (setf (nth 2 (cadar alst)) john 343 (setf (nth 2 (cadar alst)) john
336 (nth 2 (cadadr alst)) alexie) 344 (nth 2 (cadadr alst)) alexie)
337 (unwind-protect 345 (unwind-protect
338 ;; FIXME: Should not error. 346 (persist-test-save-and-compare thing)
339 (should-error (persist-test-save-and-compare thing))
340 (delete-file (slot-value thing 'file))))) 347 (delete-file (slot-value thing 'file)))))
341 348
349(ert-deftest eieio-test-persist-interior-lists-backward-compatibility ()
350 (let ((eieio-backward-compatibility t)) ; The default.
351 (eieio-test-persist-interior-lists)))
352
353(ert-deftest eieio-test-persist-interior-lists-no-backward-compatibility ()
354 :expected-result :failed ;; Bug#29220.
355 (let ((eieio-backward-compatibility nil))
356 (eieio-test-persist-interior-lists)))
357
342;;; eieio-test-persist.el ends here 358;;; eieio-test-persist.el ends here