Skip to content

Commit f798364

Browse files
authored
Merge pull request #1050 from mathjax/issue3170
Fix \require to properly handle retries in dependencies. (mathjax/MathJax#3170)
2 parents 611d09f + 001806c commit f798364

File tree

1 file changed

+60
-30
lines changed

1 file changed

+60
-30
lines changed

ts/input/tex/require/RequireConfiguration.ts

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import {expandable} from '../../../util/Options.js';
4141
const MJCONFIG = MathJax.config;
4242

4343
/**
44-
* Add an extension to the configuration, and configure its user options
44+
* Load any dependencies for an extension, and add the extension to the input jax.
4545
*
4646
* @param {TeX} jax The TeX jax whose configuration is to be modified
4747
* @param {string} name The name of the extension being added (e.g., '[tex]/amscd')
@@ -53,36 +53,57 @@ function RegisterExtension(jax: TeX<any, any, any>, name: string) {
5353
if (required.indexOf(extension) < 0) {
5454
required.push(extension);
5555
//
56-
// Register any dependencies that were loaded to handle this one
56+
// Register any dependencies that were loaded to handle this one,
57+
// and save the retry promise, if any, for when the dependencies need
58+
// to restart the expression (due to preprocessors, see below).
5759
//
58-
RegisterDependencies(jax, LOADERCONFIG.dependencies[name]);
60+
let retry = RegisterDependencies(jax, LOADERCONFIG.dependencies[name]);
5961
//
60-
// If the required file loaded an extension...
62+
// If we need to restart the expression due to the dependencies,
63+
// Wait for the dependencies to load, process this extension, then retry,
64+
// Otherwise, process the extension now.
6165
//
62-
const handler = ConfigurationHandler.get(extension);
63-
if (handler) {
64-
//
65-
// Check if there are user-supplied options
66-
// (place them in a block for the extension, if needed)
67-
//
68-
let options = MJCONFIG[name] || {};
69-
if (handler.options && Object.keys(handler.options).length === 1 && handler.options[extension]) {
70-
options = {[extension]: options};
71-
}
72-
//
73-
// Register the extension with the jax's configuration
74-
//
75-
(jax as any).configuration.add(extension, jax, options);
76-
//
77-
// If there are preprocessors, restart so that they run
78-
// (we don't have access to the document or MathItem needed to call
79-
// the preprocessors from here)
80-
//
81-
const configured = jax.parseOptions.packageData.get('require').configured;
82-
if (handler.preprocessors.length && !configured.has(extension)) {
83-
configured.set(extension, true);
84-
mathjax.retryAfter(Promise.resolve());
85-
}
66+
if (retry) {
67+
mathjax.retryAfter(retry.then(() => ProcessExtension(jax, name, extension)));
68+
} else {
69+
ProcessExtension(jax, name, extension);
70+
}
71+
}
72+
}
73+
74+
/**
75+
* Add an extension to the configuration, and configure its user options
76+
*
77+
* @param {TeX} jax The TeX jax whose configuration is to be modified
78+
* @param {string} name The name of the extension being added (e.g., '[tex]/amscd')
79+
*/
80+
function ProcessExtension(jax: TeX<any, any, any>, name: string, extension: string) {
81+
//
82+
// If the required file loaded an extension...
83+
//
84+
const handler = ConfigurationHandler.get(extension);
85+
if (handler) {
86+
//
87+
// Check if there are user-supplied options
88+
// (place them in a block for the extension, if needed)
89+
//
90+
let options = MJCONFIG[name] || {};
91+
if (handler.options && Object.keys(handler.options).length === 1 && handler.options[extension]) {
92+
options = {[extension]: options};
93+
}
94+
//
95+
// Register the extension with the jax's configuration
96+
//
97+
(jax as any).configuration.add(extension, jax, options);
98+
//
99+
// If there are preprocessors, restart the typesetting so that they run
100+
// (we don't have access to the document or MathItem needed to call
101+
// the preprocessors from here)
102+
//
103+
const configured = jax.parseOptions.packageData.get('require').configured;
104+
if (handler.preprocessors.length && !configured.has(extension)) {
105+
configured.set(extension, true);
106+
mathjax.retryAfter(Promise.resolve());
86107
}
87108
}
88109
}
@@ -92,14 +113,23 @@ function RegisterExtension(jax: TeX<any, any, any>, name: string) {
92113
*
93114
* @param {TeX} jax The jax whose configuration is being modified
94115
* @param {string[]} names The names of the dependencies to register
116+
* @return {Promise<any>} A promise resolved when all dependency's retries
117+
* are complete (or null if no retries)
95118
*/
96-
function RegisterDependencies(jax: TeX<any, any, any>, names: string[] = []) {
119+
function RegisterDependencies(jax: TeX<any, any, any>, names: string[] = []): Promise<any> {
97120
const prefix = jax.parseOptions.options.require.prefix;
121+
const retries = [];
98122
for (const name of names) {
99123
if (name.substring(0, prefix.length) === prefix) {
100-
RegisterExtension(jax, name);
124+
try {
125+
RegisterExtension(jax, name);
126+
} catch (err) {
127+
if (!err.retry) throw err;
128+
retries.push(err.retry);
129+
}
101130
}
102131
}
132+
return (retries.length ? Promise.all(retries) : null);
103133
}
104134

105135
/**

0 commit comments

Comments
 (0)