js-slang
Version:
Javascript-based implementations of Source, written in Typescript
82 lines (81 loc) • 3.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.bundleAndTabImporter = exports.docsImporter = exports.MODULES_STATIC_URL = void 0;
exports.setModulesStaticURL = setModulesStaticURL;
const misc_1 = require("../../utils/misc");
const errors_1 = require("../errors");
/** Default modules static url. Exported for testing. */
exports.MODULES_STATIC_URL = 'https://source-academy.github.io/modules';
function setModulesStaticURL(url) {
console.log('Modules Static URL set to', url);
exports.MODULES_STATIC_URL = url;
}
function wrapImporter(func) {
return async (p) => {
try {
const result = await (0, misc_1.timeoutPromise)(func(p), 10000);
return result;
}
catch (error) {
// Before calling this function, the import analyzer should've been used to make sure
// that the module being imported already exists, so the following errors should
// be thrown only if the modules server is unreachable
if (
// In the browser, import statements should throw TypeError
(typeof window !== 'undefined' && error instanceof TypeError) ||
// In Node a different error is thrown with the given code instead
error.code === 'MODULE_NOT_FOUND' ||
// Thrown specifically by Vitest
(process.env.NODE_ENV === 'test' && error.code === 'ERR_UNSUPPORTED_ESM_URL_SCHEME')) {
throw new errors_1.ModuleConnectionError();
}
throw error;
}
};
}
function getDocsImporter() {
async function fallbackImporter(p) {
const resp = await fetch(p);
if (resp.status !== 200 && resp.status !== 304) {
throw new errors_1.ModuleConnectionError();
}
const result = await resp.json();
return { default: result };
}
if (process.env.NODE_ENV === 'test') {
return async (p) => {
// @ts-expect-error This directive is here until js-slang moves to ESM
const result = await Promise.resolve(`${p}`).then(s => require(s));
return result;
};
}
if (typeof window !== 'undefined') {
try {
return new Function('path', "return import(`${path}?q=${Date.now()}`, { with: { type: 'json'} })");
}
catch {
// If the browser doesn't support import assertions, the above call will throw an error.
// In that case, fallback to using fetch
}
}
return fallbackImporter;
}
exports.docsImporter = wrapImporter(getDocsImporter());
function getBundleAndTabImporter() {
if (process.env.NODE_ENV === 'test') {
return p => Promise.resolve(`${p}`).then(s => require(s));
}
if (typeof window !== 'undefined') {
return new Function('path', 'return import(`${path}?q=${Date.now()}`)');
}
// eslint-disable-next-line @typescript-eslint/no-require-imports
return p => Promise.resolve(require(p));
}
/*
Browsers natively support esm's import() but Node does not. So we need
to change which import function we use based on the environment.
For the browser, we use the function constructor to hide the import calls from
webpack so that webpack doesn't try to compile them away.
*/
exports.bundleAndTabImporter = wrapImporter(getBundleAndTabImporter());
//# sourceMappingURL=importers.js.map