Skip to content
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
10 changes: 8 additions & 2 deletions packages/hot_hook/src/dynamic_import_checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { parseImports } from 'parse-imports'
* Otherwise we will throw an error since we cannot make the file reloadable
*
* We are caching the results to avoid reading the same file multiple times
*
* When no import is found for the given specifier we assume that it is imported using a dynamic specifier.
*/
export class DynamicImportChecker {
private cache: Map<string, Map<string, boolean>> = new Map()
Expand All @@ -20,10 +22,14 @@ export class DynamicImportChecker {
const parentCode = await readFile(parentPath, 'utf-8')
const imports = [...(await parseImports(parentCode))]

const isFileDynamicallyImportedFromParent = imports.some((importStatement) => {
return importStatement.isDynamicImport && importStatement.moduleSpecifier.value === specifier
const matchingImport = imports.find((importStatement) => {
return importStatement.moduleSpecifier.value === specifier
})

const isFileDynamicallyImportedFromParent = matchingImport
? matchingImport.isDynamicImport
: true

const currentCache = this.cache.get(cacheKey) ?? new Map()
this.cache.set(cacheKey, currentCache.set(specifier, isFileDynamicallyImportedFromParent))

Expand Down
10 changes: 9 additions & 1 deletion packages/hot_hook/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,15 @@ export class HotHookLoader {
debug('File change %s', relativeFilePath)

const filePath = pathResolve(relativeFilePath)
const realFilePath = await realpath(filePath)
const realFilePath = await realpath(filePath).catch(() => null)

/**
* Realpath throws an error when the file does not exist.
*/
if (!realFilePath) {
debug('Could not resolve realFilePath %s', filePath)
return this.#dependencyTree.remove(filePath)
}

/**
* First check if file still exists. If not, we must remove it from the
Expand Down
15 changes: 15 additions & 0 deletions packages/hot_hook/tests/dynamic_import_checker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,19 @@ test.group('Dynamic Import Checker', () => {
assert.isTrue(await checker.ensureFileIsImportedDynamicallyFromParent(path, './bla'))
assert.isTrue(await checker.ensureFileIsImportedDynamicallyFromParent(path, '#app/aliases-bla'))
})

test('Consider missing specifier as dynamically imported', async ({ assert, fs }) => {
await fs.create(
'app.ts',
`
import './foo'
await import('./bla')
`,
)

const checker = new DynamicImportChecker()
const path = join(fs.basePath, 'app.ts')

assert.isTrue(await checker.ensureFileIsImportedDynamicallyFromParent(path, './unknown'))
})
})