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

Update the asyncLoad implementations to be more consistent, and update tests. #1109

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions testsuite/tests/util/asyncLoad/esm.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { describe, test, expect } from '@jest/globals';
import {mathjax} from '#js/mathjax.js';
import {asyncLoad} from '#js/util/AsyncLoad.js';
import {setBaseURL} from '#js/util/asyncLoad/esm.js';
import * as path from 'path';

const root = new URL(path.resolve('..', 'mjs'), 'file://').href;
const lib = new URL(path.resolve('lib'), 'file://').href;
const root = path.resolve('..', 'mjs');
const lib = path.resolve('lib');

describe('asyncLoad() for esm', () => {

Expand All @@ -20,10 +21,16 @@ describe('asyncLoad() for esm', () => {
await expect(asyncLoad(absFile)).resolves.toEqual({loaded: true}); // absolute file found
await expect(asyncLoad(absUnknown).catch(() => true)).resolves.toBe(true); // absolute file not found

await expect(asyncLoad('#js/components/version.js') // load using package exports
.then((result: any) => result.VERSION)).resolves.toBe(mathjax.version);
await expect(asyncLoad('mathjax-full/js/components/version.js') // load from module
.then((result: any) => result.VERSION)).resolves.toBe(mathjax.version);

await expect(asyncLoad(mjsFile).then((result: any) => result.loaded)).resolves.toBe(true); // mjs file loads
expect(mathjax.asyncIsSynchronous).toBe(false); // esm.js is asynchronous
});

test('serBaseURL() for esm', async () => {
test('setBaseURL() for esm', async () => {
setBaseURL(lib);
const relFile = './AsyncLoad.child.cjs';
const relUnknown = './AsyncLoad.unknown.cjs';
Expand Down
9 changes: 8 additions & 1 deletion testsuite/tests/util/asyncLoad/node.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, test, expect } from '@jest/globals';
import './dirname.mjs';
import '#source/../require.mjs';
import {mathjax} from '#js/mathjax.js';
import {asyncLoad} from '#js/util/AsyncLoad.js';
import {setBaseURL} from '#js/util/asyncLoad/node.js';
import * as path from 'path';
Expand All @@ -22,10 +23,16 @@ describe('asyncLoad() for node', () => {
await expect(asyncLoad(absFile)).resolves.toEqual({loaded: true}); // absolute file found
await expect(asyncLoad(absUnknown).catch(() => true)).resolves.toBe(true); // absolute file not found

await expect(asyncLoad('#js/../cjs/components/version.js') // load using package exports
.then((result: any) => result.VERSION)).resolves.toBe(mathjax.version);
await expect(asyncLoad('mathjax-full/js/components/version.js') // load from module
.then((result: any) => result.VERSION)).resolves.toBe(mathjax.version);

await expect(asyncLoad(mjsFile).catch(() => true)).resolves.toBe(true); // mjs file fails
expect(mathjax.asyncIsSynchronous).toBe(true); // node.js is synchronous
});

test('serBaseURL() for node', async () => {
test('setBaseURL() for node', async () => {
setBaseURL(lib);
const relFile = './AsyncLoad.child.cjs';
const relUnknown = './AsyncLoad.unknown.cjs';
Expand Down
13 changes: 10 additions & 3 deletions testsuite/tests/util/asyncLoad/system.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { describe, test, expect } from '@jest/globals';
import './dirname.mjs';
import './system.cjs';
import {mathjax} from '#js/mathjax.js';
import {asyncLoad} from '#js/util/AsyncLoad.js';
import {setBaseURL} from '#js/util/asyncLoad/system.js';
import * as path from 'path';

const root = new URL(path.resolve('..', 'mjs'), 'file://').href;
const lib = new URL(path.resolve('lib'), 'file://').href;
const root = path.resolve('..', 'mjs');
const lib = path.resolve('lib');

describe('asyncLoad() for node', () => {

Expand All @@ -22,10 +23,16 @@ describe('asyncLoad() for node', () => {
await expect(asyncLoad(absFile)).resolves.toEqual({loaded: true}); // absolute file found
await expect(asyncLoad(absUnknown).catch(() => true)).resolves.toBe(true); // absolute file not found

await expect(asyncLoad('#js/components/version.js') // can't load using package exports
.catch(() => true)).resolves.toBe(true);
await expect(asyncLoad('mathjax-full/js/components/version.js') // can't load from module
.catch(() => true)).resolves.toBe(true);

await expect(asyncLoad(mjsFile).then((result: any) => result.loaded)).resolves.toBe(true); // mjs file loads
expect(mathjax.asyncIsSynchronous).toBe(false); // system.js is asynchronous
});

test('serBaseURL() for node', async () => {
test('setBaseURL() for node', async () => {
setBaseURL(lib);
const relFile = './AsyncLoad.child.cjs';
const relUnknown = './AsyncLoad.unknown.cjs';
Expand Down
4 changes: 4 additions & 0 deletions ts/mathjax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ export const mathjax = {
*/
asyncLoad: null as ((file: string) => any),

/**
* When asyncLoad uses require(), it actually operates synchronously and this is true
*/
asyncIsSynchronous: false,
};
9 changes: 5 additions & 4 deletions ts/output/common/FontData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
* @author dpvc@mathjax.org (Davide Cervone)
*/

import {mathjax} from '../../mathjax.js';
import {OptionList, defaultOptions, userOptions} from '../../util/Options.js';
import {StyleList} from '../../util/StyleList.js';
import {asyncLoad} from '../../util/AsyncLoad.js';
import {retryAfter} from '../../util/Retries.js';
import {mathjax} from '../../mathjax.js';
import {DIRECTION} from './Direction.js';
export {DIRECTION} from './Direction.js';

Expand Down Expand Up @@ -1101,7 +1101,7 @@ export class FontData<C extends CharOptions, V extends VariantData<C>, D extends
const prefix = (!dynamic.extension ? this.options.dynamicPrefix :
this.CLASS.dynamicExtensions.get(dynamic.extension).prefix);
return (dynamic.file.match(/^(?:[\/\[]|[a-z]+:\/\/|[a-z]:)/i) ? dynamic.file :
prefix + '/' + dynamic.file.replace(/\.js$/, ''));
prefix + '/' + dynamic.file.replace(/(?<!\.js)$/, '.js'));
}

/**
Expand Down Expand Up @@ -1141,8 +1141,9 @@ export class FontData<C extends CharOptions, V extends VariantData<C>, D extends
* synchronous loading function, as in util/asyncLoad/node.ts.
*/
public loadDynamicFilesSync() {
if (!mathjax.asyncLoad) {
throw Error('MathJax(loadDynamicFilesSync): mathjax.asyncLoad must be specified and synchronous');
if (!mathjax.asyncIsSynchronous) {
throw Error('MathJax(loadDynamicFilesSync): mathjax.asyncLoad must be specified and synchronous\n' +
' Try importing #js/../components/require.mjs and #js/util/asyncLoad/node.js');
}
const dynamicFiles = this.CLASS.dynamicFiles;
Object.keys(dynamicFiles).forEach(name => this.loadDynamicFileSync(dynamicFiles[name]));
Expand Down
2 changes: 1 addition & 1 deletion ts/util/AsyncLoad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {mathjax} from '../mathjax.js';
*/
export function asyncLoad(name: string): Promise<any> {
if (!mathjax.asyncLoad) {
return Promise.reject(`Can't load '${name}': No asyncLoad method specified`);
return Promise.reject(`Can't load '${name}': No mathjax.asyncLoad method specified`);
}
return new Promise((ok, fail) => {
const result = mathjax.asyncLoad(name);
Expand Down
9 changes: 5 additions & 4 deletions ts/util/asyncLoad/esm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ let root = new URL(import.meta.url).href.replace(/\/util\/asyncLoad\/esm.js$/, '

if (!mathjax.asyncLoad) {
mathjax.asyncLoad = async (name: string) => {
return import(new URL(name, root).href).then((result) => result?.default || result);
const file = (name.charAt(0) === '.' ? new URL(name, root).pathname : name);
return import(file).then((result) => result?.default || result);
};
}

/**
* @param {string} URL the base URL to use for loading relative paths
* @param {string} url the base URL to use for loading relative paths
*/
export function setBaseURL(URL: string) {
root = URL;
export function setBaseURL(url: string) {
root = new URL(url, 'file://').href;
if (!root.match(/\/$/)) {
root += '/';
}
Expand Down
6 changes: 4 additions & 2 deletions ts/util/asyncLoad/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,20 @@

import {mathjax} from '../../mathjax.js';
import * as path from 'path';
import {src} from '#source/source.cjs';

declare var require: (name: string) => any;
declare var __dirname: string;

let root = path.dirname(path.dirname(__dirname));
let root = path.resolve(src, '..', '..', 'cjs');

if (!mathjax.asyncLoad && typeof require !== 'undefined') {
mathjax.asyncLoad = (name: string) => {
return require(name.charAt(0) === '.' ? path.resolve(root, name) : name);
};
mathjax.asyncIsSynchronous = true;
}


/**
* @param {string} URL the base URL to use for loading relative paths
*/
Expand Down
2 changes: 1 addition & 1 deletion ts/util/asyncLoad/path.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
declare module 'path' {
export function dirname(dir: string): string;
export function resolve(root: string, name: string): string;
export function resolve(root: string, ...name: string[]): string;
}
9 changes: 5 additions & 4 deletions ts/util/asyncLoad/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ let root = 'file://' + __dirname.replace(/\/[^\/]*\/[^\/]*$/, '/');

if (!mathjax.asyncLoad && typeof System !== 'undefined' && System.import) {
mathjax.asyncLoad = (name: string) => {
return System.import(name, root).then((result: any) => result?.default || result);
const file = (name.charAt(0) === '.' ? new URL(name, root) : new URL(name, 'file://')).href;
return System.import(file).then((result: any) => result?.default || result);
};
}

/**
* @param {string} URL the base URL to use for loading relative paths
* @param {string} url the base URL to use for loading relative paths
*/
export function setBaseURL(URL: string) {
root = URL;
export function setBaseURL(url: string) {
root = new URL(url, 'file://').href;
if (!root.match(/\/$/)) {
root += '/';
}
Expand Down