UNPKG

reboost

Version:

A super fast dev server for rapid web development

180 lines (179 loc) 8.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createProcessor = exports.getPluginHooks = void 0; const tslib_1 = require("tslib"); const source_map_1 = require("source-map"); const chalk_1 = (0, tslib_1.__importDefault)(require("chalk")); const code_frame_1 = require("@babel/code-frame"); const estreeToolkit = (0, tslib_1.__importStar)(require("estree-toolkit")); const meriyah_1 = require("meriyah"); const fs_1 = (0, tslib_1.__importDefault)(require("fs")); const path_1 = (0, tslib_1.__importDefault)(require("path")); const utils_1 = require("../utils"); const pluginHooksMap = new Map(); const getPluginHooks = (instance) => { if (!pluginHooksMap.has(instance)) { const getHooks = (hookName) => (instance.plugins.map((plugin) => plugin[hookName]).filter((hook) => typeof hook === 'function')); pluginHooksMap.set(instance, { stopHooks: getHooks('stop'), resolveHooks: getHooks('resolve'), loadHooks: getHooks('load'), transformContentHooks: getHooks('transformContent'), transformIntoJSHooks: getHooks('transformIntoJS'), transformJSContentHooks: getHooks('transformJSContent'), transformASTHooks: getHooks('transformAST') }); instance.onStop('Removes plugins associated with the instance', () => pluginHooksMap.delete(instance)); } return pluginHooksMap.get(instance); }; exports.getPluginHooks = getPluginHooks; const createProcessor = (instance) => { const handleError = ({ message }) => { const line = '-'.repeat(process.stdout.columns); instance.log('info', chalk_1.default.red(line + '\n' + message + '\n' + line)); return { error: message }; }; return { process: async (filePath, pluginContext) => { const pluginHooks = (0, exports.getPluginHooks)(instance); let code; let sourceMap; let ast; let type; let programPath; for (const hook of pluginHooks.loadHooks) { const result = await (0, utils_1.bind)(hook, pluginContext)(filePath); if (result) { ({ code } = result); ({ type } = result); if (result.map) sourceMap = result.map; break; } } const runTransformContentHooks = async (hooks) => { for (const hook of hooks) { const result = await (0, utils_1.bind)(hook, pluginContext)({ code, type, map: sourceMap }, filePath); if (result) { if (result instanceof Error) return handleError(result); ({ code } = result); if (result.map) { // Here source maps sources can be null, like when source map is generated using MagicString (npm package) result.map.sources = result.map.sources.map((sourcePath) => !sourcePath ? filePath : sourcePath); sourceMap = sourceMap ? await (0, utils_1.mergeSourceMaps)(sourceMap, result.map) : result.map; } if (result.type) type = result.type; } } }; let transformContentError; transformContentError = await runTransformContentHooks(pluginHooks.transformContentHooks); if (transformContentError) return transformContentError; if (type !== 'js') { for (const hook of pluginHooks.transformIntoJSHooks) { const result = await (0, utils_1.bind)(hook, pluginContext)({ code, type, map: sourceMap }, filePath); if (result) { if (result instanceof Error) return handleError(result); ({ code } = result); sourceMap = result.inputMap; type = 'js'; break; } } } if (!['js', 'mjs', 'es6', 'es', 'cjs'].includes(type)) { let message = `${filePath}: File with type "${type}" is not supported. `; message += 'You may need proper loader to transform this kind of files into JS.'; return handleError({ message }); } transformContentError = await runTransformContentHooks(pluginHooks.transformJSContentHooks); if (transformContentError) return transformContentError; try { ast = (0, meriyah_1.parseModule)(code); } catch (e) /* istanbul ignore next */ { let message = ''; let consoleMessage = ''; // Example original message - `[1:4]: Unexpected token: 'end of source'` // After replace - `Unexpected token: 'end of source'` const frameMessage = e.message.replace(/^(\s*\[\d*:\d*\]:\s*)/, ''); let rawCode = code; let location = e.loc; let unableToLocateFile = false; message += `Error while parsing "${filePath}"\n`; consoleMessage += chalk_1.default.red(message); if (sourceMap) { const consumer = await new source_map_1.SourceMapConsumer(sourceMap); const originalLoc = consumer.originalPositionFor(e.loc); if (originalLoc.source) { const originalCode = consumer.sourceContentFor(originalLoc.source); if (originalCode) { rawCode = originalCode; location = originalLoc; location.column = location.column || 1; } else { const absPathToSource = path_1.default.join(instance.config.rootDir, originalLoc.source); if (fs_1.default.existsSync(absPathToSource)) { rawCode = fs_1.default.readFileSync(absPathToSource, 'utf8'); location = originalLoc; location.column = location.column || 1; } else { unableToLocateFile = true; } } } } if (unableToLocateFile) { let unableToLocateMsg = 'We are unable to locate the original file. '; unableToLocateMsg += 'This is not accurate, but it may help you at some point.\n\n'; message += unableToLocateMsg + (0, code_frame_1.codeFrameColumns)(code, { start: e.loc }, { message: frameMessage }); consoleMessage += unableToLocateMsg + (0, code_frame_1.codeFrameColumns)(code, { start: e.loc }, { highlightCode: true, message: frameMessage }); } else { message += (0, code_frame_1.codeFrameColumns)(rawCode, { start: location }, { message: frameMessage }); consoleMessage += (0, code_frame_1.codeFrameColumns)(rawCode, { start: location }, { highlightCode: true, message: frameMessage }); } instance.log('info', consoleMessage); return { error: message }; } estreeToolkit.traverse(ast, { $: { scope: true }, Program(path) { programPath = path; } }); for (const hook of pluginHooks.transformASTHooks) { await (0, utils_1.bind)(hook, pluginContext)(programPath, estreeToolkit, filePath); } return { programPath, sourceMap }; } }; }; exports.createProcessor = createProcessor;