Subject: Re: bug#15888: 24.3.50; Eval-after-load eval'ed twice

From: "Sebastien Vauban" <[email-masked]>
Date: Wed, 04 Dec 2013 21:48:07 +0100

Hello,

Nicolas Goaziou wrote:
> Nick Dokos <[email-masked]> writes:
>
>> (require 'org-loaddefs)
>>
>> (with-eval-after-load "ob-lob"
>>   ;; load some code blocks into the library of Babel
>>   (let ((lob-file (concat (file-name-directory (locate-library "org"))
>>                           "../doc/library-of-babel.org")))
>>     (when (file-exists-p lob-file)
>>       (org-babel-lob-ingest lob-file))))
>>
>> (defun foobar ()
>>   (message "LOADED") (sit-for 3) (message ""))
>>
>> (setq org-load-hook (function foobar))
>>
>> edebugged foobar and C-x C-f foo.org. It stopped at foobar twice
>> and I got the following backtraces at the two stopping points.
>
> The code in "double-load.el" calls `org-babel-lob-ingest' as soon as
> "ob-lob.el" is loaded. The problem is that:
>
>   1. `org-babel-lob-ingest' needs to open an Org file (and therefore
>      call `org-mode' in its buffer);
>   2. `ob-lob' is required before `org' is provided.
>
> Therefore, org.el is read twice and hook run as many times.

I want to be sure I fully grasp the problem completely...

You say that opening an Org file requires first `ob-lob' before *providing*
`org', right? [1]

IIUC, here are all the steps involved:

1. an Org file is opened
2. org.el is required -- but not yet provided at all, so loaded a first time
3. when loading it, it requires first extra packages; among others (via some
   call tree), ob-lob.el -- see [1]
4. ob-lob.el is then loaded, and in fine provided
5. eval-after-load "ob-lob" is run straight away, and tries to open an Org file
6. org.el is hence required -- but it still is not yet provided, so loaded a
   second time
7. at some point, org.el is provided for real
8. Eval-after-load "org" is run a first time, so are hooks
9. Eval-after-load "org" is run a second time, as the file has been loaded
   twice

IOW, isn't the problem that the `eval-after-load' is RUN AFTER EACH `provide' of
some lib, not after the FIRST `provide' of that lib?

It seems to me that such call trees can't be managed properly otherwise (I
mean, with the current rule: a lot of code may be run multiple times, while
only logically scheduled once).

Best regards,
  Seb

[1] I can't following the full library "call tree":

  org -> ??? -> ob -> ob-lob

-- 
Sebastien Vauban