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

feat: treat pseudo ESM as ESM with custom loader, disable custom Node Loader by default #1778

Merged
merged 11 commits into from
Aug 5, 2022
37 changes: 31 additions & 6 deletions packages/vitest/src/runtime/loader.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { pathToFileURL } from 'url'
import { isNodeBuiltin } from 'mlly'
import { readFile } from 'fs/promises'
import { hasESMSyntax, isNodeBuiltin } from 'mlly'
import { normalizeModuleId } from 'vite-node/utils'
import { getWorkerState } from '../utils'
import type { Loader, Resolver } from '../types/loader'
import type { Loader, ResolveResult, Resolver } from '../types/loader'
import { ModuleFormat } from '../types/loader'

interface ContextCache {
isESM: boolean
source: string
}

const cache = new Map<string, ContextCache>()

// apply transformations only to libraries
// inline code preccessed by vite-node
@@ -18,15 +27,31 @@ export const resolve: Resolver = async (url, context, next) => {
if (resolver) {
const resolved = await resolver(id, importer)
if (resolved) {
return {
url: pathToFileURL(resolved.id).toString(),
const filepath = pathToFileURL(resolved.id).toString()
const result: ResolveResult = {
url: filepath,
shortCircuit: true,
}
const source = cache.get(resolved.id)?.source ?? await readFile(resolved.id, 'utf8')
const isESM = hasESMSyntax(source)
if (isESM) {
result.format = ModuleFormat.Module
cache.set(filepath, { isESM: true, source })
}
return result
}
}
return next(url, context, next)
}

export const load: Loader = (url, context, next) => {
return next(url, context, next)
export const load: Loader = async (url, context, next) => {
const result = await next(url, context, next)
const cached = cache.get(url)
if (cached?.isESM && result.format !== 'module') {
return {
source: cached.source,
format: ModuleFormat.Module,
}
}
return result
}
10 changes: 6 additions & 4 deletions packages/vitest/src/types/loader.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import type { Awaitable } from './general'

interface ModuleContext {
interface ModuleContext extends Record<string, unknown> {
conditions: string[]
parentURL?: string
}

enum ModuleFormat {
export enum ModuleFormat {
Builtin = 'builtin',
Commonjs = 'commonjs',
Json = 'json',
Module = 'module',
Wasm = 'wasm',
}

interface ResolveResult {
export interface ResolveResult {
url: string
shortCircuit?: boolean
format?: ModuleFormat
}

export interface Resolver {
(url: string, context: ModuleContext, next: Resolver): Awaitable<ResolveResult>
}

interface LoaderContext {
interface LoaderContext extends Record<string, any> {
format: ModuleFormat
importAssertions: Record<string, string>
}

interface LoaderResult {
format: ModuleFormat
shortCircuit?: boolean
source: string | ArrayBuffer | SharedArrayBuffer | Uint8Array
}