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
@@ -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
Expand All @@ -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')
antfu marked this conversation as resolved.
Show resolved Hide resolved
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
@@ -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
}

Expand Down