0
# Utilities and Helpers
1
2
Vue Compiler Core provides a comprehensive set of utility functions for AST manipulation, type checking, identifier analysis, and common compiler operations.
3
4
## Capabilities
5
6
### AST Node Utilities
7
8
Functions for working with and analyzing AST nodes.
9
10
```typescript { .api }
11
/**
12
* Type guard for static expression nodes
13
* @param p - AST node to check
14
* @returns True if node is a static simple expression
15
*/
16
function isStaticExp(p: JSChildNode): p is SimpleExpressionNode;
17
18
/**
19
* Checks if a template child node is text or interpolation
20
* @param node - Node to check
21
* @returns True if node is TextNode or InterpolationNode
22
*/
23
function isText(node: TemplateChildNode): node is TextNode | InterpolationNode;
24
25
/**
26
* Type guard for v-slot directive
27
* @param p - Element prop to check
28
* @returns True if prop is a v-slot directive
29
*/
30
function isVSlot(p: ElementNode['props'][0]): p is DirectiveNode;
31
```
32
33
**Usage Examples:**
34
35
```typescript
36
import { isStaticExp, isText, isVSlot } from "@vue/compiler-core";
37
38
// Check if expression is static
39
if (isStaticExp(expression)) {
40
console.log('Static value:', expression.content);
41
}
42
43
// Filter text nodes from children
44
const textNodes = element.children.filter(isText);
45
46
// Find v-slot directives
47
const slotDirectives = element.props.filter(isVSlot);
48
```
49
50
### Element and Directive Queries
51
52
Functions for finding and working with element attributes and directives.
53
54
```typescript { .api }
55
/**
56
* Finds a directive on an element node
57
* @param node - Element node to search
58
* @param name - Directive name or pattern to match
59
* @param allowEmpty - Whether to match directives without expressions
60
* @returns Found directive node or undefined
61
*/
62
function findDir(
63
node: ElementNode,
64
name: string | RegExp,
65
allowEmpty?: boolean
66
): DirectiveNode | undefined;
67
68
/**
69
* Finds a prop or attribute on an element node
70
* @param node - Element node to search
71
* @param name - Prop/attribute name to find
72
* @param dynamicOnly - Only match dynamic props (v-bind)
73
* @param allowEmpty - Whether to match props without values
74
* @returns Found prop/attribute or undefined
75
*/
76
function findProp(
77
node: ElementNode,
78
name: string,
79
dynamicOnly?: boolean,
80
allowEmpty?: boolean
81
): ElementNode['props'][0] | undefined;
82
83
/**
84
* Checks if directive argument is static and matches name
85
* @param arg - Directive argument to check
86
* @param name - Name to match against
87
* @returns True if argument is static and matches
88
*/
89
function isStaticArgOf(arg: DirectiveNode['arg'], name: string): boolean;
90
91
/**
92
* Checks if element has dynamic key v-bind
93
* @param node - Element node to check
94
* @returns True if has dynamic v-bind:key
95
*/
96
function hasDynamicKeyVBind(node: ElementNode): boolean;
97
```
98
99
**Usage Examples:**
100
101
```typescript
102
import { findDir, findProp, isStaticArgOf, hasDynamicKeyVBind } from "@vue/compiler-core";
103
104
// Find v-if directive
105
const ifDir = findDir(element, 'if');
106
if (ifDir) {
107
console.log('v-if condition:', ifDir.exp?.content);
108
}
109
110
// Find class attribute or v-bind:class
111
const classProp = findProp(element, 'class');
112
113
// Check if v-on argument is static 'click'
114
if (isStaticArgOf(onDirective.arg, 'click')) {
115
console.log('Static click handler');
116
}
117
118
// Check for dynamic key binding
119
if (hasDynamicKeyVBind(element)) {
120
console.log('Element has dynamic key');
121
}
122
```
123
124
### Component and Asset Utilities
125
126
Functions for working with Vue components and assets.
127
128
```typescript { .api }
129
/**
130
* Checks if tag name refers to a core Vue component
131
* @param tag - Tag name to check
132
* @returns Symbol for core component or void
133
*/
134
function isCoreComponent(tag: string): symbol | void;
135
136
/**
137
* Converts name to valid asset identifier
138
* @param name - Asset name to convert
139
* @param type - Type of asset (component, directive, filter)
140
* @returns Valid JavaScript identifier
141
*/
142
function toValidAssetId(name: string, type: 'component' | 'directive' | 'filter'): string;
143
```
144
145
**Usage Examples:**
146
147
```typescript
148
import { isCoreComponent, toValidAssetId } from "@vue/compiler-core";
149
150
// Check for core components
151
const coreSymbol = isCoreComponent('Teleport');
152
if (coreSymbol) {
153
console.log('Teleport is a core component');
154
}
155
156
// Convert component name to valid identifier
157
const componentId = toValidAssetId('my-component', 'component');
158
// Result: "_component_my_component"
159
160
const directiveId = toValidAssetId('custom-directive', 'directive');
161
// Result: "_directive_custom_directive"
162
```
163
164
### Expression Analysis
165
166
Functions for analyzing JavaScript expressions in templates.
167
168
```typescript { .api }
169
/**
170
* Checks if name is a simple JavaScript identifier
171
* @param name - String to check
172
* @returns True if valid simple identifier
173
*/
174
function isSimpleIdentifier(name: string): boolean;
175
176
/**
177
* Checks if expression is a member access expression
178
* @param exp - Expression node to check
179
* @param context - Transform context
180
* @returns True if expression is member access
181
*/
182
function isMemberExpression(exp: ExpressionNode, context: TransformContext): boolean;
183
184
/**
185
* Checks if expression is a function expression
186
* @param exp - Expression node to check
187
* @param context - Transform context
188
* @returns True if expression is a function
189
*/
190
function isFnExpression(exp: ExpressionNode, context: TransformContext): boolean;
191
```
192
193
**Usage Examples:**
194
195
```typescript
196
import { isSimpleIdentifier, isMemberExpression, isFnExpression } from "@vue/compiler-core";
197
198
// Validate identifier names
199
if (isSimpleIdentifier('userName')) {
200
console.log('Valid identifier');
201
}
202
203
// Analyze expression types
204
if (isMemberExpression(expression, context)) {
205
console.log('Member access: obj.prop');
206
}
207
208
if (isFnExpression(expression, context)) {
209
console.log('Function expression');
210
}
211
```
212
213
### Advanced Expression Analysis
214
215
Browser and Node.js specific expression analysis functions for different runtime environments.
216
217
```typescript { .api }
218
/**
219
* Browser-specific member expression checker (lexical analysis)
220
* @param exp - Expression node to check
221
* @returns True if expression is member access
222
*/
223
function isMemberExpressionBrowser(exp: ExpressionNode): boolean;
224
225
/**
226
* Browser-specific function expression checker (lexical analysis)
227
* @param exp - Expression node to check
228
* @returns True if expression is a function
229
*/
230
function isFnExpressionBrowser(exp: ExpressionNode): boolean;
231
232
/**
233
* Checks if node contains expressions that reference current context scope ids
234
* @param node - Template child node, branch node, or expression to check
235
* @param ids - Transform context identifiers map
236
* @returns True if node references scope identifiers
237
*/
238
function hasScopeRef(
239
node: TemplateChildNode | IfBranchNode | ExpressionNode | CacheExpression | undefined,
240
ids: TransformContext['identifiers']
241
): boolean;
242
243
/**
244
* Regular expression for parsing v-for alias syntax
245
*/
246
const forAliasRE: RegExp;
247
```
248
249
### VNode and Prop Utilities
250
251
Functions for manipulating VNode calls and injecting properties.
252
253
```typescript { .api }
254
/**
255
* Injects a property into a VNode or RenderSlot call
256
* @param node - VNode call or render slot call to modify
257
* @param prop - Property to inject
258
* @param context - Transform context
259
*/
260
function injectProp(
261
node: VNodeCall | RenderSlotCall,
262
prop: Property,
263
context: TransformContext
264
): void;
265
266
/**
267
* Extracts VNode call from memo expression or returns node directly
268
* @param node - Block codegen node or memo expression
269
* @returns The underlying VNode or RenderSlot call
270
*/
271
function getMemoedVNodeCall(
272
node: BlockCodegenNode | MemoExpression
273
): VNodeCall | RenderSlotCall;
274
```
275
276
**Usage Examples:**
277
278
```typescript
279
import {
280
hasScopeRef,
281
injectProp,
282
getMemoedVNodeCall,
283
forAliasRE
284
} from "@vue/compiler-core";
285
286
// Check scope references
287
if (hasScopeRef(expression, context.identifiers)) {
288
console.log('Expression references scoped variables');
289
}
290
291
// Parse v-for syntax
292
const match = expression.match(forAliasRE);
293
if (match) {
294
const [, LHS, RHS] = match;
295
console.log('v-for alias:', LHS, 'in', RHS);
296
}
297
298
// Inject key property
299
const keyProperty = createProperty('key', createSimpleExpression('item.id'));
300
injectProp(vnodeCall, keyProperty, context);
301
302
// Extract VNode from memo
303
const actualVNode = getMemoedVNodeCall(memoOrVNode);
304
```
305
306
### Position and Location Utilities
307
308
Functions for working with source code positions and locations.
309
310
```typescript { .api }
311
/**
312
* Advances position and returns new Position (immutable)
313
* @param pos - Starting position
314
* @param source - Source text being advanced through
315
* @param numberOfCharacters - Number of characters to advance
316
* @returns New Position object
317
*/
318
function advancePositionWithClone(
319
pos: Position,
320
source: string,
321
numberOfCharacters?: number
322
): Position;
323
324
/**
325
* Advances position in-place (mutable)
326
* @param pos - Position to modify
327
* @param source - Source text being advanced through
328
* @param numberOfCharacters - Number of characters to advance
329
* @returns The same Position object (modified)
330
*/
331
function advancePositionWithMutation(
332
pos: Position,
333
source: string,
334
numberOfCharacters?: number
335
): Position;
336
```
337
338
**Usage Examples:**
339
340
```typescript
341
import { advancePositionWithClone, advancePositionWithMutation } from "@vue/compiler-core";
342
343
const startPos = { offset: 0, line: 1, column: 1 };
344
const source = "Hello\nWorld";
345
346
// Immutable advance
347
const newPos = advancePositionWithClone(startPos, source, 6);
348
console.log(newPos); // { offset: 6, line: 2, column: 1 }
349
console.log(startPos); // Still { offset: 0, line: 1, column: 1 }
350
351
// Mutable advance
352
const pos = { offset: 0, line: 1, column: 1 };
353
advancePositionWithMutation(pos, source, 6);
354
console.log(pos); // { offset: 6, line: 2, column: 1 }
355
```
356
357
### Assertion and Debugging
358
359
Utility functions for debugging and validation.
360
361
```typescript { .api }
362
/**
363
* Runtime assertion helper
364
* @param condition - Condition that should be true
365
* @param msg - Error message if assertion fails
366
* @throws Error if condition is false
367
*/
368
function assert(condition: boolean, msg?: string): void;
369
```
370
371
**Usage Examples:**
372
373
```typescript
374
import { assert } from "@vue/compiler-core";
375
376
// Validate assumptions during compilation
377
assert(node.type === NodeTypes.ELEMENT, 'Expected element node');
378
assert(directive.name === 'if', 'Expected v-if directive');
379
380
// Debug mode assertions
381
if (__DEV__) {
382
assert(context.currentNode !== null, 'Current node should not be null');
383
}
384
```
385
386
## Babel Integration Utilities
387
388
Functions for working with Babel AST nodes and JavaScript analysis.
389
390
### Identifier Walking
391
392
Functions for traversing and analyzing JavaScript identifiers.
393
394
```typescript { .api }
395
/**
396
* Walks AST and calls callback for each identifier
397
* @param root - Babel AST node to walk
398
* @param onIdentifier - Callback for each identifier found
399
* @param includeAll - Whether to include all identifiers or just references
400
* @param parentStack - Stack of parent nodes
401
* @param knownIds - Set of known identifier names
402
*/
403
function walkIdentifiers(
404
root: Node,
405
onIdentifier: (
406
node: Identifier,
407
parent: Node,
408
parentStack: Node[],
409
isReference: boolean,
410
isLocal: boolean
411
) => void,
412
includeAll?: boolean,
413
parentStack?: Node[],
414
knownIds?: Record<string, number>
415
): void;
416
417
/**
418
* Checks if identifier is being referenced (not declared)
419
* @param id - Identifier node
420
* @param parent - Parent node
421
* @param parentStack - Stack of ancestor nodes
422
* @returns True if identifier is a reference
423
*/
424
function isReferencedIdentifier(
425
id: Identifier,
426
parent: Node | null,
427
parentStack: Node[]
428
): boolean;
429
430
/**
431
* Extracts all identifier nodes from a parameter pattern
432
* @param param - Parameter node (can be pattern)
433
* @param nodes - Array to collect identifiers into
434
* @returns Array of identifier nodes
435
*/
436
function extractIdentifiers(
437
param: Node,
438
nodes?: Identifier[]
439
): Identifier[];
440
```
441
442
**Usage Examples:**
443
444
```typescript
445
import { walkIdentifiers, isReferencedIdentifier, extractIdentifiers } from "@vue/compiler-core";
446
447
// Walk expression and collect references
448
const references = new Set<string>();
449
walkIdentifiers(babelAst, (id, parent, parentStack, isReference) => {
450
if (isReference) {
451
references.add(id.name);
452
}
453
});
454
455
// Check specific identifier
456
if (isReferencedIdentifier(identifier, parent, parentStack)) {
457
console.log('Identifier is being referenced');
458
}
459
460
// Extract parameter names
461
const params = extractIdentifiers(functionNode.params[0]);
462
console.log('Parameter names:', params.map(p => p.name));
463
```
464
465
### Node Type Checking
466
467
Functions for checking Babel AST node types.
468
469
```typescript { .api }
470
/**
471
* Type guard for function nodes
472
* @param node - Node to check
473
* @returns True if node is any kind of function
474
*/
475
function isFunctionType(node: Node): node is Function;
476
477
/**
478
* Type guard for static object properties
479
* @param node - Node to check
480
* @returns True if node is a static object property
481
*/
482
function isStaticProperty(node: Node): node is ObjectProperty;
483
484
/**
485
* Unwraps TypeScript AST nodes to get underlying JavaScript
486
* @param node - Potentially wrapped TS node
487
* @returns Unwrapped JavaScript node
488
*/
489
function unwrapTSNode(node: Node): Node;
490
```
491
492
**Usage Examples:**
493
494
```typescript
495
import { isFunctionType, isStaticProperty, unwrapTSNode } from "@vue/compiler-core";
496
497
// Check for function nodes
498
if (isFunctionType(node)) {
499
console.log('Found function:', node.type);
500
}
501
502
// Filter static properties
503
const staticProps = objectExpression.properties.filter(isStaticProperty);
504
505
// Unwrap TypeScript annotations
506
const jsNode = unwrapTSNode(tsNode);
507
```
508
509
## Runtime Helpers
510
511
System for managing Vue runtime helper functions.
512
513
### Helper Symbols
514
515
Symbols representing Vue runtime helper functions.
516
517
```typescript { .api }
518
// Core VNode creation helpers
519
const FRAGMENT: unique symbol;
520
const TELEPORT: unique symbol;
521
const SUSPENSE: unique symbol;
522
const KEEP_ALIVE: unique symbol;
523
const BASE_TRANSITION: unique symbol;
524
525
// VNode creation functions
526
const OPEN_BLOCK: unique symbol;
527
const CREATE_BLOCK: unique symbol;
528
const CREATE_ELEMENT_BLOCK: unique symbol;
529
const CREATE_VNODE: unique symbol;
530
const CREATE_ELEMENT_VNODE: unique symbol;
531
const CREATE_COMMENT: unique symbol;
532
const CREATE_TEXT: unique symbol;
533
const CREATE_STATIC: unique symbol;
534
535
// Component resolution
536
const RESOLVE_COMPONENT: unique symbol;
537
const RESOLVE_DYNAMIC_COMPONENT: unique symbol;
538
const RESOLVE_DIRECTIVE: unique symbol;
539
const RESOLVE_FILTER: unique symbol;
540
541
// Directive helpers
542
const WITH_DIRECTIVES: unique symbol;
543
544
// List rendering
545
const RENDER_LIST: unique symbol;
546
const RENDER_SLOT: unique symbol;
547
const CREATE_SLOTS: unique symbol;
548
549
// Utility helpers
550
const TO_DISPLAY_STRING: unique symbol;
551
const MERGE_PROPS: unique symbol;
552
const NORMALIZE_CLASS: unique symbol;
553
const NORMALIZE_STYLE: unique symbol;
554
const NORMALIZE_PROPS: unique symbol;
555
const GUARD_REACTIVE_PROPS: unique symbol;
556
const TO_HANDLERS: unique symbol;
557
const CAMELIZE: unique symbol;
558
const CAPITALIZE: unique symbol;
559
const TO_HANDLER_KEY: unique symbol;
560
561
// Optimization helpers
562
const SET_BLOCK_TRACKING: unique symbol;
563
const WITH_CTX: unique symbol;
564
const UNREF: unique symbol;
565
const IS_REF: unique symbol;
566
const WITH_MEMO: unique symbol;
567
const IS_MEMO_SAME: unique symbol;
568
569
// Deprecated helpers (kept for backwards compatibility)
570
const PUSH_SCOPE_ID: unique symbol;
571
const POP_SCOPE_ID: unique symbol;
572
```
573
574
### Helper Management
575
576
Functions for working with runtime helpers.
577
578
```typescript { .api }
579
/**
580
* Maps helper symbols to their runtime names
581
*/
582
const helperNameMap: Record<symbol, string>;
583
584
/**
585
* Registers additional runtime helpers
586
* @param helpers - Map of helper symbols to names
587
*/
588
function registerRuntimeHelpers(helpers: Record<symbol, string>): void;
589
```
590
591
**Usage Examples:**
592
593
```typescript
594
import {
595
CREATE_VNODE,
596
RESOLVE_COMPONENT,
597
helperNameMap,
598
registerRuntimeHelpers
599
} from "@vue/compiler-core";
600
601
// Get helper name
602
const vnodeHelper = helperNameMap[CREATE_VNODE]; // "createVNode"
603
const resolveHelper = helperNameMap[RESOLVE_COMPONENT]; // "resolveComponent"
604
605
// Register custom helpers
606
const customHelpers = {
607
[Symbol('CUSTOM_HELPER')]: 'customHelper'
608
};
609
registerRuntimeHelpers(customHelpers);
610
```
611
612
## Vue 2.x Compatibility
613
614
Functions for handling Vue 2.x compatibility features.
615
616
### Compatibility Checking
617
618
```typescript { .api }
619
/**
620
* Checks if a compatibility feature is enabled (without warnings)
621
* @param key - Compatibility feature key
622
* @param context - Transform context
623
* @returns True if feature is enabled
624
*/
625
function isCompatEnabled(
626
key: CompilerDeprecationTypes,
627
context: TransformContext | ParserContext
628
): boolean;
629
630
/**
631
* Checks if a compatibility feature is enabled and warns if deprecated
632
* @param key - Compatibility feature key
633
* @param context - Transform context
634
* @param loc - Source location for warning
635
* @param args - Additional arguments for warning message
636
* @returns True if feature is enabled
637
*/
638
function checkCompatEnabled(
639
key: CompilerDeprecationTypes,
640
context: TransformContext | ParserContext,
641
loc: SourceLocation | null,
642
...args: any[]
643
): boolean;
644
645
/**
646
* Issues a deprecation warning
647
* @param key - Deprecation type
648
* @param context - Transform context
649
* @param message - Additional warning message
650
*/
651
function warnDeprecation(
652
key: CompilerDeprecationTypes,
653
context: TransformContext | ParserContext,
654
message?: string
655
): void;
656
657
/**
658
* Types of compiler deprecations for Vue 2.x compatibility
659
*/
660
enum CompilerDeprecationTypes {
661
COMPILER_IS_ON_ELEMENT = "COMPILER_IS_ON_ELEMENT",
662
COMPILER_V_BIND_SYNC = "COMPILER_V_BIND_SYNC",
663
COMPILER_V_BIND_PROP = "COMPILER_V_BIND_PROP",
664
COMPILER_V_BIND_OBJECT_ORDER = "COMPILER_V_BIND_OBJECT_ORDER",
665
COMPILER_V_ON_NATIVE = "COMPILER_V_ON_NATIVE",
666
COMPILER_V_IF_V_FOR_PRECEDENCE = "COMPILER_V_IF_V_FOR_PRECEDENCE",
667
COMPILER_NATIVE_TEMPLATE = "COMPILER_NATIVE_TEMPLATE",
668
COMPILER_INLINE_TEMPLATE = "COMPILER_INLINE_TEMPLATE",
669
COMPILER_FILTER = "COMPILER_FILTER"
670
}
671
```
672
673
**Usage Examples:**
674
675
```typescript
676
import {
677
checkCompatEnabled,
678
warnDeprecation,
679
CompilerDeprecationTypes
680
} from "@vue/compiler-core";
681
682
// Check if filters are enabled (Vue 2.x feature)
683
if (checkCompatEnabled(CompilerDeprecationTypes.COMPILER_FILTER, context)) {
684
// Process filter syntax
685
processFilter(node, context);
686
} else {
687
warnDeprecation(
688
CompilerDeprecationTypes.COMPILER_FILTER,
689
context,
690
'Filters are removed in Vue 3. Use computed properties or methods instead.'
691
);
692
}
693
```
694
695
## Common Utility Patterns
696
697
### Template Analysis
698
699
```typescript
700
// Check if element has Vue directives
701
function hasDirectives(element: ElementNode): boolean {
702
return element.props.some(prop => prop.type === NodeTypes.DIRECTIVE);
703
}
704
705
// Get all directive names on element
706
function getDirectiveNames(element: ElementNode): string[] {
707
return element.props
708
.filter((prop): prop is DirectiveNode => prop.type === NodeTypes.DIRECTIVE)
709
.map(dir => dir.name);
710
}
711
712
// Check if element is a Vue component
713
function isComponent(element: ElementNode): boolean {
714
return element.tagType === ElementTypes.COMPONENT;
715
}
716
```
717
718
### Expression Validation
719
720
```typescript
721
// Validate v-for expression format
722
function validateVForExpression(exp: string): boolean {
723
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
724
return forAliasRE.test(exp);
725
}
726
727
// Check if expression uses reserved keywords
728
function hasReservedKeywords(exp: string): boolean {
729
const reserved = ['arguments', 'eval', 'undefined', 'NaN', 'Infinity'];
730
return reserved.some(keyword => exp.includes(keyword));
731
}
732
```