Skip to content

Commit e48cbf0

Browse files
committed
refactor: restore SourceLocation.source
this is used extensively in @vue/language-tools and does not have noticeable impact on performance
1 parent 08f0baa commit e48cbf0

File tree

9 files changed

+496
-139
lines changed

9 files changed

+496
-139
lines changed

packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap

Lines changed: 229 additions & 0 deletions
Large diffs are not rendered by default.

packages/compiler-core/__tests__/parse.spec.ts

Lines changed: 210 additions & 105 deletions
Large diffs are not rendered by default.

packages/compiler-core/src/ast.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export interface Node {
7676
export interface SourceLocation {
7777
start: Position
7878
end: Position
79+
source: string
7980
}
8081

8182
export interface Position {
@@ -198,11 +199,6 @@ export interface DirectiveNode extends Node {
198199
*/
199200
rawName?: string
200201
exp: ExpressionNode | undefined
201-
/**
202-
* the raw expression as a string
203-
* only required on directives parsed from templates
204-
*/
205-
rawExp?: string
206202
arg: ExpressionNode | undefined
207203
modifiers: string[]
208204
/**
@@ -570,7 +566,8 @@ export interface ForIteratorExpression extends FunctionExpression {
570566
// Container types like CompoundExpression also don't need a real location.
571567
export const locStub: SourceLocation = {
572568
start: { line: 1, column: 1, offset: 0 },
573-
end: { line: 1, column: 1, offset: 0 }
569+
end: { line: 1, column: 1, offset: 0 },
570+
source: ''
574571
}
575572

576573
export function createRoot(

packages/compiler-core/src/parser.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ const tokenizer = new Tokenizer(stack, {
218218
name,
219219
rawName: raw,
220220
exp: undefined,
221-
rawExp: undefined,
222221
arg: undefined,
223222
modifiers: raw === '.' ? ['prop'] : [],
224223
loc: getLoc(start)
@@ -241,7 +240,7 @@ const tokenizer = new Tokenizer(stack, {
241240
const arg = getSlice(start, end)
242241
if (inVPre) {
243242
;(currentProp as AttributeNode).name += arg
244-
;(currentProp as AttributeNode).nameLoc.end = tokenizer.getPos(end)
243+
setLocEnd((currentProp as AttributeNode).nameLoc, end)
245244
} else {
246245
const isStatic = arg[0] !== `[`
247246
;(currentProp as DirectiveNode).arg = createSimpleExpression(
@@ -257,14 +256,14 @@ const tokenizer = new Tokenizer(stack, {
257256
const mod = getSlice(start, end)
258257
if (inVPre) {
259258
;(currentProp as AttributeNode).name += '.' + mod
260-
;(currentProp as AttributeNode).nameLoc.end = tokenizer.getPos(end)
259+
setLocEnd((currentProp as AttributeNode).nameLoc, end)
261260
} else if ((currentProp as DirectiveNode).name === 'slot') {
262261
// slot has no modifiers, special case for edge cases like
263262
// https://github.com/vuejs/language-tools/issues/2710
264263
const arg = (currentProp as DirectiveNode).arg
265264
if (arg) {
266265
;(arg as SimpleExpressionNode).content += '.' + mod
267-
arg.loc.end = tokenizer.getPos(end)
266+
setLocEnd(arg.loc, end)
268267
}
269268
} else {
270269
;(currentProp as DirectiveNode).modifiers.push(mod)
@@ -302,7 +301,7 @@ const tokenizer = new Tokenizer(stack, {
302301
onattribend(quote, end) {
303302
if (currentOpenTag && currentProp) {
304303
// finalize end pos
305-
currentProp.loc.end = tokenizer.getPos(end)
304+
setLocEnd(currentProp.loc, end)
306305

307306
if (quote !== QuoteType.NoValue) {
308307
if (__BROWSER__ && currentAttrValue.includes('&')) {
@@ -345,7 +344,6 @@ const tokenizer = new Tokenizer(stack, {
345344
}
346345
} else {
347346
// directive
348-
currentProp.rawExp = currentAttrValue
349347
currentProp.exp = createSimpleExpression(
350348
currentAttrValue,
351349
false,
@@ -562,7 +560,7 @@ function onText(content: string, start: number, end: number) {
562560
if (lastNode?.type === NodeTypes.TEXT) {
563561
// merge
564562
lastNode.content += content
565-
lastNode.loc.end = tokenizer.getPos(end)
563+
setLocEnd(lastNode.loc, end)
566564
} else {
567565
parent.children.push({
568566
type: NodeTypes.TEXT,
@@ -576,9 +574,9 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
576574
// attach end position
577575
if (isImplied) {
578576
// implied close, end should be backtracked to close
579-
el.loc.end = tokenizer.getPos(backTrack(end, CharCodes.Lt))
577+
setLocEnd(el.loc, backTrack(end, CharCodes.Lt))
580578
} else {
581-
el.loc.end = tokenizer.getPos(end + fastForward(end, CharCodes.Gt) + 1)
579+
setLocEnd(el.loc, end + fastForward(end, CharCodes.Gt) + 1)
582580
}
583581

584582
if (tokenizer.inSFCRoot) {
@@ -588,6 +586,10 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
588586
} else {
589587
el.innerLoc!.end = extend({}, el.innerLoc!.start)
590588
}
589+
el.innerLoc!.source = getSlice(
590+
el.innerLoc!.start.offset,
591+
el.innerLoc!.end.offset
592+
)
591593
}
592594

593595
// refine element type
@@ -885,10 +887,17 @@ function getLoc(start: number, end?: number): SourceLocation {
885887
return {
886888
start: tokenizer.getPos(start),
887889
// @ts-expect-error allow late attachment
888-
end: end && tokenizer.getPos(end)
890+
end: end == null ? end : tokenizer.getPos(end),
891+
// @ts-expect-error allow late attachment
892+
source: end == null ? end : getSlice(start, end)
889893
}
890894
}
891895

896+
function setLocEnd(loc: SourceLocation, end: number) {
897+
loc.end = tokenizer.getPos(end)
898+
loc.source = getSlice(loc.start.offset, end)
899+
}
900+
892901
function dirToAttr(dir: DirectiveNode): AttributeNode {
893902
const attr: AttributeNode = {
894903
type: NodeTypes.ATTRIBUTE,

packages/compiler-core/src/transforms/transformElement.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ export const transformElement: NodeTransform = (node, context) => {
158158
context.onError(
159159
createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, {
160160
start: node.children[0].loc.start,
161-
end: node.children[node.children.length - 1].loc.end
161+
end: node.children[node.children.length - 1].loc.end,
162+
source: ''
162163
})
163164
)
164165
}

packages/compiler-core/src/transforms/transformExpression.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ export function processExpression(
337337
false,
338338
{
339339
start: advancePositionWithClone(node.loc.start, source, start),
340-
end: advancePositionWithClone(node.loc.start, source, end)
340+
end: advancePositionWithClone(node.loc.start, source, end),
341+
source
341342
},
342343
id.isConstant ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT
343344
)

packages/compiler-core/src/transforms/vModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
3131

3232
// we assume v-model directives are always parsed
3333
// (not artificially created by a transform)
34-
const rawExp = dir.rawExp!
34+
const rawExp = exp.loc.source
3535
const expString =
3636
exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp
3737

packages/compiler-dom/__tests__/parse.spec.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ describe('DOM parser', () => {
2626
content: 'some<div>text</div>and<!--comment-->',
2727
loc: {
2828
start: { offset: 10, line: 1, column: 11 },
29-
end: { offset: 46, line: 1, column: 47 }
29+
end: { offset: 46, line: 1, column: 47 },
30+
source: 'some<div>text</div>and<!--comment-->'
3031
}
3132
})
3233
})
@@ -41,7 +42,8 @@ describe('DOM parser', () => {
4142
content: '&',
4243
loc: {
4344
start: { offset: 10, line: 1, column: 11 },
44-
end: { offset: 15, line: 1, column: 16 }
45+
end: { offset: 15, line: 1, column: 16 },
46+
source: '&amp;'
4547
}
4648
})
4749
})
@@ -75,7 +77,8 @@ describe('DOM parser', () => {
7577
content: 'some<div>text</div>and<!--comment-->',
7678
loc: {
7779
start: { offset: 7, line: 1, column: 8 },
78-
end: { offset: 43, line: 1, column: 44 }
80+
end: { offset: 43, line: 1, column: 44 },
81+
source: 'some<div>text</div>and<!--comment-->'
7982
}
8083
})
8184
})
@@ -90,7 +93,8 @@ describe('DOM parser', () => {
9093
content: '&amp;',
9194
loc: {
9295
start: { offset: 7, line: 1, column: 8 },
93-
end: { offset: 12, line: 1, column: 13 }
96+
end: { offset: 12, line: 1, column: 13 },
97+
source: '&amp;'
9498
}
9599
})
96100
})
@@ -104,7 +108,8 @@ describe('DOM parser', () => {
104108
content: 'some text',
105109
loc: {
106110
start: { offset: 14, line: 1, column: 15 },
107-
end: { offset: 23, line: 1, column: 24 }
111+
end: { offset: 23, line: 1, column: 24 },
112+
source: 'some text'
108113
}
109114
})
110115
})
@@ -175,7 +180,8 @@ describe('DOM parser', () => {
175180
content: '&ersand;',
176181
loc: {
177182
start: { offset: 0, line: 1, column: 1 },
178-
end: { offset: 11, line: 1, column: 12 }
183+
end: { offset: 11, line: 1, column: 12 },
184+
source: '&ampersand;'
179185
}
180186
})
181187
})
@@ -196,23 +202,26 @@ describe('DOM parser', () => {
196202
content: '&ampersand;',
197203
loc: {
198204
start: { offset: 7, line: 1, column: 8 },
199-
end: { offset: 20, line: 1, column: 21 }
205+
end: { offset: 20, line: 1, column: 21 },
206+
source: '"&ampersand;"'
200207
}
201208
})
202209
expect(text2).toStrictEqual({
203210
type: NodeTypes.TEXT,
204211
content: '&ersand;',
205212
loc: {
206213
start: { offset: 23, line: 1, column: 24 },
207-
end: { offset: 37, line: 1, column: 38 }
214+
end: { offset: 37, line: 1, column: 38 },
215+
source: '"&amp;ersand;"'
208216
}
209217
})
210218
expect(text3).toStrictEqual({
211219
type: NodeTypes.TEXT,
212220
content: '&!',
213221
loc: {
214222
start: { offset: 40, line: 1, column: 41 },
215-
end: { offset: 47, line: 1, column: 48 }
223+
end: { offset: 47, line: 1, column: 48 },
224+
source: '"&amp!"'
216225
}
217226
})
218227
})
@@ -226,7 +235,8 @@ describe('DOM parser', () => {
226235
content: '†',
227236
loc: {
228237
start: { offset: 0, line: 1, column: 1 },
229-
end: { offset: 6, line: 1, column: 7 }
238+
end: { offset: 6, line: 1, column: 7 },
239+
source: '&#x86;'
230240
}
231241
})
232242
})
@@ -247,12 +257,14 @@ describe('DOM parser', () => {
247257
constType: ConstantTypes.NOT_CONSTANT,
248258
loc: {
249259
start: { offset: 8, line: 1, column: 9 },
250-
end: { offset: 16, line: 1, column: 17 }
260+
end: { offset: 16, line: 1, column: 17 },
261+
source: 'a &lt; b'
251262
}
252263
},
253264
loc: {
254265
start: { offset: 5, line: 1, column: 6 },
255-
end: { offset: 19, line: 1, column: 20 }
266+
end: { offset: 19, line: 1, column: 20 },
267+
source: '{{ a &lt; b }}'
256268
}
257269
})
258270
})
@@ -272,7 +284,8 @@ describe('DOM parser', () => {
272284
children: [],
273285
loc: {
274286
start: { offset: 0, line: 1, column: 1 },
275-
end: { offset: 5, line: 1, column: 6 }
287+
end: { offset: 5, line: 1, column: 6 },
288+
source: '<img>'
276289
},
277290
codegenNode: undefined
278291
})
@@ -314,7 +327,8 @@ describe('DOM parser', () => {
314327
content: 'hello</textarea</textarea0>',
315328
loc: {
316329
start: { offset: 10, line: 1, column: 11 },
317-
end: { offset: 37, line: 1, column: 38 }
330+
end: { offset: 37, line: 1, column: 38 },
331+
source: 'hello</textarea</textarea0>'
318332
}
319333
})
320334
})

packages/compiler-dom/src/transforms/Transition.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export const transformTransition: NodeTransform = (node, context) => {
2727
DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN,
2828
{
2929
start: node.children[0].loc.start,
30-
end: node.children[node.children.length - 1].loc.end
30+
end: node.children[node.children.length - 1].loc.end,
31+
source: ''
3132
}
3233
)
3334
)

0 commit comments

Comments
 (0)