aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoam Postavsky2017-07-13 00:42:38 -0400
committerNoam Postavsky2017-08-07 18:54:49 -0400
commit79a74568e9166f63a12adb30f54edcd57a6405a3 (patch)
treef228a53ad54805030c7bde905604aa4a4d08b816
parentb5c8e9898d9dbd4145c40d08e8eef84a5e32008a (diff)
downloademacs-79a74568e9166f63a12adb30f54edcd57a6405a3.tar.gz
emacs-79a74568e9166f63a12adb30f54edcd57a6405a3.zip
Don't define gv expanders in compiler's runtime (Bug#27016)
This prevents definitions being compiled from leaking into the current Emacs doing the compilation. * lisp/emacs-lisp/gv.el (gv-define-expander): Use function-put instead of `put' with `eval-and-compile'. * test/lisp/emacs-lisp/gv-tests.el: New tests.
-rw-r--r--lisp/emacs-lisp/gv.el7
-rw-r--r--test/lisp/emacs-lisp/gv-tests.el147
2 files changed, 148 insertions, 6 deletions
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 27376fc7f95..a8b8974cb4f 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -146,12 +146,7 @@ NAME is a symbol: the name of a function, macro, or special form.
146HANDLER is a function which takes an argument DO followed by the same 146HANDLER is a function which takes an argument DO followed by the same
147arguments as NAME. DO is a function as defined in `gv-get'." 147arguments as NAME. DO is a function as defined in `gv-get'."
148 (declare (indent 1) (debug (sexp form))) 148 (declare (indent 1) (debug (sexp form)))
149 ;; Use eval-and-compile so the method can be used in the same file as it 149 `(function-put ',name 'gv-expander ,handler))
150 ;; is defined.
151 ;; FIXME: Just like byte-compile-macro-environment, we should have something
152 ;; like byte-compile-symbolprop-environment so as to handle these things
153 ;; cleanly without affecting the running Emacs.
154 `(eval-and-compile (put ',name 'gv-expander ,handler)))
155 150
156;;;###autoload 151;;;###autoload
157(defun gv--defun-declaration (symbol name args handler &optional fix) 152(defun gv--defun-declaration (symbol name args handler &optional fix)
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
new file mode 100644
index 00000000000..f19af024b57
--- /dev/null
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -0,0 +1,147 @@
1;;; gv-tests.el --- tests for gv.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2017 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23(eval-when-compile (require 'cl-lib))
24
25(cl-defmacro gv-tests--in-temp-dir ((elvar elcvar)
26 (&rest filebody)
27 &rest body)
28 (declare (indent 2))
29 `(let ((default-directory (make-temp-file "gv-test" t)))
30 (unwind-protect
31 (let ((,elvar "gv-test-deffoo.el")
32 (,elcvar "gv-test-deffoo.elc"))
33 (with-temp-file ,elvar
34 (insert ";; -*- lexical-binding: t; -*-\n")
35 (dolist (form ',filebody)
36 (pp form (current-buffer))))
37 ,@body)
38 (delete-directory default-directory t))))
39
40(ert-deftest gv-define-expander-in-file ()
41 (gv-tests--in-temp-dir (el elc)
42 ((gv-define-setter gv-test-foo (newval cons)
43 `(setcar ,cons ,newval))
44 (defvar gv-test-pair (cons 1 2))
45 (setf (gv-test-foo gv-test-pair) 99)
46 (message "%d" (car gv-test-pair)))
47 (with-temp-buffer
48 (call-process (concat invocation-directory invocation-name)
49 nil '(t t) nil
50 "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
51 "-l" elc)
52 (should (equal (buffer-string) "99\n")))))
53
54(ert-deftest gv-define-expander-in-file-twice ()
55 (gv-tests--in-temp-dir (el elc)
56 ((gv-define-setter gv-test-foo (newval cons)
57 `(setcar ,cons ,newval))
58 (defvar gv-test-pair (cons 1 2))
59 (setf (gv-test-foo gv-test-pair) 99)
60 (gv-define-setter gv-test-foo (newval cons)
61 `(setcdr ,cons ,newval))
62 (setf (gv-test-foo gv-test-pair) 42)
63 (message "%S" gv-test-pair))
64 (with-temp-buffer
65 (call-process (concat invocation-directory invocation-name)
66 nil '(t t) nil
67 "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
68 "-l" elc)
69 (should (equal (buffer-string) "(99 . 42)\n")))))
70
71(ert-deftest gv-dont-define-expander-in-file ()
72 ;; The expander is defined while we are compiling the file, even
73 ;; though it's inside (when nil ...) because the compiler won't
74 ;; analyze the conditional.
75 :expected-result :failed
76 (gv-tests--in-temp-dir (el elc)
77 ((when nil (gv-define-setter gv-test-foo (newval cons)
78 `(setcar ,cons ,newval)))
79 (defvar gv-test-pair (cons 1 2))
80 (setf (gv-test-foo gv-test-pair) 99)
81 (message "%d" (car gv-test-pair)))
82 (with-temp-buffer
83 (call-process (concat invocation-directory invocation-name)
84 nil '(t t) nil
85 "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
86 "-l" elc)
87 (should (equal (buffer-string)
88 "Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
89
90(ert-deftest gv-define-expander-in-function ()
91 ;; The expander is not defined while we are compiling the file, the
92 ;; compiler won't handle gv definitions not at top-level.
93 :expected-result :failed
94 (gv-tests--in-temp-dir (el elc)
95 ((defun foo ()
96 (gv-define-setter gv-test-foo (newval cons)
97 `(setcar ,cons ,newval))
98 t)
99 (defvar gv-test-pair (cons 1 2))
100 (setf (gv-test-foo gv-test-pair) 99)
101 (message "%d" (car gv-test-pair)))
102 (with-temp-buffer
103 (call-process (concat invocation-directory invocation-name)
104 nil '(t t) nil
105 "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
106 "-l" elc)
107 (should (equal (buffer-string) "99\n")))))
108
109(ert-deftest gv-define-expander-out-of-file ()
110 (gv-tests--in-temp-dir (el elc)
111 ((gv-define-setter gv-test-foo (newval cons)
112 `(setcar ,cons ,newval))
113 (defvar gv-test-pair (cons 1 2)))
114 (with-temp-buffer
115 (call-process (concat invocation-directory invocation-name)
116 nil '(t t) nil
117 "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
118 "-l" elc
119 "--eval"
120 (prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
121 (message "%d" (car gv-test-pair)))))
122 (should (equal (buffer-string) "99\n")))))
123
124(ert-deftest gv-dont-define-expander-other-file ()
125 (gv-tests--in-temp-dir (el elc)
126 ((if nil (gv-define-setter gv-test-foo (newval cons)
127 `(setcar ,cons ,newval)))
128 (defvar gv-test-pair (cons 1 2)))
129 (with-temp-buffer
130 (call-process (concat invocation-directory invocation-name)
131 nil '(t t) nil
132 "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
133 "-l" elc
134 "--eval"
135 (prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
136 (message "%d" (car gv-test-pair)))))
137 (should (equal (buffer-string)
138 "Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
139
140;; `ert-deftest' messes up macroexpansion when the test file itself is
141;; compiled (see Bug #24402).
142
143;; Local Variables:
144;; no-byte-compile: t
145;; End:
146
147;;; gv-tests.el ends here