or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-types.mdcompilation.mderror-handling.mdindex.mdtransforms.mdutilities.md

transforms.mddocs/

0

# Transform System

1

2

Vue Compiler Core's transform system provides a flexible plugin architecture for processing and modifying AST nodes. The system includes built-in transforms for Vue directives, structural elements, and optimizations, as well as extensibility for custom transforms.

3

4

## Capabilities

5

6

### Transform Context

7

8

The central context object that manages transformation state and provides utilities.

9

10

```typescript { .api }

11

/**

12

* Context object passed through all transformations

13

*/

14

interface TransformContext {

15

/** Root AST node being transformed */

16

root: RootNode;

17

/** Map of runtime helpers to usage count */

18

helpers: Map<symbol, number>;

19

/** Set of component names referenced */

20

components: Set<string>;

21

/** Set of directive names referenced */

22

directives: Set<string>;

23

/** Array of hoisted expressions */

24

hoists: (JSChildNode | null)[];

25

/** Import statements needed */

26

imports: ImportItem[];

27

/** Cache for constant expressions */

28

constantCache: WeakMap<TemplateChildNode, ConstantTypes>;

29

/** Number of temporary variables */

30

temps: number;

31

/** Number of cached expressions */

32

cached: number;

33

/** Identifier tracking for scoping */

34

identifiers: { [name: string]: number | undefined };

35

/** Scope counters for different directive types */

36

scopes: {

37

vFor: number;

38

vSlot: number;

39

vPre: number;

40

vOnce: number;

41

};

42

/** Current parent node */

43

parent: ParentNode | null;

44

/** Index of current node in parent's children */

45

childIndex: number;

46

/** Current node being processed */

47

currentNode: RootNode | TemplateChildNode | null;

48

/** Whether currently inside v-once */

49

inVOnce: boolean;

50

51

/** Add a runtime helper and return its name */

52

helper(name: symbol): string;

53

/** Remove a runtime helper */

54

removeHelper(name: symbol): void;

55

/** Get string representation of helper */

56

helperString(name: symbol): string;

57

/** Replace the current node */

58

replaceNode(node: TemplateChildNode): void;

59

/** Remove the current node */

60

removeNode(node?: TemplateChildNode): void;

61

/** Callback when node is removed */

62

onNodeRemoved: (() => void) | undefined;

63

/** Add identifiers to scope tracking */

64

addIdentifiers(exp: ExpressionNode | string): void;

65

/** Remove identifiers from scope tracking */

66

removeIdentifiers(exp: ExpressionNode | string): void;

67

/** Hoist an expression for static optimization */

68

hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode;

69

/** Cache an expression */

70

cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T;

71

}

72

73

/**

74

* Creates a new transform context

75

*/

76

function createTransformContext(

77

root: RootNode,

78

options: TransformOptions

79

): TransformContext;

80

```

81

82

### Transform Functions

83

84

Core functions for applying transformations to AST nodes.

85

86

```typescript { .api }

87

/**

88

* Traverses and transforms a single AST node and its children

89

* @param node - AST node to process

90

* @param context - Transform context

91

*/

92

function traverseNode(

93

node: RootNode | TemplateChildNode,

94

context: TransformContext

95

): void;

96

97

/**

98

* Creates a structural directive transform

99

* @param name - Directive name or pattern to match

100

* @param fn - Transform function to apply

101

* @returns Node transform function

102

*/

103

function createStructuralDirectiveTransform(

104

name: string | RegExp,

105

fn: StructuralDirectiveTransform

106

): NodeTransform;

107

```

108

109

**Usage Examples:**

110

111

```typescript

112

import {

113

createTransformContext,

114

traverseNode,

115

createStructuralDirectiveTransform

116

} from "@vue/compiler-core";

117

118

// Create transform context

119

const context = createTransformContext(ast, {

120

nodeTransforms: [/* transforms */],

121

directiveTransforms: {/* directive transforms */}

122

});

123

124

// Traverse and transform nodes

125

traverseNode(ast, context);

126

127

// Create custom structural directive transform

128

const customIfTransform = createStructuralDirectiveTransform(

129

'custom-if',

130

(node, dir, context) => {

131

// Transform logic here

132

}

133

);

134

```

