Skip to content

Commit

Permalink
feat: support emit object errors
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Feb 6, 2024
1 parent 63ad87c commit 8f00f57
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 53 deletions.
30 changes: 26 additions & 4 deletions src/esbuild/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { Buffer } from 'buffer'
import remapping from '@ampproject/remapping'
import { Parser } from 'acorn'
import type { DecodedSourceMap, EncodedSourceMap } from '@ampproject/remapping'
import type { BuildOptions, Loader, PartialMessage } from 'esbuild'
import type { BuildOptions, Loader, Location, Message, PartialMessage } from 'esbuild'
import type { SourceMap } from 'rollup'
import type { UnpluginBuildContext, UnpluginContext } from '../types'
import type { UnpluginBuildContext, UnpluginContext, UnpluginMessage } from '../types'

export * from '../utils'

Expand Down Expand Up @@ -144,8 +144,30 @@ export function createPluginContext(context: UnpluginBuildContext) {
const errors: PartialMessage[] = []
const warnings: PartialMessage[] = []
const pluginContext: UnpluginContext = {
error(message) { errors.push({ text: String(message) }) },
warn(message) { warnings.push({ text: String(message) }) },
error(message) { errors.push(normalizeMessage(message)) },
warn(message) { warnings.push(normalizeMessage(message)) },
}

function normalizeMessage(message: string | UnpluginMessage): Message {
if (typeof message === 'string')
message = { message }

return {
id: message.id!,
pluginName: message.plugin!,
text: message.message!,

location: message.loc
? {
file: message.loc.file,
line: message.loc.line,
column: message.loc.column,
} as Location
: null,

detail: message.meta,
notes: [],
}
}

const mixedContext: UnpluginContext & UnpluginBuildContext = {
Expand Down
18 changes: 15 additions & 3 deletions src/rspack/context.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Buffer } from 'buffer'
import sources from 'webpack-sources'
import type { Compilation } from '@rspack/core'
import type { Compilation, LoaderContext } from '@rspack/core'
import { Parser } from 'acorn'
import type { UnpluginBuildContext } from '..'
import type { UnpluginBuildContext, UnpluginContext, UnpluginMessage } from '../types'

export function createRspackContext(compilation: Compilation): UnpluginBuildContext {
export function createBuildContext(compilation: Compilation): UnpluginBuildContext {
return {
parse(code: string, opts: any = {}) {
return Parser.parse(code, {
Expand Down Expand Up @@ -36,3 +36,15 @@ export function createRspackContext(compilation: Compilation): UnpluginBuildCont
},
}
}

export function createContext(loader: LoaderContext): UnpluginContext {
function normalizeMessage(error: string | UnpluginMessage): Error {
return typeof error === 'string'
? new Error(error)
: error as Error
}
return {
error: error => loader.emitError(normalizeMessage(error)),
warn: message => loader.emitWarning(normalizeMessage(message)),
}
}
6 changes: 3 additions & 3 deletions src/rspack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
UnpluginFactory,
UnpluginInstance,
} from '../types'
import { createRspackContext } from './context'
import { createBuildContext } from './context'

const TRANSFORM_LOADER = resolve(
__dirname,
Expand Down Expand Up @@ -90,14 +90,14 @@ export function getRspackPlugin<UserOptions = Record<string, never>>(

if (plugin.buildStart) {
compiler.hooks.make.tapPromise(plugin.name, async (compilation) => {
const context = createRspackContext(compilation)
const context = createBuildContext(compilation)
return plugin.buildStart!.call(context)
})
}

if (plugin.buildEnd) {
compiler.hooks.emit.tapPromise(plugin.name, async (compilation) => {
await plugin.buildEnd!.call(createRspackContext(compilation))
await plugin.buildEnd!.call(createBuildContext(compilation))
})
}

Expand Down
11 changes: 3 additions & 8 deletions src/rspack/loaders/load.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { LoaderContext } from '@rspack/core'
import type { UnpluginContext } from '../../types'
import { createRspackContext } from '../context'
import { createBuildContext, createContext } from '../context'
import { normalizeAbsolutePath } from '../../utils'

export default async function load(this: LoaderContext, source: string, map: any) {
Expand All @@ -15,14 +14,10 @@ export default async function load(this: LoaderContext, source: string, map: any
if (plugin.loadInclude && !plugin.loadInclude(id))
return callback(null, source, map)

const context: UnpluginContext = {
error: error => this.emitError(typeof error === 'string' ? new Error(error) : error),
warn: error => this.emitWarning(typeof error === 'string' ? new Error(error) : error),
}

const context = createContext(this)
const res = await plugin.load.call(
Object.assign(
this._compilation && createRspackContext(this._compilation),
this._compilation && createBuildContext(this._compilation),
context,
),
normalizeAbsolutePath(id),
Expand Down
12 changes: 3 additions & 9 deletions src/rspack/loaders/transform.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { LoaderContext } from '@rspack/core'
import { createRspackContext } from '../context'
import type { UnpluginContext } from '../../types'
import { createBuildContext, createContext } from '../context'

export default async function transform(
this: LoaderContext,
Expand All @@ -24,15 +23,10 @@ export default async function transform(
if (!plugin?.transform)
return callback(null, source, map)

const context: UnpluginContext = {
error: error =>
this.emitError(typeof error === 'string' ? new Error(error) : error),
warn: error =>
this.emitWarning(typeof error === 'string' ? new Error(error) : error),
}
const context = createContext(this)
const res = await plugin.transform.call(
Object.assign(
this._compilation && createRspackContext(this._compilation),
this._compilation && createBuildContext(this._compilation),
context,
),
source,
Expand Down
20 changes: 18 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,25 @@ export type UnpluginContextMeta = Partial<RollupContextMeta> & ({
}
})

export interface UnpluginMessage {
name?: string
id?: string
message: string
stack?: string
code?: string
plugin?: string
pluginCode?: unknown
loc?: {
column: number
file?: string
line: number
}
meta?: any
}

export interface UnpluginContext {
error(message: any): void
warn(message: any): void
error(message: string | UnpluginMessage): void
warn(message: string | UnpluginMessage): void
}

declare module 'webpack' {
Expand Down
18 changes: 15 additions & 3 deletions src/webpack/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { resolve } from 'path'
import { Buffer } from 'buffer'
import process from 'process'
import sources from 'webpack-sources'
import type { Compilation } from 'webpack'
import type { Compilation, LoaderContext } from 'webpack'
import { Parser } from 'acorn'
import type { UnpluginBuildContext } from '../types'
import type { UnpluginBuildContext, UnpluginContext, UnpluginMessage } from '../types'

interface ContextOptions {
addWatchFile(file: string): void
Expand All @@ -22,7 +22,7 @@ export function contextOptionsFromCompilation(compilation: Compilation): Context
}
}

export function createContext(options: ContextOptions, compilation?: Compilation): UnpluginBuildContext {
export function createBuildContext(options: ContextOptions, compilation?: Compilation): UnpluginBuildContext {
return {
parse(code: string, opts: any = {}) {
return Parser.parse(code, {
Expand Down Expand Up @@ -61,3 +61,15 @@ export function createContext(options: ContextOptions, compilation?: Compilation
},
}
}

export function createContext(loader: LoaderContext<{ unpluginName: string }>): UnpluginContext {
function normalizeMessage(error: string | UnpluginMessage): Error {
return typeof error === 'string'
? new Error(error)
: error as Error
}
return {
error: error => loader.emitError(normalizeMessage(error)),
warn: message => loader.emitWarning(normalizeMessage(message)),
}
}
12 changes: 6 additions & 6 deletions src/webpack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import VirtualModulesPlugin from 'webpack-virtual-modules'
import type { ResolvePluginInstance, Resolver } from 'webpack'
import type { ResolvedUnpluginOptions, UnpluginContext, UnpluginContextMeta, UnpluginFactory, UnpluginInstance, WebpackCompiler } from '../types'
import { normalizeAbsolutePath, shouldLoad, toArray, transformUse } from '../utils'
import { contextOptionsFromCompilation, createContext } from './context'
import { contextOptionsFromCompilation, createBuildContext } from './context'

const TRANSFORM_LOADER = resolve(
__dirname,
Expand Down Expand Up @@ -92,7 +92,7 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(
// resolveContext.fileDependencies is typed as a WriteOnlySet, so make our own copy here
// so we can return it from getWatchFiles.
const fileDependencies = new Set<string>()
const context = createContext({
const context = createBuildContext({
addWatchFile(file) {
fileDependencies.add(file)
resolveContext.fileDependencies?.add(file)
Expand All @@ -103,9 +103,9 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(
})
let error: Error | undefined
const pluginContext: UnpluginContext = {
error(msg: string | Error) {
error(msg) {
if (error == null)
error = typeof msg === 'string' ? new Error(msg) : msg
error = typeof msg === 'string' ? new Error(msg) : msg as Error
else
console.error(`unplugin/webpack: multiple errors returned from resolveId hook: ${msg}`)
},
Expand Down Expand Up @@ -189,7 +189,7 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(

if (plugin.watchChange || plugin.buildStart) {
compiler.hooks.make.tapPromise(plugin.name, async (compilation) => {
const context = createContext(contextOptionsFromCompilation(compilation), compilation)
const context = createBuildContext(contextOptionsFromCompilation(compilation), compilation)
if (plugin.watchChange && (compiler.modifiedFiles || compiler.removedFiles)) {
const promises: Promise<void>[] = []
if (compiler.modifiedFiles) {
Expand All @@ -212,7 +212,7 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(

if (plugin.buildEnd) {
compiler.hooks.emit.tapPromise(plugin.name, async (compilation) => {
await plugin.buildEnd!.call(createContext(contextOptionsFromCompilation(compilation), compilation))
await plugin.buildEnd!.call(createBuildContext(contextOptionsFromCompilation(compilation), compilation))
})
}

Expand Down
11 changes: 3 additions & 8 deletions src/webpack/loaders/load.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { LoaderContext } from 'webpack'
import type { UnpluginContext } from '../../types'
import { createContext } from '../context'
import { createBuildContext, createContext } from '../context'
import { normalizeAbsolutePath } from '../../utils'

export default async function load(this: LoaderContext<any>, source: string, map: any) {
Expand All @@ -12,16 +11,12 @@ export default async function load(this: LoaderContext<any>, source: string, map
if (!plugin?.load || !id)
return callback(null, source, map)

const context: UnpluginContext = {
error: error => this.emitError(typeof error === 'string' ? new Error(error) : error),
warn: error => this.emitWarning(typeof error === 'string' ? new Error(error) : error),
}

if (id.startsWith(plugin.__virtualModulePrefix))
id = decodeURIComponent(id.slice(plugin.__virtualModulePrefix.length))

const context = createContext(this)
const res = await plugin.load.call(
{ ...createContext({
{ ...createBuildContext({
addWatchFile: (file) => {
this.addDependency(file)
},
Expand Down
10 changes: 3 additions & 7 deletions src/webpack/loaders/transform.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { LoaderContext } from 'webpack'
import type { UnpluginContext } from '../../types'
import { createContext } from '../context'
import { createBuildContext, createContext } from '../context'

export default async function transform(this: LoaderContext<{ unpluginName: string }>, source: string, map: any) {
const callback = this.async()
Expand All @@ -19,12 +18,9 @@ export default async function transform(this: LoaderContext<{ unpluginName: stri
if (!plugin?.transform)
return callback(null, source, map)

const context: UnpluginContext = {
error: error => this.emitError(typeof error === 'string' ? new Error(error) : error),
warn: error => this.emitWarning(typeof error === 'string' ? new Error(error) : error),
}
const context = createContext(this)
const res = await plugin.transform.call(
{ ...createContext({
{ ...createBuildContext({
addWatchFile: (file) => {
this.addDependency(file)
},
Expand Down

0 comments on commit 8f00f57

Please sign in to comment.