Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array of elements passed to Typeset is ignored if no callback is given #1680

Closed
jdleesmiller opened this issue Dec 23, 2016 · 4 comments
Closed
Labels
Accepted Issue has been reproduced by MathJax team Fixed Test Available v2.7

Comments

@jdleesmiller
Copy link

The documentation for Hub.Typeset suggests that you can pass an array of elements or a callback or both:
image

However, the argument handling in the elementCallback helper method has some (IMHO) odd behaviour when element is an array and callback is not specified. The code in question is:

if (callback == null && (MathJax.Object.isArray(element) || typeof element === 'function'))
  {try {MathJax.Callback(element); callback = element; element = null} catch(e) {}}

The result is that callback ends up being set to the first element in the array, and element is set to null. The element then defaults to the document's body later on, which in most cases masks the bug (unless the intended elements aren't yet in thebody, in which case much confusion ensues). However, if you use signal.Interest to track the events, you can see that the element is not actually tracked.

It's also worth noting that this affects other hub functions, such as Update.

Example

Run this in the dev console on the home page:

MathJax.Hub.signal.Interest(function (message) {console.log(message)});
MathJax.Hub.Queue(['Typeset', MathJax.Hub, $('.hero-math').toArray()]);
MathJax.Hub.Queue(['Typeset', MathJax.Hub, $('.hero-math').toArray(), function callbackHere() {}])

Output:
image

When the callback is not specified, the signal messages indicate that MathJax is searching the body. When the callback is specified, the signal messages indicate that MathJax is searching the div.hero-math element, which is what was intended.

@dpvc
Copy link
Member

dpvc commented Dec 29, 2016

The issue here is a little more complicated than it might appear, and has to do with the fact that a callback (in MathJax) need not be a function, but can be specified in a variety of other ways (see the callback documentation).

When a single argument is passed to Typeset(), MathJax needs to decide whether it is a callback or an element (either an id of one, or the DOM element itself, or an array of those), and this is a bit tricky. The line you quote above is intended to do that (but it isn't perfect).

if (callback == null && (MathJax.Object.isArray(element) || typeof element === 'function'))
  {try {MathJax.Callback(element); callback = element; element = null} catch(e) {}}

Here, if there is no callback (i.e., only one argument was passed), and if that argument looks like it could be a callback specification (a callback can be a function or an array with the right kind of elements), then Typeset() tries to create a callback out of the argument, and if it succeeds, it uses the argument as its callback and sets the element to null (otherwise it keeps the argument as the element and leaves the callback as null). Because the array form of a callback is complicated, Typeset() leave the checking for a valid callback to MathJax.Callback(). (Technically, a callback can also be specified as an object with certain properties, so the code here misses that, but it is a rare usage.)

It turns out that the situation that causes problems is when the single argument to Typeset() is an array of only one element. If $('.hero-math').toArray() returned more than one element, everything would be OK, as I describe below.

The problem actually is in MathJax.Callback(), not in MathJax.Hub.Typeset(). One of the ways of specifying a callback is as a function, but MathJax also accepts an array consisting of a single function as a specification for a callback. As it tries to determine the format of a callback, MathJax.Callback() "unpacks" a singleton-array into its single element at line 301, and this is the source of the problem. If the array consists of a single DOM element, MathJax.Callback() turns it into that single DOM element, and then thinks that this is giving the callback as an object literal (one of the valid forms), so a callback is created. (If it is an array of two DOM elements, then it is not unpacked, and the array ends up not matching a valid callback, and none is returned, as expected.)

So line 301 is the culprit. It should only unpack the array if it is an array whose one element is a function object, not just any object.

Until that is fixed, it is best to use

MathJax.Hub.Queue(['Typeset', MathJax.Hub, $('.hero-math').toArray(), {}]);

to force there to be an empty callback if the query select could return an array with only one element.

@pkra pkra added the Accepted Issue has been reproduced by MathJax team label Dec 29, 2016
@pkra pkra added this to the A future release milestone Dec 29, 2016
@dpvc dpvc self-assigned this Jun 28, 2017
@dpvc dpvc modified the milestones: A future release, MathJax v2.7.2 Jul 6, 2017
dpvc added a commit to dpvc/MathJax that referenced this issue Jul 7, 2017
…s (by only unpacking singleton callback arrays when the one element is a function). Resolves issue mathjax#1680.
@dpvc
Copy link
Member

dpvc commented Jul 7, 2017

The issue1680 branch of my fork of MathJax includes a fix for this.

@dpvc dpvc removed their assignment Jul 7, 2017
dpvc added a commit that referenced this issue Jul 10, 2017
Properly handle arrays of elements in Typeset() call without callbacks.  #1680
@dpvc
Copy link
Member

dpvc commented Jul 10, 2017

==> Merged

@dpvc dpvc added Merged Merged into develop branch and removed Ready for Review labels Jul 10, 2017
dpvc added a commit to mathjax/MathJax-test that referenced this issue Jul 14, 2017
@dpvc
Copy link
Member

dpvc commented Jul 14, 2017

==> In testsuite

API/Callback/issue1680.html

@dpvc dpvc closed this as completed Jul 14, 2017
@dpvc dpvc added Fixed v2.7 and removed Merged Merged into develop branch labels Jul 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Issue has been reproduced by MathJax team Fixed Test Available v2.7
Projects
None yet
Development

No branches or pull requests

3 participants