Skip to content

Commit db8dc75

Browse files
committed
feat(experimental): standalone ref transform
1 parent 84b24a7 commit db8dc75

16 files changed

+1257
-872
lines changed

.eslintrc.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ module.exports = {
4949
},
5050
// Packages targeting Node
5151
{
52-
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
52+
files: [
53+
'packages/{compiler-sfc,compiler-ssr,server-renderer,ref-transform}/**'
54+
],
5355
rules: {
5456
'no-restricted-globals': ['error', ...DOMGlobals],
5557
'no-restricted-syntax': 'off'

packages/compiler-core/src/babelUtils.ts

+63-41
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
Identifier,
44
Node,
55
Function,
6-
ObjectProperty
6+
ObjectProperty,
7+
BlockStatement
78
} from '@babel/types'
89
import { walk } from 'estree-walker'
910

@@ -17,9 +18,10 @@ export function walkIdentifiers(
1718
isLocal: boolean
1819
) => void,
1920
onNode?: (node: Node, parent: Node, parentStack: Node[]) => void | boolean,
21+
includeAll = false,
22+
analyzeScope = true,
2023
parentStack: Node[] = [],
21-
knownIds: Record<string, number> = Object.create(null),
22-
includeAll = false
24+
knownIds: Record<string, number> = Object.create(null)
2325
) {
2426
const rootExp =
2527
root.type === 'Program' &&
@@ -42,62 +44,41 @@ export function walkIdentifiers(
4244
return this.skip()
4345
}
4446
if (node.type === 'Identifier') {
45-
const isLocal = !!knownIds[node.name]
47+
const isLocal = analyzeScope && !!knownIds[node.name]
4648
const isRefed = isReferencedIdentifier(node, parent!, parentStack)
4749
if (includeAll || (isRefed && !isLocal)) {
4850
onIdentifier(node, parent!, parentStack, isRefed, isLocal)
4951
}
50-
} else if (isFunctionType(node)) {
51-
// walk function expressions and add its arguments to known identifiers
52-
// so that we don't prefix them
53-
for (const p of node.params) {
54-
;(walk as any)(p, {
55-
enter(child: Node, parent: Node) {
56-
if (
57-
child.type === 'Identifier' &&
58-
// do not record as scope variable if is a destructured key
59-
!isStaticPropertyKey(child, parent) &&
60-
// do not record if this is a default value
61-
// assignment of a destructured variable
62-
!(
63-
parent &&
64-
parent.type === 'AssignmentPattern' &&
65-
parent.right === child
66-
)
67-
) {
68-
markScopeIdentifier(node, child, knownIds)
69-
}
70-
}
71-
})
72-
}
73-
} else if (node.type === 'BlockStatement') {
74-
// #3445 record block-level local variables
75-
for (const stmt of node.body) {
76-
if (stmt.type === 'VariableDeclaration') {
77-
for (const decl of stmt.declarations) {
78-
for (const id of extractIdentifiers(decl.id)) {
79-
markScopeIdentifier(node, id, knownIds)
80-
}
81-
}
82-
}
83-
}
8452
} else if (
8553
node.type === 'ObjectProperty' &&
8654
parent!.type === 'ObjectPattern'
8755
) {
8856
// mark property in destructure pattern
8957
;(node as any).inPattern = true
58+
} else if (analyzeScope) {
59+
if (isFunctionType(node)) {
60+
// walk function expressions and add its arguments to known identifiers
61+
// so that we don't prefix them
62+
walkFunctionParams(node, id =>
63+
markScopeIdentifier(node, id, knownIds)
64+
)
65+
} else if (node.type === 'BlockStatement') {
66+
// #3445 record block-level local variables
67+
walkBlockDeclarations(node, id =>
68+
markScopeIdentifier(node, id, knownIds)
69+
)
70+
}
9071
}
9172
},
9273
leave(node: Node & { scopeIds?: Set<string> }, parent: Node | undefined) {
9374
parent && parentStack.pop()
94-
if (node !== rootExp && node.scopeIds) {
95-
node.scopeIds.forEach((id: string) => {
75+
if (analyzeScope && node !== rootExp && node.scopeIds) {
76+
for (const id of node.scopeIds) {
9677
knownIds[id]--
9778
if (knownIds[id] === 0) {
9879
delete knownIds[id]
9980
}
100-
})
81+
}
10182
}
10283
}
10384
})
@@ -156,6 +137,47 @@ export function isInDestructureAssignment(
156137
return false
157138
}
158139

140+
export function walkFunctionParams(
141+
node: Function,
142+
onIdent: (id: Identifier) => void
143+
) {
144+
for (const p of node.params) {
145+
;(walk as any)(p, {
146+
enter(child: Node, parent: Node) {
147+
if (
148+
child.type === 'Identifier' &&
149+
// do not record as scope variable if is a destructured key
150+
!isStaticPropertyKey(child, parent) &&
151+
// do not record if this is a default value
152+
// assignment of a destructured variable
153+
!(
154+
parent &&
155+
parent.type === 'AssignmentPattern' &&
156+
parent.right === child
157+
)
158+
) {
159+
onIdent(child)
160+
}
161+
}
162+
})
163+
}
164+
}
165+
166+
export function walkBlockDeclarations(
167+
block: BlockStatement,
168+
onIdent: (node: Identifier) => void
169+
) {
170+
for (const stmt of block.body) {
171+
if (stmt.type === 'VariableDeclaration') {
172+
for (const decl of stmt.declarations) {
173+
for (const id of extractIdentifiers(decl.id)) {
174+
onIdent(id)
175+
}
176+
}
177+
}
178+
}
179+
}
180+
159181
function extractIdentifiers(
160182
param: Node,
161183
nodes: Identifier[] = []

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,10 @@ export function processExpression(
283283
}
284284
},
285285
undefined,
286+
true, // invoke on ALL identifiers
287+
true, // isLocal scope analysis
286288
parentStack,
287-
knownIds,
288-
// invoke on ALL identifiers
289-
true
289+
knownIds
290290
)
291291

292292
// We break up the compound expression into an array of strings and sub

0 commit comments

Comments
 (0)