feat(experimental): support ref transform for sfc normal <script>
				
					
				
			This commit is contained in:
		
							parent
							
								
									f173cf0026
								
							
						
					
					
						commit
						06051c4bf2
					
				| @ -4,7 +4,8 @@ import { | |||||||
|   Node, |   Node, | ||||||
|   Function, |   Function, | ||||||
|   ObjectProperty, |   ObjectProperty, | ||||||
|   BlockStatement |   BlockStatement, | ||||||
|  |   Program | ||||||
| } from '@babel/types' | } from '@babel/types' | ||||||
| import { walk } from 'estree-walker' | import { walk } from 'estree-walker' | ||||||
| 
 | 
 | ||||||
| @ -149,16 +150,23 @@ export function walkFunctionParams( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function walkBlockDeclarations( | export function walkBlockDeclarations( | ||||||
|   block: BlockStatement, |   block: BlockStatement | Program, | ||||||
|   onIdent: (node: Identifier) => void |   onIdent: (node: Identifier) => void | ||||||
| ) { | ) { | ||||||
|   for (const stmt of block.body) { |   for (const stmt of block.body) { | ||||||
|     if (stmt.type === 'VariableDeclaration') { |     if (stmt.type === 'VariableDeclaration') { | ||||||
|  |       if (stmt.declare) continue | ||||||
|       for (const decl of stmt.declarations) { |       for (const decl of stmt.declarations) { | ||||||
|         for (const id of extractIdentifiers(decl.id)) { |         for (const id of extractIdentifiers(decl.id)) { | ||||||
|           onIdent(id) |           onIdent(id) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |     } else if ( | ||||||
|  |       stmt.type === 'FunctionDeclaration' || | ||||||
|  |       stmt.type === 'ClassDeclaration' | ||||||
|  |     ) { | ||||||
|  |       if (stmt.declare || !stmt.id) continue | ||||||
|  |       onIdent(stmt.id) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,43 +0,0 @@ | |||||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP |  | ||||||
| 
 |  | ||||||
| exports[`<script setup> ref sugar $ unwrapping 1`] = ` |  | ||||||
| "import { ref, shallowRef } from 'vue' |  | ||||||
|      |  | ||||||
| export default { |  | ||||||
|   setup(__props, { expose }) { |  | ||||||
|   expose() |  | ||||||
| 
 |  | ||||||
|     let foo = (ref()) |  | ||||||
|     let a = (ref(1)) |  | ||||||
|     let b = (shallowRef({ |  | ||||||
|       count: 0 |  | ||||||
|     })) |  | ||||||
|     let c = () => {} |  | ||||||
|     let d |  | ||||||
|      |  | ||||||
| return { foo, a, b, c, d, ref, shallowRef } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }" |  | ||||||
| `; |  | ||||||
| 
 |  | ||||||
| exports[`<script setup> ref sugar $ref & $shallowRef declarations 1`] = ` |  | ||||||
| "import { ref as _ref, shallowRef as _shallowRef } from 'vue' |  | ||||||
| 
 |  | ||||||
| export default { |  | ||||||
|   setup(__props, { expose }) { |  | ||||||
|   expose() |  | ||||||
| 
 |  | ||||||
|     let foo = _ref() |  | ||||||
|     let a = _ref(1) |  | ||||||
|     let b = _shallowRef({ |  | ||||||
|       count: 0 |  | ||||||
|     }) |  | ||||||
|     let c = () => {} |  | ||||||
|     let d |  | ||||||
|      |  | ||||||
| return { foo, a, b, c, d } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }" |  | ||||||
| `; |  | ||||||
| @ -0,0 +1,80 @@ | |||||||
|  | // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||||
|  | 
 | ||||||
|  | exports[`sfc ref transform $ unwrapping 1`] = ` | ||||||
|  | "import { ref, shallowRef } from 'vue' | ||||||
|  |      | ||||||
|  | export default { | ||||||
|  |   setup(__props, { expose }) { | ||||||
|  |   expose() | ||||||
|  | 
 | ||||||
|  |     let foo = (ref()) | ||||||
|  |     let a = (ref(1)) | ||||||
|  |     let b = (shallowRef({ | ||||||
|  |       count: 0 | ||||||
|  |     })) | ||||||
|  |     let c = () => {} | ||||||
|  |     let d | ||||||
|  |      | ||||||
|  | return { foo, a, b, c, d, ref, shallowRef } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | }" | ||||||
|  | `; | ||||||
|  | 
 | ||||||
|  | exports[`sfc ref transform $ref & $shallowRef declarations 1`] = ` | ||||||
|  | "import { ref as _ref, shallowRef as _shallowRef } from 'vue' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   setup(__props, { expose }) { | ||||||
|  |   expose() | ||||||
|  | 
 | ||||||
|  |     let foo = _ref() | ||||||
|  |     let a = _ref(1) | ||||||
|  |     let b = _shallowRef({ | ||||||
|  |       count: 0 | ||||||
|  |     }) | ||||||
|  |     let c = () => {} | ||||||
|  |     let d | ||||||
|  |      | ||||||
|  | return { foo, a, b, c, d } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | }" | ||||||
|  | `; | ||||||
|  | 
 | ||||||
|  | exports[`sfc ref transform usage in normal <script> 1`] = ` | ||||||
|  | "import { ref as _ref } from 'vue' | ||||||
|  | 
 | ||||||
|  |     export default { | ||||||
|  |       setup() { | ||||||
|  |         let count = _ref(0) | ||||||
|  |         const inc = () => count.value++ | ||||||
|  |         return ({ count }) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     " | ||||||
|  | `; | ||||||
|  | 
 | ||||||
|  | exports[`sfc ref transform usage with normal <script> + <script setup> 1`] = ` | ||||||
|  | "import { ref as _ref } from 'vue' | ||||||
|  | 
 | ||||||
|  |     let a = _ref(0) | ||||||
|  |     let c = _ref(0) | ||||||
|  |      | ||||||
|  | export default { | ||||||
|  |   setup(__props, { expose }) { | ||||||
|  |   expose() | ||||||
|  | 
 | ||||||
|  |     let b = _ref(0) | ||||||
|  |     let c = 0 | ||||||
|  |     function change() { | ||||||
|  |       a.value++ | ||||||
|  |       b.value++ | ||||||
|  |       c++ | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | return { a, c, b, change } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | }" | ||||||
|  | `; | ||||||
| @ -3,13 +3,13 @@ import { compileSFCScript as compile, assertCode } from './utils' | |||||||
| 
 | 
 | ||||||
| // this file only tests integration with SFC - main test case for the ref
 | // this file only tests integration with SFC - main test case for the ref
 | ||||||
| // transform can be found in <root>/packages/ref-transform/__tests__
 | // transform can be found in <root>/packages/ref-transform/__tests__
 | ||||||
| describe('<script setup> ref sugar', () => { | describe('sfc ref transform', () => { | ||||||
|   function compileWithRefSugar(src: string) { |   function compileWithRefTransform(src: string) { | ||||||
|     return compile(src, { refSugar: true }) |     return compile(src, { refSugar: true }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   test('$ unwrapping', () => { |   test('$ unwrapping', () => { | ||||||
|     const { content, bindings } = compileWithRefSugar(`<script setup>
 |     const { content, bindings } = compileWithRefTransform(`<script setup>
 | ||||||
|     import { ref, shallowRef } from 'vue' |     import { ref, shallowRef } from 'vue' | ||||||
|     let foo = $(ref()) |     let foo = $(ref()) | ||||||
|     let a = $(ref(1)) |     let a = $(ref(1)) | ||||||
| @ -46,7 +46,7 @@ describe('<script setup> ref sugar', () => { | |||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   test('$ref & $shallowRef declarations', () => { |   test('$ref & $shallowRef declarations', () => { | ||||||
|     const { content, bindings } = compileWithRefSugar(`<script setup>
 |     const { content, bindings } = compileWithRefTransform(`<script setup>
 | ||||||
|     let foo = $ref() |     let foo = $ref() | ||||||
|     let a = $ref(1) |     let a = $ref(1) | ||||||
|     let b = $shallowRef({ |     let b = $shallowRef({ | ||||||
| @ -81,6 +81,58 @@ describe('<script setup> ref sugar', () => { | |||||||
|     }) |     }) | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|  |   test('usage in normal <script>', () => { | ||||||
|  |     const { content } = compileWithRefTransform(`<script>
 | ||||||
|  |     export default { | ||||||
|  |       setup() { | ||||||
|  |         let count = $ref(0) | ||||||
|  |         const inc = () => count++ | ||||||
|  |         return $$({ count }) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     </script>`)
 | ||||||
|  |     expect(content).not.toMatch(`$ref(0)`) | ||||||
|  |     expect(content).toMatch(`import { ref as _ref } from 'vue'`) | ||||||
|  |     expect(content).toMatch(`let count = _ref(0)`) | ||||||
|  |     expect(content).toMatch(`count.value++`) | ||||||
|  |     expect(content).toMatch(`return ({ count })`) | ||||||
|  |     assertCode(content) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   test('usage with normal <script> + <script setup>', () => { | ||||||
|  |     const { content, bindings } = compileWithRefTransform(`<script>
 | ||||||
|  |     let a = $ref(0) | ||||||
|  |     let c = $ref(0) | ||||||
|  |     </script> | ||||||
|  |     <script setup> | ||||||
|  |     let b = $ref(0) | ||||||
|  |     let c = 0 | ||||||
|  |     function change() { | ||||||
|  |       a++ | ||||||
|  |       b++ | ||||||
|  |       c++ | ||||||
|  |     } | ||||||
|  |     </script>`)
 | ||||||
|  |     // should dedupe helper imports
 | ||||||
|  |     expect(content).toMatch(`import { ref as _ref } from 'vue'`) | ||||||
|  | 
 | ||||||
|  |     expect(content).toMatch(`let a = _ref(0)`) | ||||||
|  |     expect(content).toMatch(`let b = _ref(0)`) | ||||||
|  | 
 | ||||||
|  |     // root level ref binding declared in <script> should be inherited in <script setup>
 | ||||||
|  |     expect(content).toMatch(`a.value++`) | ||||||
|  |     expect(content).toMatch(`b.value++`) | ||||||
|  |     // c shadowed
 | ||||||
|  |     expect(content).toMatch(`c++`) | ||||||
|  |     assertCode(content) | ||||||
|  |     expect(bindings).toStrictEqual({ | ||||||
|  |       a: BindingTypes.SETUP_REF, | ||||||
|  |       b: BindingTypes.SETUP_REF, | ||||||
|  |       c: BindingTypes.SETUP_REF, | ||||||
|  |       change: BindingTypes.SETUP_CONST | ||||||
|  |     }) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|   describe('errors', () => { |   describe('errors', () => { | ||||||
|     test('defineProps/Emit() referencing ref declarations', () => { |     test('defineProps/Emit() referencing ref declarations', () => { | ||||||
|       expect(() => |       expect(() => | ||||||
| @ -165,12 +165,34 @@ export function compileScript( | |||||||
|       return script |       return script | ||||||
|     } |     } | ||||||
|     try { |     try { | ||||||
|       const scriptAst = _parse(script.content, { |       let content = script.content | ||||||
|  |       let map = script.map | ||||||
|  |       const scriptAst = _parse(content, { | ||||||
|         plugins, |         plugins, | ||||||
|         sourceType: 'module' |         sourceType: 'module' | ||||||
|       }).program.body |       }).program | ||||||
|       const bindings = analyzeScriptBindings(scriptAst) |       const bindings = analyzeScriptBindings(scriptAst.body) | ||||||
|       let content = script.content |       if (enableRefTransform && shouldTransformRef(content)) { | ||||||
|  |         const s = new MagicString(source) | ||||||
|  |         const startOffset = script.loc.start.offset | ||||||
|  |         const endOffset = script.loc.end.offset | ||||||
|  |         const { importedHelpers } = transformRefAST(scriptAst, s, startOffset) | ||||||
|  |         if (importedHelpers.length) { | ||||||
|  |           s.prepend( | ||||||
|  |             `import { ${importedHelpers | ||||||
|  |               .map(h => `${h} as _${h}`) | ||||||
|  |               .join(', ')} } from 'vue'\n` | ||||||
|  |           ) | ||||||
|  |         } | ||||||
|  |         s.remove(0, startOffset) | ||||||
|  |         s.remove(endOffset, source.length) | ||||||
|  |         content = s.toString() | ||||||
|  |         map = s.generateMap({ | ||||||
|  |           source: filename, | ||||||
|  |           hires: true, | ||||||
|  |           includeContent: true | ||||||
|  |         }) as unknown as RawSourceMap | ||||||
|  |       } | ||||||
|       if (cssVars.length) { |       if (cssVars.length) { | ||||||
|         content = rewriteDefault(content, `__default__`, plugins) |         content = rewriteDefault(content, `__default__`, plugins) | ||||||
|         content += genNormalScriptCssVarsCode( |         content += genNormalScriptCssVarsCode( | ||||||
| @ -184,8 +206,9 @@ export function compileScript( | |||||||
|       return { |       return { | ||||||
|         ...script, |         ...script, | ||||||
|         content, |         content, | ||||||
|  |         map, | ||||||
|         bindings, |         bindings, | ||||||
|         scriptAst |         scriptAst: scriptAst.body | ||||||
|       } |       } | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       // silently fallback if parse fails since user may be using custom
 |       // silently fallback if parse fails since user may be using custom
 | ||||||
| @ -629,6 +652,23 @@ export function compileScript( | |||||||
|         walkDeclaration(node, setupBindings, userImportAlias) |         walkDeclaration(node, setupBindings, userImportAlias) | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     // apply ref transform
 | ||||||
|  |     if (enableRefTransform && shouldTransformRef(script.content)) { | ||||||
|  |       warnExperimental( | ||||||
|  |         `ref sugar`, | ||||||
|  |         `https://github.com/vuejs/rfcs/discussions/369` | ||||||
|  |       ) | ||||||
|  |       const { rootVars, importedHelpers } = transformRefAST( | ||||||
|  |         scriptAst, | ||||||
|  |         s, | ||||||
|  |         scriptStartOffset! | ||||||
|  |       ) | ||||||
|  |       refBindings = rootVars | ||||||
|  |       for (const h of importedHelpers) { | ||||||
|  |         helperImports.add(h) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // 2. parse <script setup> and  walk over top level statements
 |   // 2. parse <script setup> and  walk over top level statements
 | ||||||
| @ -862,7 +902,7 @@ export function compileScript( | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // 3. Apply ref sugar transform
 |   // 3. Apply ref sugar transform
 | ||||||
|   if (enableRefTransform && shouldTransformRef(source)) { |   if (enableRefTransform && shouldTransformRef(scriptSetup.content)) { | ||||||
|     warnExperimental( |     warnExperimental( | ||||||
|       `ref sugar`, |       `ref sugar`, | ||||||
|       `https://github.com/vuejs/rfcs/discussions/369` |       `https://github.com/vuejs/rfcs/discussions/369` | ||||||
| @ -870,9 +910,10 @@ export function compileScript( | |||||||
|     const { rootVars, importedHelpers } = transformRefAST( |     const { rootVars, importedHelpers } = transformRefAST( | ||||||
|       scriptSetupAst, |       scriptSetupAst, | ||||||
|       s, |       s, | ||||||
|       startOffset |       startOffset, | ||||||
|  |       refBindings | ||||||
|     ) |     ) | ||||||
|     refBindings = rootVars |     refBindings = refBindings ? [...refBindings, ...rootVars] : rootVars | ||||||
|     for (const h of importedHelpers) { |     for (const h of importedHelpers) { | ||||||
|       helperImports.add(h) |       helperImports.add(h) | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -136,6 +136,9 @@ exports[`nested scopes 1`] = ` | |||||||
|     b.value++ // outer b |     b.value++ // outer b | ||||||
|     c++ // outer c |     c++ // outer c | ||||||
| 
 | 
 | ||||||
|  |     let bar = _ref(0) | ||||||
|  |     bar.value++ // outer bar | ||||||
|  | 
 | ||||||
|     function foo({ a }) { |     function foo({ a }) { | ||||||
|       a++ // inner a |       a++ // inner a | ||||||
|       b.value++ // inner b |       b.value++ // inner b | ||||||
| @ -143,10 +146,11 @@ exports[`nested scopes 1`] = ` | |||||||
|       c.value++ // inner c |       c.value++ // inner c | ||||||
|       let d = _ref(0) |       let d = _ref(0) | ||||||
| 
 | 
 | ||||||
|       const bar = (c) => { |       function bar(c) { | ||||||
|         c++ // nested c |         c++ // nested c | ||||||
|         d.value++ // nested d |         d.value++ // nested d | ||||||
|       } |       } | ||||||
|  |       bar() // inner bar | ||||||
| 
 | 
 | ||||||
|       if (true) { |       if (true) { | ||||||
|         let a = _ref(0) |         let a = _ref(0) | ||||||
|  | |||||||
| @ -279,6 +279,9 @@ test('nested scopes', () => { | |||||||
|     b++ // outer b
 |     b++ // outer b
 | ||||||
|     c++ // outer c
 |     c++ // outer c
 | ||||||
| 
 | 
 | ||||||
|  |     let bar = $ref(0) | ||||||
|  |     bar++ // outer bar
 | ||||||
|  | 
 | ||||||
|     function foo({ a }) { |     function foo({ a }) { | ||||||
|       a++ // inner a
 |       a++ // inner a
 | ||||||
|       b++ // inner b
 |       b++ // inner b
 | ||||||
| @ -286,10 +289,11 @@ test('nested scopes', () => { | |||||||
|       c++ // inner c
 |       c++ // inner c
 | ||||||
|       let d = $ref(0) |       let d = $ref(0) | ||||||
| 
 | 
 | ||||||
|       const bar = (c) => { |       function bar(c) { | ||||||
|         c++ // nested c
 |         c++ // nested c
 | ||||||
|         d++ // nested d
 |         d++ // nested d
 | ||||||
|       } |       } | ||||||
|  |       bar() // inner bar
 | ||||||
| 
 | 
 | ||||||
|       if (true) { |       if (true) { | ||||||
|         let a = $ref(0) |         let a = $ref(0) | ||||||
| @ -299,7 +303,7 @@ test('nested scopes', () => { | |||||||
|       return $$({ a, b, c, d }) |       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('a.value++ // outer a') | ||||||
|   expect(code).toMatch('b.value++ // outer b') |   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(`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 })`) |   expect(code).toMatch(`return ({ a, b, c, d })`) | ||||||
|   assertCode(code) |   assertCode(code) | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| import { | import { | ||||||
|   Node, |   Node, | ||||||
|   Identifier, |   Identifier, | ||||||
|   VariableDeclarator, |  | ||||||
|   BlockStatement, |   BlockStatement, | ||||||
|   CallExpression, |   CallExpression, | ||||||
|   ObjectPattern, |   ObjectPattern, | ||||||
| @ -30,14 +29,6 @@ export function shouldTransform(src: string): boolean { | |||||||
|   return transformCheckRE.test(src) |   return transformCheckRE.test(src) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface ReactiveDeclarator { |  | ||||||
|   node: VariableDeclarator |  | ||||||
|   statement: VariableDeclaration |  | ||||||
|   ids: Identifier[] |  | ||||||
|   isPattern: boolean |  | ||||||
|   isRoot: boolean |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Scope = Record<string, boolean> | type Scope = Record<string, boolean> | ||||||
| 
 | 
 | ||||||
| export interface RefTransformOptions { | export interface RefTransformOptions { | ||||||
| @ -105,18 +96,26 @@ export function transform( | |||||||
| export function transformAST( | export function transformAST( | ||||||
|   ast: Node, |   ast: Node, | ||||||
|   s: MagicString, |   s: MagicString, | ||||||
|   offset = 0 |   offset = 0, | ||||||
|  |   knownRootVars?: string[] | ||||||
| ): { | ): { | ||||||
|   rootVars: string[] |   rootVars: string[] | ||||||
|   importedHelpers: string[] |   importedHelpers: string[] | ||||||
| } { | } { | ||||||
|   const importedHelpers = new Set<string>() |   const importedHelpers = new Set<string>() | ||||||
|   const blockStack: BlockStatement[] = [] |   const blockStack: BlockStatement[] = [] | ||||||
|  |   let currentBlock: BlockStatement | null = null | ||||||
|   const rootScope: Scope = {} |   const rootScope: Scope = {} | ||||||
|   const blockToScopeMap = new WeakMap<BlockStatement, Scope>() |   const blockToScopeMap = new WeakMap<BlockStatement, Scope>() | ||||||
|   const excludedIds = new Set<Identifier>() |   const excludedIds = new Set<Identifier>() | ||||||
|   const parentStack: Node[] = [] |   const parentStack: Node[] = [] | ||||||
| 
 | 
 | ||||||
|  |   if (knownRootVars) { | ||||||
|  |     for (const key of knownRootVars) { | ||||||
|  |       rootScope[key] = true | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   const error = (msg: string, node: Node) => { |   const error = (msg: string, node: Node) => { | ||||||
|     const e = new Error(msg) |     const e = new Error(msg) | ||||||
|     ;(e as any).node = node |     ;(e as any).node = node | ||||||
| @ -130,7 +129,6 @@ export function transformAST( | |||||||
| 
 | 
 | ||||||
|   const registerBinding = (id: Identifier, isRef = false) => { |   const registerBinding = (id: Identifier, isRef = false) => { | ||||||
|     excludedIds.add(id) |     excludedIds.add(id) | ||||||
|     const currentBlock = blockStack[blockStack.length - 1] |  | ||||||
|     if (currentBlock) { |     if (currentBlock) { | ||||||
|       const currentScope = blockToScopeMap.get(currentBlock) |       const currentScope = blockToScopeMap.get(currentBlock) | ||||||
|       if (!currentScope) { |       if (!currentScope) { | ||||||
| @ -145,13 +143,16 @@ export function transformAST( | |||||||
| 
 | 
 | ||||||
|   const registerRefBinding = (id: Identifier) => registerBinding(id, true) |   const registerRefBinding = (id: Identifier) => registerBinding(id, true) | ||||||
| 
 | 
 | ||||||
|  |   if (ast.type === 'Program') { | ||||||
|  |     walkBlockDeclarations(ast, registerBinding) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // 1st pass: detect macro callsites and register ref bindings
 |   // 1st pass: detect macro callsites and register ref bindings
 | ||||||
|   ;(walk as any)(ast, { |   ;(walk as any)(ast, { | ||||||
|     enter(node: Node, parent?: Node) { |     enter(node: Node, parent?: Node) { | ||||||
|       parent && parentStack.push(parent) |       parent && parentStack.push(parent) | ||||||
| 
 |  | ||||||
|       if (node.type === 'BlockStatement') { |       if (node.type === 'BlockStatement') { | ||||||
|         blockStack.push(node) |         blockStack.push((currentBlock = node)) | ||||||
|         walkBlockDeclarations(node, registerBinding) |         walkBlockDeclarations(node, registerBinding) | ||||||
|         if (parent && isFunctionType(parent)) { |         if (parent && isFunctionType(parent)) { | ||||||
|           walkFunctionParams(parent, registerBinding) |           walkFunctionParams(parent, registerBinding) | ||||||
| @ -213,6 +214,7 @@ export function transformAST( | |||||||
|       parent && parentStack.pop() |       parent && parentStack.pop() | ||||||
|       if (node.type === 'BlockStatement') { |       if (node.type === 'BlockStatement') { | ||||||
|         blockStack.pop() |         blockStack.pop() | ||||||
|  |         currentBlock = blockStack[blockStack.length - 1] || null | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }) |   }) | ||||||
| @ -356,7 +358,7 @@ export function transformAST( | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     rootVars: Object.keys(rootScope), |     rootVars: Object.keys(rootScope).filter(key => rootScope[key]), | ||||||
|     importedHelpers: [...importedHelpers] |     importedHelpers: [...importedHelpers] | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user