135

136

### Transform Function Types

137

138

Type definitions for different kinds of transform functions.

139

140

```typescript { .api }

141

/**

142

* Node transform function signature

143

*/

144

type NodeTransform = (

145

node: RootNode | TemplateChildNode,

146

context: TransformContext

147

) => void | (() => void) | (() => void)[];

148

149

/**

150

* Directive transform function signature

151

*/

152

type DirectiveTransform = (

153

dir: DirectiveNode,

154

node: ElementNode,

155

context: TransformContext,

156

augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult

157

) => DirectiveTransformResult;

158

159

/**

160

* Structural directive transform function signature

161

*/

162

type StructuralDirectiveTransform = (

163

node: ElementNode,

164

dir: DirectiveNode,

165

context: TransformContext

166

) => void | (() => void);

167

168

/**

169

* Hoist transform function signature

170

*/

171

type HoistTransform = (

172

children: TemplateChildNode[],

173

context: TransformContext,

174

parent: ParentNode

175

) => void;

176

```

177

178

## Built-in Directive Transforms

179

180

Pre-built transforms for Vue's core directives.

181

182

### v-model Transform

183

184

Handles two-way data binding transformation.

185

186

```typescript { .api }

187

/**

188

* Transform for v-model directive

189

*/

190

const transformModel: DirectiveTransform;

191

```

192

193

**Usage Examples:**

194

195

```typescript

196

// Template: <input v-model="value" />

197

// Transforms to: <input :modelValue="value" @update:modelValue="value = $event" />

198

199

// Custom v-model transform in directive transforms map

200

const directiveTransforms = {

201

model: transformModel

202

};

203

```

204

205

### v-on Transform

206

207

Handles event listener transformation.

208

209

```typescript { .api }

210

/**

211

* Transform for v-on directive

212

*/

213

const transformOn: DirectiveTransform;

214

```

215

216

**Usage Examples:**

217

218

```typescript

219

// Template: <button v-on:click="handler" />

220

// Template: <button @click="handler" />

221

// Transforms to event listener binding

222

223

const directiveTransforms = {

224

on: transformOn

225

};

226

```

227

228

### v-bind Transform

229

230

Handles attribute and property binding.

231

232

```typescript { .api }

233

/**

234

* Transform for v-bind directive

235

*/

236

const transformBind: DirectiveTransform;

237

```

238

239

**Usage Examples:**

240

241

```typescript

242

// Template: <div v-bind:class="classes" />

243

// Template: <div :class="classes" />

244

// Transforms to property binding

245

246

const directiveTransforms = {

247

bind: transformBind

248

};

249

```

250

251

### No-op Transform

252

253

Placeholder transform for directives that don't need processing.

254

255

```typescript { .api }

256

/**

257

* No-operation directive transform

258

*/

259

const noopDirectiveTransform: DirectiveTransform;

260

```

261

262

## Structural Directive Processing

263

264

Functions for handling structural directives like v-if and v-for.

265

266

### v-if Processing

267

268

Handles conditional rendering transformation.

269

270

```typescript { .api }

271

/**

272

* Processes v-if structural directive

273

* @param node - Element node with v-if

274

* @param branch - If branch node

275

* @param context - Transform context

276

*/

277

function processIf(

278

node: ElementNode,

279

branch: IfBranchNode,

280

context: TransformContext,

281

processCodegen?: (node: IfNode, branch: IfBranchNode, isRoot: boolean) => () => void

282

): () => void;

283

```

284

285

**Usage Examples:**

286

287

```typescript

288

// Template: <div v-if="condition">Content</div>

289

// Processes into conditional render structure

290

291

import { processIf } from "@vue/compiler-core";

292

293

// Used within node transforms to handle v-if

294

const ifTransform: NodeTransform = (node, context) => {

295

if (node.type === NodeTypes.ELEMENT && hasDirective(node, 'if')) {

296

return processIf(node, branch, context);

297

}

298

};

299

```

300

301

### v-for Processing

302

303

Handles list rendering transformation.

304

305

