summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/edebug.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/edebug.el')
-rw-r--r--lisp/emacs-lisp/edebug.el206
1 files changed, 123 insertions, 83 deletions
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index 2f7d03e9d79..aa68978f6d6 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -1225,8 +1225,10 @@ purpose by adding an entry to this alist, and setting
;; But the list will just be reversed.
,@(nreverse edebug-def-args))
'nil)
- (function (lambda () ,@forms))
- ))
+ ;; Make sure `forms' is not nil so we don't accidentally return
+ ;; the magic keyword. Mark the closure so we don't throw away
+ ;; unused vars (bug#59213).
+ #'(lambda () :closure-dont-trim-context ,@(or forms '(nil)))))
(defvar edebug-form-begin-marker) ; the mark for def being instrumented
@@ -1542,9 +1544,7 @@ contains a circular object."
(defun edebug-list-form (cursor)
;; Return an instrumented form built from the list form.
;; The after offset will be left in the cursor after processing the form.
- (let ((head (edebug-top-element-required cursor "Expected elements"))
- ;; Prevent backtracking whenever instrumenting.
- (edebug-gate t))
+ (let ((head (edebug-top-element-required cursor "Expected elements")))
;; Skip the first offset.
(edebug-set-cursor cursor (edebug-cursor-expressions cursor)
(cdr (edebug-cursor-offsets cursor)))
@@ -2467,12 +2467,52 @@ MSG is printed after `::::} '."
(setf (cdr (assq 'edebug edebug-behavior-alist))
'(edebug-default-enter edebug-fast-before edebug-fast-after)))
-(defalias 'edebug-before nil
+;; The following versions of `edebug-before' and `edebug-after' exist
+;; to handle the error which occurs if either of them gets called
+;; without an enclosing `edebug-enter'. This can happen, for example,
+;; when a macro mistakenly has a `form' element in its edebug spec,
+;; and it additionally, at macro-expansion time, calls `eval',
+;; `apply', or `funcall' (etc.) on the corresponding argument. This
+;; is intended to fix bug#65620.
+
+(defun edebug-b/a-error (func)
+ "Throw an error for an invalid call of FUNC.
+FUNC is expected to be `edebug-before' or `edebug-after'."
+ (let (this-macro
+ (n 0)
+ bt-frame)
+ (while (and (setq bt-frame (backtrace-frame n))
+ (not (and (car bt-frame)
+ (memq (cadr bt-frame)
+ '(macroexpand macroexpand-1)))))
+ (setq n (1+ n)))
+ (when bt-frame
+ (setq this-macro (caaddr bt-frame)))
+
+ (error
+ (concat "Invalid call to `" (symbol-name func) "'"
+ (if this-macro
+ (concat ". Is the edebug spec for `"
+ (symbol-name this-macro)
+ "' correct?")
+ "" ; Not sure this case is possible (ACM, 2023-09-02)
+ )))))
+
+(defun edebug-before (_before-index)
"Function called by Edebug before a form is evaluated.
-See `edebug-behavior-alist' for implementations.")
-(defalias 'edebug-after nil
+See `edebug-behavior-alist' for other implementations. This
+version of `edebug-before' gets called when edebug is not yet set
+up. `edebug-enter' binds the function cell to a real function
+when edebug becomes active."
+ (edebug-b/a-error 'edebug-before))
+
+(defun edebug-after (_before-index _after-index _form)
"Function called by Edebug after a form is evaluated.
-See `edebug-behavior-alist' for implementations.")
+See `edebug-behavior-alist' for other implementations. This
+version of `edebug-after' gets called when edebug is not yet set
+up. `edebug-enter' binds the function cell to a real function
+when edebug becomes active."
+ (edebug-b/a-error 'edebug-after))
(defun edebug--update-coverage (after-index value)
(let ((old-result (aref edebug-coverage after-index)))
@@ -2851,81 +2891,81 @@ See `edebug-behavior-alist' for implementations.")
edebug-inside-windows
)
- (unwind-protect
- (let (
- ;; Declare global values local but using the same global value.
- ;; We could set these to the values for previous edebug call.
- (last-command last-command)
- (this-command this-command)
- (current-prefix-arg nil)
-
- (last-input-event nil)
- (last-command-event nil)
- (last-event-frame nil)
- (last-nonmenu-event nil)
- (track-mouse nil)
-
- (standard-output t)
- (standard-input t)
-
- ;; Don't keep reading from an executing kbd macro
- ;; within edebug unless edebug-continue-kbd-macro is
- ;; non-nil. Again, local binding may not be best.
- (executing-kbd-macro
- (if edebug-continue-kbd-macro executing-kbd-macro))
-
- ;; Don't get confused by the user's keymap changes.
- (overriding-local-map nil)
- (overriding-terminal-local-map nil)
- ;; Override other minor modes that may bind the keys
- ;; edebug uses.
- (minor-mode-overriding-map-alist
- (list (cons 'edebug-mode edebug-mode-map)))
-
- ;; Bind again to outside values.
- (debug-on-error edebug-outside-debug-on-error)
- (debug-on-quit edebug-outside-debug-on-quit)
-
- ;; Don't keep defining a kbd macro.
- (defining-kbd-macro
- (if edebug-continue-kbd-macro defining-kbd-macro))
-
- ;; others??
- )
- (if (and (eq edebug-execution-mode 'go)
- (not (memq arg-mode '(after error))))
- (message "Break"))
-
- (setq signal-hook-function nil)
-
- (edebug-mode 1)
- (unwind-protect
- (recursive-edit) ; <<<<<<<<<< Recursive edit
-
- ;; Do the following, even if quit occurs.
- (setq signal-hook-function #'edebug-signal)
- (if edebug-backtrace-buffer
- (kill-buffer edebug-backtrace-buffer))
-
- ;; Remember selected-window after recursive-edit.
- ;; (setq edebug-inside-window (selected-window))
-
- (set-match-data edebug-outside-match-data)
-
- ;; Recursive edit may have changed buffers,
- ;; so set it back before exiting let.
- (if (buffer-name edebug-buffer) ; if it still exists
- (progn
- (set-buffer edebug-buffer)
- (when (memq edebug-execution-mode '(go Go-nonstop))
- (edebug-overlay-arrow)
- (sit-for 0))
- (edebug-mode -1))
- ;; gotta have a buffer to let its buffer local variables be set
- (get-buffer-create " bogus edebug buffer"))
- ));; inner let
- )))
+ (let (
+ ;; Declare global values local but using the same global value.
+ ;; We could set these to the values for previous edebug call.
+ (last-command last-command)
+ (this-command this-command)
+ (current-prefix-arg nil)
+
+ (last-input-event nil)
+ (last-command-event nil)
+ (last-event-frame nil)
+ (last-nonmenu-event nil)
+ (track-mouse nil)
+
+ (standard-output t)
+ (standard-input t)
+
+ ;; Don't keep reading from an executing kbd macro
+ ;; within edebug unless edebug-continue-kbd-macro is
+ ;; non-nil. Again, local binding may not be best.
+ (executing-kbd-macro
+ (if edebug-continue-kbd-macro executing-kbd-macro))
+
+ ;; Don't get confused by the user's keymap changes.
+ (overriding-local-map nil)
+ (overriding-terminal-local-map nil)
+ ;; Override other minor modes that may bind the keys
+ ;; edebug uses.
+ (minor-mode-overriding-map-alist
+ (list (cons 'edebug-mode edebug-mode-map)))
+
+ ;; Bind again to outside values.
+ (debug-on-error edebug-outside-debug-on-error)
+ (debug-on-quit edebug-outside-debug-on-quit)
+
+ ;; Don't keep defining a kbd macro.
+ (defining-kbd-macro
+ (if edebug-continue-kbd-macro defining-kbd-macro))
+
+ ;; others??
+ )
+
+ (if (and (eq edebug-execution-mode 'go)
+ (not (memq arg-mode '(after error))))
+ (message "Break"))
+
+ (setq signal-hook-function nil)
+
+ (edebug-mode 1)
+ (unwind-protect
+ (recursive-edit) ; <<<<<<<<<< Recursive edit
+
+ ;; Do the following, even if quit occurs.
+ (setq signal-hook-function #'edebug-signal)
+ (if edebug-backtrace-buffer
+ (kill-buffer edebug-backtrace-buffer))
+
+ ;; Remember selected-window after recursive-edit.
+ ;; (setq edebug-inside-window (selected-window))
+
+ (set-match-data edebug-outside-match-data)
+
+ ;; Recursive edit may have changed buffers,
+ ;; so set it back before exiting let.
+ (if (buffer-name edebug-buffer) ; if it still exists
+ (progn
+ (set-buffer edebug-buffer)
+ (when (memq edebug-execution-mode '(go Go-nonstop))
+ (edebug-overlay-arrow)
+ (sit-for 0))
+ (edebug-mode -1))
+ ;; gotta have a buffer to let its buffer local variables be set
+ (get-buffer-create " bogus edebug buffer"))
+ ));; inner let
+ ))
;;; Display related functions