Issues with autoloaded extensions

92 views
Skip to first unread message

Krasimir Kiryakov

unread,
Mar 29, 2022, 7:42:17 AM3/29/22
to MathJax Users
Hello,

We have math that contains the \cancel and \enclose macros (not necessarily together). In our MathJax config file we specify the 'autoload' extension to be loaded explicitly which should then load the 'cancel' and 'enclose' extensions when \cancel and \enclose are first used:

MathJax = {
    tex: {
        packages: ['base', 'ams', 'autoload'],
        autoload: {
            color: [],
            colorv2: ['color']
        }
    },
    loader: {
        load: ['input/asciimath', 'output/chtml', '[tex]/autoload'
    },
    ...
}

The problem is that math containing \cancel and/or \enclose is sometimes rendered correctly and sometimes we see 'Invalid control sequence \cancel / \enclose'. When we get the yellow error, I can confirm that the 'cancel' and/or 'enclose' extension has been loaded (there is a 'input/tex/extensions/cancel.js' file under Network tab of Chrome's Dev Tools) and it appears at the end of list (as expected - loaded on first use).

If I change the above config to explicitly load the 'cancel' and 'enclose' extensions, the yellow error goes away and everything works fine. In this case the extensions are loaded much earlier (also expected).

Any ideas what might be causing this? I don't want to explicitly load those two extensions, because this defeats the autoload concept. And it is a partial solution for these two macros only. Could there be a bug or timing issue in MathJax related to autoloaded extensions? I don't rule out something on our side because as I said it sometimes works, but at the same time it doesn't make the sense to me to have the same configuration and have MathJax sometimes recognize those macros and sometimes not.

We are using version 3.1.2 but I've tried 3.2.0 too and got the same results.
Let me know if you need more info.

Thanks!

Davide Cervone

unread,
Mar 29, 2022, 11:22:01 AM3/29/22
to mathja...@googlegroups.com
You haven't said how you call MathJax, but it sounds like you may be using dynamically loaded content and not chaining the MathJax promises when you process it.  That is, if you load content and use MathJax.typesetPromise(), then load more content, you need to wait for the first promise to resolve before calling MathJax.typesetPromise() again.  For example, if the first content includes the first instance of \cancel, then MathJax will need to load the cancel extension dynamically, and that means other code can run while it is waiting for that.  If your second call to MathJax.typesetPromise() occurs during that time, and it also has a \cancel, then \cancel will not yet be defined, and will produce the message you indicate.  The reason for this is that, if a macro is set to autoload an extension, then when it is used, it will be made undefined before the extension is loaded (that way, in case the extension fails to load, you won't have an infinite loop of the macro trying to load the extension when the expression), then when the extension loads (or fails to load), the expression is typeset again.  If you typeset something during the time the extension is being loaded, then the macro is undefined during that period.

That could account for your experience of sometimes having it be defined and sometimes not, since the timing of the loading of the extension versus the second typeset call would affect the outcome.  There is clearly a race condition, and this is the most likely explanation.

The documentation includes several methods of handling the promises


so you might consider one of them.  If that is not the issue, then you will need to give more details about your situation.  An example page that exhibits the problem is always a help.

Davide


--
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mathjax-users/cf2ad829-8a2f-42d9-84c4-158e06b0a712n%40googlegroups.com.

Krasimir Kiryakov

unread,
Mar 29, 2022, 1:56:26 PM3/29/22
to MathJax Users
Thanks for the quick response, Davide. The info you have provided explains many things. We do have dynamically loaded content. I just played with one very simple HTML page affected by the issue - basically one math instance is injected into the page and the page is typeset by calling MathJax.typesetPromise(document.body). Changing
        MathJax.typesetPromise(document.body);
to
        MathJax.startup.promise = MathJax.startup.promise.then(() => MathJax.typesetPromise(document.body));

fixed the issue and I can confirm that without this change the initial typesetting of the page didn't happen before the call to MathJax.typesetPromise(document.body). So we really had two concurrent async typesettings leading to the scenario you have described. I'll go ahead and implement the above change globally.

We are good.
Best,
Krasimir

Davide Cervone

unread,
Mar 29, 2022, 2:00:37 PM3/29/22
to mathja...@googlegroups.com
Glad you got it working,

You may want to use

MathJax = {
  startup: {
    typeset: false
  }
};

as part of your configuration to prevent the initial typeset from occurring until you call MathJax.typesetPromise() when your content is loaded.

Davide


Krasimir Kiryakov

unread,
Mar 29, 2022, 2:04:48 PM3/29/22
to MathJax Users
I know but don't think disabling the initial typesetting is something we want to do.
Thanks again!

Reply all
Reply to author
Forward
0 new messages