```typescript { .api }

306

/**

307

* Processes v-for structural directive

308

* @param node - Element node with v-for

309

* @param context - Transform context

310

*/

311

function processFor(

312

node: ElementNode,

313

context: TransformContext,

314

processCodegen?: (forNode: ForNode, child: ElementNode, context: TransformContext) => (() => void) | undefined

315

): (() => void) | undefined;

316

317

/**

318

* Creates parameters for v-for loops

319

* @param parseResult - Parsed v-for expression

320

* @param context - Transform context

321

*/

322

function createForLoopParams(

323

parseResult: ForParseResult,

324

context: TransformContext

325

): ExpressionNode[];

326

```

327

328

**Usage Examples:**

329

330

```typescript

331

// Template: <li v-for="item in items" :key="item.id">{{ item.name }}</li>

332

// Processes into render list structure

333

334

import { processFor, createForLoopParams } from "@vue/compiler-core";

335

336

// Used within node transforms to handle v-for

337

const forTransform: NodeTransform = (node, context) => {

338

if (node.type === NodeTypes.ELEMENT && hasDirective(node, 'for')) {

339

return processFor(node, context);

340

}

341

};

342

```

343

344

## Expression Processing

345

346

Functions for handling JavaScript expressions within templates.

347

348

### Expression Transform

349

350

Main transform for processing JavaScript expressions.

351

352

```typescript { .api }

353

/**

354

* Node transform for JavaScript expressions

355

*/

356

const transformExpression: NodeTransform;

357

358

/**

359

* Processes JavaScript expressions in templates

360

* @param node - Expression node to process

361

* @param context - Transform context

362

* @param asParams - Whether to treat as function parameters

363

* @param asRawStatements - Whether to treat as raw statements

364

* @param localVars - Local variable context

365

*/

366

function processExpression(

367

node: SimpleExpressionNode,

368

context: TransformContext,

369

asParams?: boolean,

370

asRawStatements?: boolean,

371

localVars?: Record<string, number>

372

): ExpressionNode;

373

374

/**

375

* Stringifies expressions for static analysis

376

* @param exp - Expression to stringify

377

*/

378

function stringifyExpression(exp: ExpressionNode | string): string;

379

```

380

381

**Usage Examples:**

382

383

```typescript

384

import { transformExpression, processExpression } from "@vue/compiler-core";

385

386

// Include in node transforms for expression processing

387

const nodeTransforms = [

388

transformExpression, // Handles {{ expressions }} and directive values

389

// ... other transforms

390

];

391

392

// Manual expression processing

393

const processedExp = processExpression(simpleExp, context);

394

```

395

396

## Slot Processing

397

398

Functions for handling Vue slots and scoped slots.

399

400

### Slot Building

401

402

Functions for constructing slot expressions.

403

404

```typescript { .api }

405

/**

406

* Builds slot expressions from v-slot directives

407

* @param node - Element node with slots

408

* @param context - Transform context

409

* @param buildSlotFn - Function to build individual slots

410

*/

411

function buildSlots(

412

node: ElementNode,

413

context: TransformContext,

414

buildSlotFn?: SlotFnBuilder

415

): SlotsExpression;

416

417

/**

418

* Function signature for building individual slot functions

419

*/

420

type SlotFnBuilder = (

421

slotProps: ExpressionNode | undefined,

422

slotChildren: TemplateChildNode[],

423

loc: SourceLocation

424

) => FunctionExpression;

425

426

/**

427

* Processes slot outlet elements (<slot> tags)

428

* @param node - Slot outlet node

429

* @param context - Transform context

430

* @returns Slot name and props information

431

*/

432

function processSlotOutlet(

433

node: SlotOutletNode,

434

context: TransformContext

435

): { slotName: string | ExpressionNode; slotProps: PropsExpression | undefined };

436

437

/**

438

* Tracks v-for scope variables in slots

439

*/

440

const trackVForSlotScopes: NodeTransform;

441

442

/**

443

* Tracks slot scope variables

444

*/

445

const trackSlotScopes: NodeTransform;

446

```

447

448

**Usage Examples:**

449

450

