Skip to content

Commit

Permalink
feat(experimental): standalone ref transform
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Aug 23, 2021
1 parent 84b24a7 commit db8dc75
Show file tree
Hide file tree
Showing 16 changed files with 1,257 additions and 872 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Expand Up @@ -49,7 +49,9 @@ module.exports = {
},
// Packages targeting Node
{
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
files: [
'packages/{compiler-sfc,compiler-ssr,server-renderer,ref-transform}/**'
],
rules: {
'no-restricted-globals': ['error', ...DOMGlobals],
'no-restricted-syntax': 'off'
Expand Down
104 changes: 63 additions & 41 deletions packages/compiler-core/src/babelUtils.ts
Expand Up @@ -3,7 +3,8 @@ import {
Identifier,
Node,
Function,
ObjectProperty
ObjectProperty,
BlockStatement
} from '@babel/types'
import { walk } from 'estree-walker'

Expand All @@ -17,9 +18,10 @@ export function walkIdentifiers(
isLocal: boolean
) => void,
onNode?: (node: Node, parent: Node, parentStack: Node[]) => void | boolean,
includeAll = false,
analyzeScope = true,
parentStack: Node[] = [],
knownIds: Record<string, number> = Object.create(null),
includeAll = false
knownIds: Record<string, number> = Object.create(null)
) {
const rootExp =
root.type === 'Program' &&
Expand All @@ -42,62 +44,41 @@ export function walkIdentifiers(
return this.skip()
}
if (node.type === 'Identifier') {
const isLocal = !!knownIds[node.name]
const isLocal = analyzeScope && !!knownIds[node.name]
const isRefed = isReferencedIdentifier(node, parent!, parentStack)
if (includeAll || (isRefed && !isLocal)) {
onIdentifier(node, parent!, parentStack, isRefed, isLocal)
}
} else if (isFunctionType(node)) {
// walk function expressions and add its arguments to known identifiers
// so that we don't prefix them
for (const p of node.params) {
;(walk as any)(p, {
enter(child: Node, parent: Node) {
if (
child.type === 'Identifier' &&
// do not record as scope variable if is a destructured key
!isStaticPropertyKey(child, parent) &&
// do not record if this is a default value
// assignment of a destructured variable
!(
parent &&
parent.type === 'AssignmentPattern' &&
parent.right === child
)
) {
markScopeIdentifier(node, child, knownIds)
}
}
})
}
} else if (node.type === 'BlockStatement') {
// #3445 record block-level local variables
for (const stmt of node.body) {
if (stmt.type === 'VariableDeclaration') {
for (const decl of stmt.declarations) {
for (const id of extractIdentifiers(decl.id)) {
markScopeIdentifier(node, id, knownIds)
}
}
}
}
} else if (
node.type === 'ObjectProperty' &&
parent!.type === 'ObjectPattern'
) {
// mark property in destructure pattern
;(node as any).inPattern = true
} else if (analyzeScope) {
if (isFunctionType(node)) {
// walk function expressions and add its arguments to known identifiers
// so that we don't prefix them
walkFunctionParams(node, id =>
markScopeIdentifier(node, id, knownIds)
)
} else if (node.type === 'BlockStatement') {
// #3445 record block-level local variables
walkBlockDeclarations(node, id =>
markScopeIdentifier(node, id, knownIds)
)
}
}
},
leave(node: Node & { scopeIds?: Set<string> }, parent: Node | undefined) {
parent && parentStack.pop()
if (node !== rootExp && node.scopeIds) {
node.scopeIds.forEach((id: string) => {
if (analyzeScope && node !== rootExp && node.scopeIds) {
for (const id of node.scopeIds) {
knownIds[id]--
if (knownIds[id] === 0) {
delete knownIds[id]
}
})
}
}
}
})
Expand Down Expand Up @@ -156,6 +137,47 @@ export function isInDestructureAssignment(
return false
}

export function walkFunctionParams(
node: Function,
onIdent: (id: Identifier) => void
) {
for (const p of node.params) {
;(walk as any)(p, {
enter(child: Node, parent: Node) {
if (
child.type === 'Identifier' &&
// do not record as scope variable if is a destructured key
!isStaticPropertyKey(child, parent) &&
// do not record if this is a default value
// assignment of a destructured variable
!(
parent &&
parent.type === 'AssignmentPattern' &&
parent.right === child
)
) {
onIdent(child)
}
}
})
}
}

export function walkBlockDeclarations(
block: BlockStatement,
onIdent: (node: Identifier) => void
) {
for (const stmt of block.body) {
if (stmt.type === 'VariableDeclaration') {
for (const decl of stmt.declarations) {
for (const id of extractIdentifiers(decl.id)) {
onIdent(id)
}
}
}
}
}

function extractIdentifiers(
param: Node,
nodes: Identifier[] = []
Expand Down
6 changes: 3 additions & 3 deletions packages/compiler-core/src/transforms/transformExpression.ts
Expand Up @@ -283,10 +283,10 @@ export function processExpression(
}
},
undefined,
true, // invoke on ALL identifiers
true, // isLocal scope analysis
parentStack,
knownIds,
// invoke on ALL identifiers
true
knownIds
)

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

0 comments on commit db8dc75

Please sign in to comment.