Skip to content

Commit 63f9deb

Browse files
committed
Incorporate import assertions into docs importer
1 parent 0f5c20b commit 63f9deb

File tree

2 files changed

+40
-20
lines changed

2 files changed

+40
-20
lines changed

src/modules/loader/__tests__/loader.test.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '../loaders'
1212
import type { ModuleDocumentation, ModuleManifest } from '../../moduleTypes'
1313

14-
const moduleMocker = vi.hoisted(() => vi.fn())
14+
const moduleMocker = vi.fn()
1515

1616
// Using virtual modules, we can pretend the modules with the given
1717
// import path actually exist
@@ -56,16 +56,12 @@ describe('bundle loading', () => {
5656
})
5757

5858
describe('tab loading', () => {
59-
const mockedFetch = vi.spyOn(global, 'fetch')
60-
6159
test("Load a module's tabs", async () => {
62-
mockedFetch.mockResolvedValueOnce({
63-
json: () =>
64-
Promise.resolve({
65-
one_module: { tabs: ['tab1', 'tab2'] }
66-
}),
67-
status: 200
68-
} as any)
60+
mockedDocsImporter.mockResolvedValueOnce({
61+
default: {
62+
one_module: { tabs: ['tab1', 'tab2'] }
63+
}
64+
})
6965

7066
const tabs = await loadModuleTabsAsync('one_module')
7167

src/modules/loader/importers.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { ModuleBundle } from '../moduleTypes'
66
export let MODULES_STATIC_URL = 'https://source-academy.github.io/modules'
77

88
export function setModulesStaticURL(url: string) {
9+
console.log('Modules Static URL set to', url)
910
MODULES_STATIC_URL = url
1011
}
1112

@@ -33,18 +34,41 @@ function wrapImporter<T>(func: (p: string) => Promise<T>) {
3334
}
3435
}
3536

36-
export const docsImporter = wrapImporter<{ default: any }>(async p => {
37-
// TODO: Use import attributes when they become supported
38-
// Import Assertions and Attributes are not widely supported by all
39-
// browsers yet, so we use fetch in the meantime
40-
const resp = await fetch(p)
41-
if (resp.status !== 200 && resp.status !== 304) {
42-
throw new ModuleConnectionError()
37+
function getDocsImporter(): (p: string) => Promise<{ default: object }> {
38+
async function fallbackImporter(p: string) {
39+
const resp = await fetch(p)
40+
if (resp.status !== 200 && resp.status !== 304) {
41+
throw new ModuleConnectionError()
42+
}
43+
44+
const result = await resp.json()
45+
return { default: result }
46+
}
47+
48+
if (process.env.NODE_ENV === 'test') {
49+
return async p => {
50+
// @ts-expect-error This directive is here until js-slang moves to ESM
51+
const result = await import(p, { with: { type: 'json' } })
52+
return result
53+
}
4354
}
4455

45-
const result = await resp.json()
46-
return { default: result }
47-
})
56+
if (typeof window !== 'undefined') {
57+
try {
58+
return new Function(
59+
'path',
60+
"return import(`${path}?q=${Date.now()}`, { with: { type: 'json'} })"
61+
) as any
62+
} catch {
63+
// If the browser doesn't support import assertions, the above call will throw an error.
64+
// In that case, fallback to using fetch
65+
}
66+
}
67+
68+
return fallbackImporter
69+
}
70+
71+
export const docsImporter = wrapImporter<{ default: any }>(getDocsImporter())
4872

4973
function getBundleAndTabImporter(): (p: string) => Promise<{ default: ModuleBundle }> {
5074
if (process.env.NODE_ENV === 'test') {

0 commit comments

Comments
 (0)