```typescript

451

import { buildSlots, trackVForSlotScopes, trackSlotScopes } from "@vue/compiler-core";

452

453

// Include slot tracking in transforms

454

const nodeTransforms = [

455

trackSlotScopes,

456

trackVForSlotScopes,

457

// ... other transforms

458

];

459

460

// Build slots for component

461

const slots = buildSlots(componentNode, context);

462

```

463

464

## Element and Component Processing

465

466

Functions for processing element nodes and component resolution.

467

468

### Element Transform

469

470

Main transform for element processing.

471

472

```typescript { .api }

473

/**

474

* Main node transform for element processing

475

*/

476

const transformElement: NodeTransform;

477

478

/**

479

* Resolves component names to runtime references

480

* @param node - Element node

481

* @param context - Transform context

482

* @param ssr - Whether in SSR mode

483

*/

484

function resolveComponentType(

485

node: ElementNode,

486

context: TransformContext,

487

ssr?: boolean

488

): string | symbol;

489

490

/**

491

* Builds props expression from attributes and directives

492

* @param node - Element node

493

* @param context - Transform context

494

* @param props - Props array to process

495

* @param ssr - Whether in SSR mode

496

*/

497

function buildProps(

498

node: ElementNode,

499

context: TransformContext,

500

props?: ElementNode['props'],

501

ssr?: boolean

502

): PropsExpression | undefined;

503

504

/**

505

* Builds directive arguments array

506

* @param props - Props array containing directives

507

* @param context - Transform context

508

*/

509

function buildDirectiveArgs(

510

props: ElementNode['props'],

511

context: TransformContext

512

): DirectiveArguments | undefined;

513

514

/**

515

* Type for props expressions

516

*/

517

type PropsExpression = ObjectExpression | CallExpression | ExpressionNode;

518

```

519

520

### Slot Outlet Processing

521

522

Function for processing slot outlet elements.

523

524

```typescript { .api }

525

/**

526

* Processes slot outlet elements (<slot>)

527

* @param node - Slot outlet element

528

* @param context - Transform context

529

*/

530

function processSlotOutlet(

531

node: ElementNode,

532

context: TransformContext

533

): void;

534

```

535

536

### Static Analysis

537

538

Function for determining constant types for optimization.

539

540

```typescript { .api }

541

/**

542

* Determines if a node can be statically analyzed and cached

543

* @param node - AST node to analyze

544

* @param context - Transform context

545

*/

546

function getConstantType(

547

node: TemplateChildNode | TemplateChildNode[],

548

context: TransformContext

549

): ConstantTypes;

550

```

551

552

## Transform Result Types

553

554

Types for transform function results.

555

556

```typescript { .api }

557

/**

558

* Result of directive transform

559

*/

560

interface DirectiveTransformResult {

561

/** Generated props */

562

props: Property[];

563

/** Whether this directive needs runtime */

564

needRuntime?: boolean | symbol;

565

/** SSR-specific properties */

566

ssrTagParts?: TemplateLiteral['elements'];

567

}

568

569

/**

570

* Import item for transform context

571

*/

572

interface ImportItem {

573

/** Expression to import */

574

exp: string | ExpressionNode;

575

/** Path to import from */

576

path: string;

577

}

578

```

579

580

## Usage Patterns

581

582

### Custom Node Transform

583

584

```typescript

585

import { type NodeTransform, NodeTypes } from "@vue/compiler-core";

586

587

const customTransform: NodeTransform = (node, context) => {

588

if (node.type === NodeTypes.ELEMENT && node.tag === 'custom-element') {

589

// Transform custom elements

590

node.tag = 'div'; // Replace with div

591

return () => {

592

// Exit function called after children are processed

593

console.log('Custom element processed');

594

};

595

}

596

};

597

```

598

599

### Custom Directive Transform

600

601

```typescript

602

import { type DirectiveTransform } from "@vue/compiler-core";

603

604

const customDirectiveTransform: DirectiveTransform = (dir, node, context) => {

605

if (dir.name === 'custom') {

606

return {

607

props: [

608

// Generate props for the directive

609

createObjectProperty('customProp', dir.exp || createSimpleExpression('true', true))

610

]

611

};

612

}

613

return { props: [] };

614

};

615

```