Function: js-eval-defun
js-eval-defun is an interactive and byte-compiled function defined in
js.el.gz.
Signature
(js-eval-defun)
Documentation
Update a Mozilla tab using the JavaScript defun at point.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/js.el.gz
(cl-defun js-eval-defun ()
"Update a Mozilla tab using the JavaScript defun at point."
(interactive)
;; This function works by generating a temporary file that contains
;; the function we'd like to insert. We then use the elisp-js bridge
;; to command mozilla to load this file by inserting a script tag
;; into the document we set. This way, debuggers and such will have
;; a way to find the source of the just-inserted function.
;;
;; We delete the temporary file if there's an error, but otherwise
;; we add an unload event listener on the Mozilla side to delete the
;; file.
(save-excursion
(let (begin end pstate defun-info temp-name defun-body)
(js-end-of-defun)
(setq end (point))
(js--ensure-cache)
(js-beginning-of-defun)
(re-search-forward "\\_<function\\_>")
(setq begin (match-beginning 0))
(setq pstate (js--forward-pstate))
(when (or (null pstate)
(> (point) end))
(error "Could not locate function definition"))
(setq defun-info (js--guess-eval-defun-info pstate))
(let ((overlay (make-overlay begin end)))
(overlay-put overlay 'face 'highlight)
(unwind-protect
(unless (y-or-n-p (format "Send %s to Mozilla? "
(mapconcat #'identity defun-info ".")))
(message "") ; question message lingers until next command
(cl-return-from js-eval-defun))
(delete-overlay overlay)))
(setq defun-body (buffer-substring-no-properties begin end))
(make-directory js-js-tmpdir t)
;; (Re)register a Mozilla resource URL to point to the
;; temporary directory
(js--js-add-resource-alias "js" js-js-tmpdir)
(setq temp-name (make-temp-file (concat js-js-tmpdir
"/js-")
nil ".js"))
(unwind-protect
(with-js
(with-temp-buffer
(insert js--js-inserter)
(insert "(")
(let ((standard-output (current-buffer)))
(json--print-list defun-info))
(insert ",\n")
(insert defun-body)
(insert "\n)")
(write-region (point-min) (point-max) temp-name
nil 1))
;; Give Mozilla responsibility for deleting this file
(let* ((content-window (js--js-content-window
(js--get-js-context)))
(content-document (js< content-window "document"))
(head (if (js? (js< content-document "body"))
;; Regular content
(js< (js! (content-document "getElementsByTagName")
"head")
0)
;; Chrome
(js< content-document "documentElement")))
(elem (js! (content-document "createElementNS")
"http://www.w3.org/1999/xhtml" "script")))
(js! (elem "setAttribute") "type" "text/javascript")
(js! (elem "setAttribute") "src"
(format "resource://js/%s"
(file-name-nondirectory temp-name)))
(js! (head "appendChild") elem)
(js! (content-window "addEventListener") "unload"
(js! ((js-new
"Function" "file"
"return function() { file.remove(false) }"))
(js--make-nsilocalfile temp-name))
'false)
(setq temp-name nil)
))
;; temp-name is set to nil on success
(when temp-name
(delete-file temp-name))))))