mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-28 08:11:05 -08:00
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.
This commit is contained in:
parent
b5c8e9898d
commit
79a74568e9
2 changed files with 148 additions and 6 deletions
|
|
@ -146,12 +146,7 @@ NAME is a symbol: the name of a function, macro, or special form.
|
|||
HANDLER is a function which takes an argument DO followed by the same
|
||||
arguments as NAME. DO is a function as defined in `gv-get'."
|
||||
(declare (indent 1) (debug (sexp form)))
|
||||
;; Use eval-and-compile so the method can be used in the same file as it
|
||||
;; is defined.
|
||||
;; FIXME: Just like byte-compile-macro-environment, we should have something
|
||||
;; like byte-compile-symbolprop-environment so as to handle these things
|
||||
;; cleanly without affecting the running Emacs.
|
||||
`(eval-and-compile (put ',name 'gv-expander ,handler)))
|
||||
`(function-put ',name 'gv-expander ,handler))
|
||||
|
||||
;;;###autoload
|
||||
(defun gv--defun-declaration (symbol name args handler &optional fix)
|
||||
|
|
|
|||
147
test/lisp/emacs-lisp/gv-tests.el
Normal file
147
test/lisp/emacs-lisp/gv-tests.el
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
;;; gv-tests.el --- tests for gv.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2017 Free Software Foundation, Inc.
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert)
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
|
||||
(cl-defmacro gv-tests--in-temp-dir ((elvar elcvar)
|
||||
(&rest filebody)
|
||||
&rest body)
|
||||
(declare (indent 2))
|
||||
`(let ((default-directory (make-temp-file "gv-test" t)))
|
||||
(unwind-protect
|
||||
(let ((,elvar "gv-test-deffoo.el")
|
||||
(,elcvar "gv-test-deffoo.elc"))
|
||||
(with-temp-file ,elvar
|
||||
(insert ";; -*- lexical-binding: t; -*-\n")
|
||||
(dolist (form ',filebody)
|
||||
(pp form (current-buffer))))
|
||||
,@body)
|
||||
(delete-directory default-directory t))))
|
||||
|
||||
(ert-deftest gv-define-expander-in-file ()
|
||||
(gv-tests--in-temp-dir (el elc)
|
||||
((gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcar ,cons ,newval))
|
||||
(defvar gv-test-pair (cons 1 2))
|
||||
(setf (gv-test-foo gv-test-pair) 99)
|
||||
(message "%d" (car gv-test-pair)))
|
||||
(with-temp-buffer
|
||||
(call-process (concat invocation-directory invocation-name)
|
||||
nil '(t t) nil
|
||||
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
|
||||
"-l" elc)
|
||||
(should (equal (buffer-string) "99\n")))))
|
||||
|
||||
(ert-deftest gv-define-expander-in-file-twice ()
|
||||
(gv-tests--in-temp-dir (el elc)
|
||||
((gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcar ,cons ,newval))
|
||||
(defvar gv-test-pair (cons 1 2))
|
||||
(setf (gv-test-foo gv-test-pair) 99)
|
||||
(gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcdr ,cons ,newval))
|
||||
(setf (gv-test-foo gv-test-pair) 42)
|
||||
(message "%S" gv-test-pair))
|
||||
(with-temp-buffer
|
||||
(call-process (concat invocation-directory invocation-name)
|
||||
nil '(t t) nil
|
||||
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
|
||||
"-l" elc)
|
||||
(should (equal (buffer-string) "(99 . 42)\n")))))
|
||||
|
||||
(ert-deftest gv-dont-define-expander-in-file ()
|
||||
;; The expander is defined while we are compiling the file, even
|
||||
;; though it's inside (when nil ...) because the compiler won't
|
||||
;; analyze the conditional.
|
||||
:expected-result :failed
|
||||
(gv-tests--in-temp-dir (el elc)
|
||||
((when nil (gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcar ,cons ,newval)))
|
||||
(defvar gv-test-pair (cons 1 2))
|
||||
(setf (gv-test-foo gv-test-pair) 99)
|
||||
(message "%d" (car gv-test-pair)))
|
||||
(with-temp-buffer
|
||||
(call-process (concat invocation-directory invocation-name)
|
||||
nil '(t t) nil
|
||||
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
|
||||
"-l" elc)
|
||||
(should (equal (buffer-string)
|
||||
"Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
|
||||
|
||||
(ert-deftest gv-define-expander-in-function ()
|
||||
;; The expander is not defined while we are compiling the file, the
|
||||
;; compiler won't handle gv definitions not at top-level.
|
||||
:expected-result :failed
|
||||
(gv-tests--in-temp-dir (el elc)
|
||||
((defun foo ()
|
||||
(gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcar ,cons ,newval))
|
||||
t)
|
||||
(defvar gv-test-pair (cons 1 2))
|
||||
(setf (gv-test-foo gv-test-pair) 99)
|
||||
(message "%d" (car gv-test-pair)))
|
||||
(with-temp-buffer
|
||||
(call-process (concat invocation-directory invocation-name)
|
||||
nil '(t t) nil
|
||||
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
|
||||
"-l" elc)
|
||||
(should (equal (buffer-string) "99\n")))))
|
||||
|
||||
(ert-deftest gv-define-expander-out-of-file ()
|
||||
(gv-tests--in-temp-dir (el elc)
|
||||
((gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcar ,cons ,newval))
|
||||
(defvar gv-test-pair (cons 1 2)))
|
||||
(with-temp-buffer
|
||||
(call-process (concat invocation-directory invocation-name)
|
||||
nil '(t t) nil
|
||||
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
|
||||
"-l" elc
|
||||
"--eval"
|
||||
(prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
|
||||
(message "%d" (car gv-test-pair)))))
|
||||
(should (equal (buffer-string) "99\n")))))
|
||||
|
||||
(ert-deftest gv-dont-define-expander-other-file ()
|
||||
(gv-tests--in-temp-dir (el elc)
|
||||
((if nil (gv-define-setter gv-test-foo (newval cons)
|
||||
`(setcar ,cons ,newval)))
|
||||
(defvar gv-test-pair (cons 1 2)))
|
||||
(with-temp-buffer
|
||||
(call-process (concat invocation-directory invocation-name)
|
||||
nil '(t t) nil
|
||||
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
|
||||
"-l" elc
|
||||
"--eval"
|
||||
(prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
|
||||
(message "%d" (car gv-test-pair)))))
|
||||
(should (equal (buffer-string)
|
||||
"Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
|
||||
|
||||
;; `ert-deftest' messes up macroexpansion when the test file itself is
|
||||
;; compiled (see Bug #24402).
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
|
||||
;;; gv-tests.el ends here
|
||||
Loading…
Add table
Add a link
Reference in a new issue