Диагностика некорректной трансформации
Некорректная трансформация в 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
Любое отклонение между сборками сигнализирует о нестабильности трансформации или побочных эффектах в плагинах.