From dd2973bf5040d26d29a937d252eeaf2884dca9fb Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 13 Aug 2022 12:03:22 -0400 Subject: [PATCH] nadvice.el: Avoid exponential blow up in interactive-form recursion * lisp/emacs-lisp/nadvice.el (advice--interactive-form): Sink the call to `commandp` into the autoloaded function case since it's redundant in the other branch. (advice--make-interactive-form): Take just the interactive forms rather than the actual functions as arguments. (oclosure-interactive-form): Use `advice--interactive-form` rather than `commandp` since we'd call `advice--interactive-form` afterwards anyway. --- lisp/emacs-lisp/nadvice.el | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el index 2d5a1b5e77b..86f26fc0d84 100644 --- a/lisp/emacs-lisp/nadvice.el +++ b/lisp/emacs-lisp/nadvice.el @@ -167,31 +167,31 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.") (defun advice--interactive-form (function) "Like `interactive-form' but tries to avoid autoloading functions." - (when (commandp function) - (if (not (and (symbolp function) (autoloadp (indirect-function function)))) - (interactive-form function) - `(interactive (advice-eval-interactive-spec + (if (not (and (symbolp function) (autoloadp (indirect-function function)))) + (interactive-form function) + (when (commandp function) + `(interactive (advice--eval-interactive-spec (cadr (interactive-form ',function))))))) -(defun advice--make-interactive-form (function main) +(defun advice--make-interactive-form (iff ifm) ;; TODO: make it so that interactive spec can be a constant which ;; dynamically checks the advice--car/cdr to do its job. ;; For that, advice-eval-interactive-spec needs to be more faithful. - (let* ((iff (advice--interactive-form function)) - (ifm (advice--interactive-form main)) - (fspec (cadr iff))) + (let* ((fspec (cadr iff))) (when (eq 'function (car-safe fspec)) ;; Macroexpanded lambda? - (setq fspec (nth 1 fspec))) + (setq fspec (eval fspec t))) (if (functionp fspec) `(funcall ',fspec ',(cadr ifm)) (cadr (or iff ifm))))) (cl-defmethod oclosure-interactive-form ((ad advice) &optional _) - (let ((car (advice--car ad)) - (cdr (advice--cdr ad))) - (when (or (commandp car) (commandp cdr)) - `(interactive ,(advice--make-interactive-form car cdr))))) + (let* ((car (advice--car ad)) + (cdr (advice--cdr ad)) + (ifa (advice--interactive-form car)) + (ifd (advice--interactive-form cdr))) + (when (or ifa ifd) + `(interactive ,(advice--make-interactive-form ifa ifd))))) (cl-defmethod cl-print-object ((object advice) stream) (cl-assert (advice--p object)) -- 2.39.5