Диагностика некорректной трансформации

Некорректная трансформация в SWC проявляется как расхождение между исходным JavaScript/TypeScript кодом и результатом, который формируется после компиляции. Такие ошибки редко связаны с самим парсером — чаще они возникают на уровне преобразований AST, конфигурации пресетов, взаимодействия плагинов или генерации source map. ### Природа ошибок трансформации в SWC SWC работает по классической схеме компилятора: **код → AST → трансформации → генерация кода → source map** Нарушение может возникнуть на любом этапе трансформаций, но диагностически важны именно промежуточные состояния AST и итоговая генерация. Типичные симптомы некорректной трансформации: * исчезновение или дублирование выражений * изменение семантики асинхронного кода * некорректное преобразование модулей ES ↔ CommonJS * сломанные импорты после bundle/transform * несоответствие source map исходному коду * различия поведения между dev и production сборкой ### Основные классы проблем #### Ошибки конфигурации трансформеров SWC строго следует конфигурации `.swcrc`. Малейшее расхождение приводит к радикально разному результату. Критические параметры: * `jsc.transform` * `module.type` * `minify` * `isModule` * `env.targets` Ошибочная комбинация, например включение `module: commonjs` при уже транспилированных модулях, приводит к двойному оборачиванию кода: ```js // исходный код export const a = 1; // после некорректной конфигурации "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.a = void 0; exports.a = 1; ``` Проблема усложняется, если одновременно активированы Babel-совместимые плагины. --- #### Неверные AST-трансформации SWC использует visitor-подобные трансформеры. Ошибки здесь проявляются как некорректные обходы дерева. Типичный сценарий — повторное изменение уже трансформированного узла. Пример: * исходное выражение: `a + b` * плагин преобразует в `sum(a, b)` * второй проход ошибочно применяет ту же трансформацию Результат: ```js sum(sum(a, b), undefined) ``` Диагностика требует анализа промежуточного AST через debug-вывод. --- #### Конфликты плагинов SWC позволяет расширять трансформации через плагины (Rust-based или JS bindings в некоторых обёртках). Конфликты возникают при: * одинаковых visitor-правилах * порядке выполнения transforms * перекрытии целей (например, JSX + custom transform) Если один плагин меняет структуру узла, второй может работать уже с невалидным состоянием. --- #### Проблемы генерации source map Одним из самых сложных классов ошибок являются рассинхронизации source map. Основные причины: * изменение AST без корректной привязки `span` * агрессивный minify * удаление узлов без сохранения позиции * объединение строк (line folding) Результат — код выполняется правильно, но дебаггер указывает на ложные строки. --- ### Инструменты диагностики #### Включение подробного логирования SWC поддерживает расширенные режимы вывода: * debug трансформаций * вывод промежуточного AST * контроль этапов компиляции При работе через `@swc/core` часто используется: ```js import { transformSync } from "@swc/core"; transformSync(code, { jsc: { parser: { syntax: "typescript", }, transform: { react: true, }, }, sourceMaps: true, configFile: false, minify: false, }); ``` Ключевой момент диагностики — отключение внешних конфигураций (`configFile: false`), чтобы исключить влияние глобальных настроек. --- #### Сравнение AST до и после трансформации SWC позволяет извлекать AST на разных этапах. Базовая стратегия: 1. получить AST после парсинга 2. применить transform 3. получить итоговый AST 4. сравнить структуру узлов Особое внимание уделяется: * `CallExpression` * `MemberExpression` * `ArrowFunctionExpression` * `ImportDeclaration` Любое изменение структуры узла без ожидаемой трансформации указывает на ошибку плагина или конфигурации. --- #### Проверка детерминированности трансформации SWC должен выдавать одинаковый результат при одинаковом входе. Нарушение детерминизма возникает при: * использовании нестабильных плагинов * параллельных трансформациях с shared state * мутации глобальных объектов внутри transform Симптом — один и тот же файл компилируется по-разному в разных запусках. --- #### Анализ module boundary ошибок Одна из самых частых проблем — некорректная обработка модулей. SWC различает: * ES Modules * CommonJS * AMD (редко) * UMD Ошибки проявляются при смешивании типов: ```js import x from "./x"; module.exports = x; ``` Результат может содержать дублирующие экспортные обёртки или потерю default export. Диагностика включает проверку: * `module.type` * наличия `interop` * флага `esModule` --- ### Source map как основной инструмент восстановления Корректный source map позволяет восстановить цепочку трансформаций. Ключевые проблемы: * смещение строк после minify * потеря колонок (column mapping) * некорректные inline mappings При анализе важно проверять: * соответствие оригинальных span * наличие `sourcesContent` * корректность VLQ-кодирования --- ### Типичные сценарии скрытых ошибок #### Асинхронные функции Неправильная трансформация async/await приводит к генерации state machine с нарушенной логикой переходов. Симптом: * зависание промисов * пропуск await * некорректный порядок выполнения --- #### JSX трансформация При использовании React трансформера возможны: * неправильный `key` injection * дублирование React.createElement вызовов * потеря Fragment структуры --- #### Tree-shaking эффекты Некорректная оптимизация приводит к удалению "якобы неиспользуемого" кода: ```js function helper() { console.log("used later"); } helper(); ``` После оптимизации функция может исчезнуть, если анализ зависимостей выполнен неверно. --- ### Методика изоляции проблемы Эффективная диагностика строится на последовательной изоляции: 1. отключение minify 2. отключение plugin transforms 3. переход на базовый parser-only режим 4. постепенное включение отдельных трансформаций 5. фиксация первого появления ошибки Такой подход позволяет точно определить слой, в котором происходит нарушение. --- ### Поведение SWC при некорректных AST span SWC активно использует `Span` для привязки исходного кода. При повреждении span: * source map становится неточным * генерация кода может сдвигать выражения * возможны "плавающие" ошибки runtime Особенно критично это при ручных AST трансформациях через API `@swc/core`, когда узлы создаются без корректных позиций. --- ### Различия поведения между Babel и SWC При диагностике часто выявляются расхождения: * SWC более агрессивен в оптимизациях * порядок visitor traversal отличается * некоторые edge-case трансформации упрощены Это приводит к ситуациям, когда код работает в Babel-сборке, но ломается в SWC. --- ### Контрольные точки стабильности трансформации Для устойчивой диагностики используются контрольные маркеры: * фиксация входного AST (hash) * фиксация результата transform stage * контроль длины output * сравнение source map checksum Любое отклонение между сборками сигнализирует о нестабильности трансформации или побочных эффектах в плагинах.