Skip to content

Commit

Permalink
fix: worker forever hang
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Jun 24, 2021
1 parent e0a0f35 commit b5e159f
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 31 deletions.
2 changes: 2 additions & 0 deletions packages/checker-vls/src/commands/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ async function getDiagnostics(
uri: URI.file(absFilePath).toString(),
version: DOC_VERSION.init,
})) as Diagnostic[]

/**
* Ignore eslint errors for now
*/
Expand All @@ -271,6 +272,7 @@ async function getDiagnostics(
console.error(err.stack)
}
}

logUpdate(logChunk)
return initialErrCount
}
Expand Down
8 changes: 5 additions & 3 deletions packages/checker-vls/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { isMainThread, parentPort } from 'worker_threads'

import { DiagnosticOptions, diagnostics } from './commands/diagnostics'

import type { ConfigEnv } from 'vite'

export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => {
let overlay = true // Vite defaults to true

Expand Down Expand Up @@ -47,10 +49,10 @@ const { mainScript, workerScript } = createScript<{ vls: VlsConfig }>({
})!

if (isMainThread) {
const createChecker = mainScript()
const configCurryFn = (vlsConfig: VlsConfig) => {
return (sharedConfig: SharedConfig) => {
return createChecker({ vls: vlsConfig, ...sharedConfig })
return (sharedConfig: SharedConfig, env: ConfigEnv) => {
const createChecker = mainScript()
return createChecker({ vls: vlsConfig, ...sharedConfig }, env)
}
}

Expand Down
13 changes: 8 additions & 5 deletions packages/vite-plugin-checker/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export * from './worker'
const sharedConfigKeys: (keyof SharedConfig)[] = ['enableBuild', 'overlay']
const buildInCheckerKeys: (keyof BuildInCheckers)[] = ['typescript', 'vueTsc']

function createCheckers(userConfig: UserPluginConfig): ServeAndBuildChecker[] {
function createCheckers(userConfig: UserPluginConfig, env: ConfigEnv): ServeAndBuildChecker[] {
const { typescript, vueTsc } = userConfig
const serveAndBuildCheckers: ServeAndBuildChecker[] = []
const sharedConfig = pick(userConfig, sharedConfigKeys)
Expand All @@ -31,13 +31,13 @@ function createCheckers(userConfig: UserPluginConfig): ServeAndBuildChecker[] {
if (typescript) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { createServeAndBuild } = require('./checkers/tsc')
serveAndBuildCheckers.push(createServeAndBuild({ typescript, ...sharedConfig }))
serveAndBuildCheckers.push(createServeAndBuild({ typescript, ...sharedConfig }, env))
}

if (vueTsc) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { createServeAndBuild } = require('./checkers/vue-tsc')
serveAndBuildCheckers.push(createServeAndBuild({ vueTsc, ...sharedConfig }))
serveAndBuildCheckers.push(createServeAndBuild({ vueTsc, ...sharedConfig }, env))
}

Object.keys(customCheckers).forEach((key) => {
Expand All @@ -46,14 +46,16 @@ function createCheckers(userConfig: UserPluginConfig): ServeAndBuildChecker[] {
typeof checkerCurryFn === 'function',
`Custom checker key should be a function, but got ${typeof checkerCurryFn}`
)
serveAndBuildCheckers.push(checkerCurryFn(sharedConfig))

serveAndBuildCheckers.push(checkerCurryFn(sharedConfig, env))
})

return serveAndBuildCheckers
}

export default function Plugin(userConfig?: UserPluginConfig): Plugin {
const checkers = createCheckers(userConfig || {})
let checkers: ServeAndBuildChecker[] = []
// const checkers = createCheckers(userConfig || {})
const enableBuild = userConfig?.enableBuild ?? true
let viteMode: ConfigEnv['command'] | undefined

Expand All @@ -63,6 +65,7 @@ export default function Plugin(userConfig?: UserPluginConfig): Plugin {
// for dev mode (1/2)
// Initialize checker with config
viteMode = env.command
checkers = createCheckers(userConfig || {}, env)
if (viteMode !== 'serve') return

checkers.forEach((checker) => {
Expand Down
11 changes: 8 additions & 3 deletions packages/vite-plugin-checker/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface SharedConfig {
overlay: boolean
}

export type CustomChecker = (vlsConfig: any) => ServeAndBuildChecker
export type CustomChecker = (checkerConfig: any, env: ConfigEnv) => ServeAndBuildChecker

export interface CustomCheckers {
// TODO: poor TS index signature type https://stackoverflow.com/questions/49969390/how-do-i-type-an-object-with-known-and-unknown-keys-in-typescript?noredirect=1&lq=1
Expand All @@ -56,9 +56,10 @@ export type UserPluginConfig = Partial<PluginConfig>
/* ----------------------------- worker actions ----------------------------- */

export enum ACTION_TYPES {
overlayError = 'overlayError',
config = 'config',
configureServer = 'configureServer',
overlayError = 'overlayError',
unref = 'unref',
}

interface Action {
Expand All @@ -83,7 +84,11 @@ export interface ConfigureServerAction extends Action {
}
}

export type Actions = OverlayErrorAction | ConfigAction | ConfigureServerAction
export interface UnrefAction extends Action {
type: ACTION_TYPES.unref
}

export type Actions = OverlayErrorAction | ConfigAction | ConfigureServerAction | UnrefAction

/* ----------------------------- internal types ----------------------------- */

Expand Down
58 changes: 40 additions & 18 deletions packages/vite-plugin-checker/src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { ConfigEnv } from 'vite'
import { parentPort, Worker, workerData } from 'worker_threads'

import { ACTION_TYPES } from './types'

import type {
// ServeCheckerFactory,
ServeChecker,
ConfigureServeChecker,
ConfigAction,
Expand All @@ -9,17 +12,16 @@ import type {
BuildCheckBin,
ServeAndBuildChecker,
SharedConfig,
UnrefAction,
} from './types'
import { ACTION_TYPES } from './types'

interface WorkerScriptOptions {
absFilename: string
buildBin: BuildCheckBin
serverChecker: ServeChecker
}

interface Script<T> {
mainScript: () => (config: T & SharedConfig) => ServeAndBuildChecker
mainScript: () => (config: T & SharedConfig, env: ConfigEnv) => ServeAndBuildChecker
workerScript: () => void
}

Expand All @@ -31,16 +33,23 @@ export function createScript<T>({
type CheckerConfig = T & SharedConfig
return {
mainScript: () => {
// console.log(process.env)
// initialized in main thread
const createWorker = (checkerConfig?: CheckerConfig): ConfigureServeChecker => {
const createWorker = (
checkerConfig: CheckerConfig,
env: ConfigEnv
): ConfigureServeChecker => {
const isBuild = env.command === 'build'
const worker = new Worker(absFilename, {
workerData: checkerConfig,
workerData: { env, checkerConfig },
})

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {
worker,
config: (config) => {
if (isBuild) return // just run the command

const configAction: ConfigAction = { type: ACTION_TYPES.config, payload: config }
worker.postMessage(configAction)
},
Expand All @@ -54,27 +63,40 @@ export function createScript<T>({
}
}

return (config) => ({
serve: createWorker(config),
return (config, env) => ({
serve: createWorker(config, env),
build: { buildBin },
})
},
workerScript: () => {
// runs in worker thread
let diagnostic: CheckerDiagnostic | null = null
if (!parentPort) throw Error('should have parentPort as file runs in worker thread')
const isBuild = workerData.env.command === 'build'
// only run bin command and do not listen message in build mode
if (isBuild) return

parentPort.on('message', (action: ConfigAction | ConfigureServerAction) => {
if (action.type === ACTION_TYPES.config) {
// const checker = checkerFactory()
const checkerConfig: T = workerData
diagnostic = serverChecker.createDiagnostic(checkerConfig)
diagnostic.config(action.payload)
} else if (action.type === ACTION_TYPES.configureServer) {
if (!diagnostic) throw Error('diagnostic should be initialized in `config` hook of Vite')
diagnostic.configureServer(action.payload)
const port = parentPort.on(
'message',
(action: ConfigAction | ConfigureServerAction | UnrefAction) => {
switch (action.type) {
case ACTION_TYPES.config: {
const checkerConfig: T = workerData.checkerConfig
diagnostic = serverChecker.createDiagnostic(checkerConfig)
diagnostic.config(action.payload)
break
}
case ACTION_TYPES.configureServer:
if (!diagnostic)
throw Error('diagnostic should be initialized in `config` hook of Vite')
diagnostic.configureServer(action.payload)
break
case ACTION_TYPES.unref:
port.unref()
break
}
}
})
)
},
}
}
5 changes: 4 additions & 1 deletion playground/vue2-vls/__tests__/build.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ describe('vue2-vls', () => {

describe('build', () => {
it('console error', async () => {
await viteBuild({ expectErrorMsg: 'error TS2345', cwd: composeTestTempDirPath() })
await viteBuild({
expectErrorMsg: `Property 'msg1' does not exist on type`,
cwd: composeTestTempDirPath(),
})
})
})
})
2 changes: 1 addition & 1 deletion vetur.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ module.exports = {
},
// **optional** default: `[{ root: './' }]`
// support monorepos
projects: ['./playground/vue2-vls'],
projects: ['./playground/vue2-vls', './temp/vue2-vls'],
}

0 comments on commit b5e159f

Please sign in to comment.