feat(experimental): support ref transform for sfc normal <script>
This commit is contained in:
@@ -136,6 +136,9 @@ exports[`nested scopes 1`] = `
|
||||
b.value++ // outer b
|
||||
c++ // outer c
|
||||
|
||||
let bar = _ref(0)
|
||||
bar.value++ // outer bar
|
||||
|
||||
function foo({ a }) {
|
||||
a++ // inner a
|
||||
b.value++ // inner b
|
||||
@@ -143,10 +146,11 @@ exports[`nested scopes 1`] = `
|
||||
c.value++ // inner c
|
||||
let d = _ref(0)
|
||||
|
||||
const bar = (c) => {
|
||||
function bar(c) {
|
||||
c++ // nested c
|
||||
d.value++ // nested d
|
||||
}
|
||||
bar() // inner bar
|
||||
|
||||
if (true) {
|
||||
let a = _ref(0)
|
||||
|
||||
@@ -279,6 +279,9 @@ test('nested scopes', () => {
|
||||
b++ // outer b
|
||||
c++ // outer c
|
||||
|
||||
let bar = $ref(0)
|
||||
bar++ // outer bar
|
||||
|
||||
function foo({ a }) {
|
||||
a++ // inner a
|
||||
b++ // inner b
|
||||
@@ -286,10 +289,11 @@ test('nested scopes', () => {
|
||||
c++ // inner c
|
||||
let d = $ref(0)
|
||||
|
||||
const bar = (c) => {
|
||||
function bar(c) {
|
||||
c++ // nested c
|
||||
d++ // nested d
|
||||
}
|
||||
bar() // inner bar
|
||||
|
||||
if (true) {
|
||||
let a = $ref(0)
|
||||
@@ -299,7 +303,7 @@ test('nested scopes', () => {
|
||||
return $$({ a, b, c, d })
|
||||
}
|
||||
`)
|
||||
expect(rootVars).toStrictEqual(['a', 'b'])
|
||||
expect(rootVars).toStrictEqual(['a', 'b', 'bar'])
|
||||
|
||||
expect(code).toMatch('a.value++ // outer a')
|
||||
expect(code).toMatch('b.value++ // outer b')
|
||||
@@ -314,6 +318,10 @@ test('nested scopes', () => {
|
||||
|
||||
expect(code).toMatch(`a.value++ // if block a`) // if block
|
||||
|
||||
expect(code).toMatch(`bar.value++ // outer bar`)
|
||||
// inner bar shadowed by function declaration
|
||||
expect(code).toMatch(`bar() // inner bar`)
|
||||
|
||||
expect(code).toMatch(`return ({ a, b, c, d })`)
|
||||
assertCode(code)
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Node,
|
||||
Identifier,
|
||||
VariableDeclarator,
|
||||
BlockStatement,
|
||||
CallExpression,
|
||||
ObjectPattern,
|
||||
@@ -30,14 +29,6 @@ export function shouldTransform(src: string): boolean {
|
||||
return transformCheckRE.test(src)
|
||||
}
|
||||
|
||||
export interface ReactiveDeclarator {
|
||||
node: VariableDeclarator
|
||||
statement: VariableDeclaration
|
||||
ids: Identifier[]
|
||||
isPattern: boolean
|
||||
isRoot: boolean
|
||||
}
|
||||
|
||||
type Scope = Record<string, boolean>
|
||||
|
||||
export interface RefTransformOptions {
|
||||
@@ -105,18 +96,26 @@ export function transform(
|
||||
export function transformAST(
|
||||
ast: Node,
|
||||
s: MagicString,
|
||||
offset = 0
|
||||
offset = 0,
|
||||
knownRootVars?: string[]
|
||||
): {
|
||||
rootVars: string[]
|
||||
importedHelpers: string[]
|
||||
} {
|
||||
const importedHelpers = new Set<string>()
|
||||
const blockStack: BlockStatement[] = []
|
||||
let currentBlock: BlockStatement | null = null
|
||||
const rootScope: Scope = {}
|
||||
const blockToScopeMap = new WeakMap<BlockStatement, Scope>()
|
||||
const excludedIds = new Set<Identifier>()
|
||||
const parentStack: Node[] = []
|
||||
|
||||
if (knownRootVars) {
|
||||
for (const key of knownRootVars) {
|
||||
rootScope[key] = true
|
||||
}
|
||||
}
|
||||
|
||||
const error = (msg: string, node: Node) => {
|
||||
const e = new Error(msg)
|
||||
;(e as any).node = node
|
||||
@@ -130,7 +129,6 @@ export function transformAST(
|
||||
|
||||
const registerBinding = (id: Identifier, isRef = false) => {
|
||||
excludedIds.add(id)
|
||||
const currentBlock = blockStack[blockStack.length - 1]
|
||||
if (currentBlock) {
|
||||
const currentScope = blockToScopeMap.get(currentBlock)
|
||||
if (!currentScope) {
|
||||
@@ -145,13 +143,16 @@ export function transformAST(
|
||||
|
||||
const registerRefBinding = (id: Identifier) => registerBinding(id, true)
|
||||
|
||||
if (ast.type === 'Program') {
|
||||
walkBlockDeclarations(ast, registerBinding)
|
||||
}
|
||||
|
||||
// 1st pass: detect macro callsites and register ref bindings
|
||||
;(walk as any)(ast, {
|
||||
enter(node: Node, parent?: Node) {
|
||||
parent && parentStack.push(parent)
|
||||
|
||||
if (node.type === 'BlockStatement') {
|
||||
blockStack.push(node)
|
||||
blockStack.push((currentBlock = node))
|
||||
walkBlockDeclarations(node, registerBinding)
|
||||
if (parent && isFunctionType(parent)) {
|
||||
walkFunctionParams(parent, registerBinding)
|
||||
@@ -213,6 +214,7 @@ export function transformAST(
|
||||
parent && parentStack.pop()
|
||||
if (node.type === 'BlockStatement') {
|
||||
blockStack.pop()
|
||||
currentBlock = blockStack[blockStack.length - 1] || null
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -356,7 +358,7 @@ export function transformAST(
|
||||
}
|
||||
|
||||
return {
|
||||
rootVars: Object.keys(rootScope),
|
||||
rootVars: Object.keys(rootScope).filter(key => rootScope[key]),
|
||||
importedHelpers: [...importedHelpers]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user