wip: defineContext -> useOptions
This commit is contained in:
		
							parent
							
								
									292a657861
								
							
						
					
					
						commit
						001f8ce993
					
				| @ -56,25 +56,7 @@ return { color } | ||||
| }" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> defineContext() 1`] = ` | ||||
| "export default { | ||||
|   props: { | ||||
|     foo: String | ||||
|   }, | ||||
|   emit: ['a', 'b'], | ||||
|   setup(__props, { props, emit }) { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| const bar = 1 | ||||
| 
 | ||||
| return { props, emit, bar } | ||||
| } | ||||
| 
 | ||||
| }" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> errors should allow defineContext() referencing imported binding 1`] = ` | ||||
| exports[`SFC compile <script setup> errors should allow useOptions() referencing imported binding 1`] = ` | ||||
| "import { bar } from './bar' | ||||
|            | ||||
| export default { | ||||
| @ -93,7 +75,7 @@ return { bar } | ||||
| }" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> errors should allow defineContext() referencing scope var 1`] = ` | ||||
| exports[`SFC compile <script setup> errors should allow useOptions() referencing scope var 1`] = ` | ||||
| "export default { | ||||
|   props: { | ||||
|               foo: { | ||||
| @ -393,7 +375,40 @@ return { a, b, c, d, x } | ||||
| }" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript defineContext w/ runtime options 1`] = ` | ||||
| exports[`SFC compile <script setup> useOptions() 1`] = ` | ||||
| "export default { | ||||
|   props: { | ||||
|     foo: String | ||||
|   }, | ||||
|   emit: ['a', 'b'], | ||||
|   setup(__props, { props, emit }) { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| const bar = 1 | ||||
| 
 | ||||
| return { props, emit, bar } | ||||
| } | ||||
| 
 | ||||
| }" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript hoist type declarations 1`] = ` | ||||
| "import { defineComponent } from 'vue' | ||||
| export interface Foo {} | ||||
|         type Bar = {} | ||||
|        | ||||
| export default defineComponent({ | ||||
|   setup() { | ||||
| 
 | ||||
|          | ||||
| return {  } | ||||
| } | ||||
| 
 | ||||
| })" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript useOptions w/ runtime options 1`] = ` | ||||
| "import { defineComponent } from 'vue' | ||||
| 
 | ||||
| 
 | ||||
| @ -410,7 +425,7 @@ return { props, emit } | ||||
| })" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript defineContext w/ type / extract emits (union) 1`] = ` | ||||
| exports[`SFC compile <script setup> with TypeScript useOptions w/ type / extract emits (union) 1`] = ` | ||||
| "import { Slots, defineComponent } from 'vue' | ||||
| 
 | ||||
|        | ||||
| @ -431,7 +446,7 @@ return { emit } | ||||
| })" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript defineContext w/ type / extract emits 1`] = ` | ||||
| exports[`SFC compile <script setup> with TypeScript useOptions w/ type / extract emits 1`] = ` | ||||
| "import { Slots, defineComponent } from 'vue' | ||||
| 
 | ||||
|        | ||||
| @ -452,7 +467,7 @@ return { emit } | ||||
| })" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript defineContext w/ type / extract props 1`] = ` | ||||
| exports[`SFC compile <script setup> with TypeScript useOptions w/ type / extract props 1`] = ` | ||||
| "import { defineComponent } from 'vue' | ||||
| 
 | ||||
|       interface Test {} | ||||
| @ -488,21 +503,6 @@ export default defineComponent({ | ||||
| 
 | ||||
|        | ||||
|        | ||||
| return {  } | ||||
| } | ||||
| 
 | ||||
| })" | ||||
| `; | ||||
| 
 | ||||
| exports[`SFC compile <script setup> with TypeScript hoist type declarations 1`] = ` | ||||
| "import { defineComponent } from 'vue' | ||||
| export interface Foo {} | ||||
|         type Bar = {} | ||||
|        | ||||
| export default defineComponent({ | ||||
|   setup() { | ||||
| 
 | ||||
|          | ||||
| return {  } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -36,11 +36,11 @@ describe('SFC compile <script setup>', () => { | ||||
|     expect(content).toMatch('return { a, b, c, d, x }') | ||||
|   }) | ||||
| 
 | ||||
|   test('defineContext()', () => { | ||||
|   test('useOptions()', () => { | ||||
|     const { content, bindings } = compile(` | ||||
| <script setup> | ||||
| import { defineContext } from 'vue' | ||||
| const { props, emit } = defineContext({ | ||||
| import { useOptions } from 'vue' | ||||
| const { props, emit } = useOptions({ | ||||
|   props: { | ||||
|     foo: String | ||||
|   }, | ||||
| @ -60,8 +60,8 @@ const bar = 1 | ||||
|       emit: 'const' | ||||
|     }) | ||||
| 
 | ||||
|     // should remove defineContext import and call
 | ||||
|     expect(content).not.toMatch('defineContext') | ||||
|     // should remove useOptions import and call
 | ||||
|     expect(content).not.toMatch('useOptions') | ||||
|     // should generate correct setup signature
 | ||||
|     expect(content).toMatch(`setup(__props, { props, emit }) {`) | ||||
|     // should include context options in default export
 | ||||
| @ -143,7 +143,7 @@ const bar = 1 | ||||
|       const { content } = compile( | ||||
|         ` | ||||
|         <script setup> | ||||
|         import { ref, defineContext } from 'vue' | ||||
|         import { ref, useOptions } from 'vue' | ||||
|         import Foo from './Foo.vue' | ||||
|         import other from './util' | ||||
|         const count = ref(0) | ||||
| @ -183,11 +183,11 @@ const bar = 1 | ||||
|       assertCode(content) | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext w/ runtime options', () => { | ||||
|     test('useOptions w/ runtime options', () => { | ||||
|       const { content } = compile(` | ||||
| <script setup lang="ts"> | ||||
| import { defineContext } from 'vue' | ||||
| const { props, emit } = defineContext({ | ||||
| import { useOptions } from 'vue' | ||||
| const { props, emit } = useOptions({ | ||||
|   props: { foo: String }, | ||||
|   emits: ['a', 'b'] | ||||
| }) | ||||
| @ -200,15 +200,15 @@ const { props, emit } = defineContext({ | ||||
|   setup(__props, { props, emit }) {`)
 | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext w/ type / extract props', () => { | ||||
|     test('useOptions w/ type / extract props', () => { | ||||
|       const { content, bindings } = compile(` | ||||
|       <script setup lang="ts"> | ||||
|       import { defineContext } from 'vue' | ||||
|       import { useOptions } from 'vue' | ||||
|       interface Test {} | ||||
| 
 | ||||
|       type Alias = number[] | ||||
| 
 | ||||
|       defineContext<{ | ||||
|       useOptions<{ | ||||
|         props: { | ||||
|           string: string | ||||
|           number: number | ||||
| @ -288,11 +288,11 @@ const { props, emit } = defineContext({ | ||||
|       }) | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext w/ type / extract emits', () => { | ||||
|     test('useOptions w/ type / extract emits', () => { | ||||
|       const { content } = compile(` | ||||
|       <script setup lang="ts"> | ||||
|       import { defineContext } from 'vue' | ||||
|       const { emit } = defineContext<{ | ||||
|       import { useOptions } from 'vue' | ||||
|       const { emit } = useOptions<{ | ||||
|         emit: (e: 'foo' | 'bar') => void | ||||
|       }>() | ||||
|       </script> | ||||
| @ -302,11 +302,11 @@ const { props, emit } = defineContext({ | ||||
|       expect(content).toMatch(`emits: ["foo", "bar"] as unknown as undefined`) | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext w/ type / extract emits (union)', () => { | ||||
|     test('useOptions w/ type / extract emits (union)', () => { | ||||
|       const { content } = compile(` | ||||
|       <script setup lang="ts"> | ||||
|       import { defineContext } from 'vue' | ||||
|       const { emit } = defineContext<{ | ||||
|       import { useOptions } from 'vue' | ||||
|       const { emit } = useOptions<{ | ||||
|         emit: ((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void) | ||||
|       }>() | ||||
|       </script> | ||||
| @ -633,21 +633,21 @@ const { props, emit } = defineContext({ | ||||
|       ).toThrow(`ref: statements can only contain assignment expressions`) | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext() w/ both type and non-type args', () => { | ||||
|     test('useOptions() w/ both type and non-type args', () => { | ||||
|       expect(() => { | ||||
|         compile(`<script setup lang="ts">
 | ||||
|         import { defineContext } from 'vue' | ||||
|         defineContext<{}>({}) | ||||
|         import { useOptions } from 'vue' | ||||
|         useOptions<{}>({}) | ||||
|         </script>`)
 | ||||
|       }).toThrow(`cannot accept both type and non-type arguments`) | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext() referencing local var', () => { | ||||
|     test('useOptions() referencing local var', () => { | ||||
|       expect(() => | ||||
|         compile(`<script setup>
 | ||||
|         import { defineContext } from 'vue' | ||||
|         import { useOptions } from 'vue' | ||||
|         const bar = 1 | ||||
|         defineContext({ | ||||
|         useOptions({ | ||||
|           props: { | ||||
|             foo: { | ||||
|               default: () => bar | ||||
| @ -658,24 +658,24 @@ const { props, emit } = defineContext({ | ||||
|       ).toThrow(`cannot reference locally declared variables`) | ||||
|     }) | ||||
| 
 | ||||
|     test('defineContext() referencing ref declarations', () => { | ||||
|     test('useOptions() referencing ref declarations', () => { | ||||
|       expect(() => | ||||
|         compile(`<script setup>
 | ||||
|         import { defineContext } from 'vue' | ||||
|         import { useOptions } from 'vue' | ||||
|         ref: bar = 1 | ||||
|         defineContext({ | ||||
|         useOptions({ | ||||
|           props: { bar } | ||||
|         }) | ||||
|       </script>`)
 | ||||
|       ).toThrow(`cannot reference locally declared variables`) | ||||
|     }) | ||||
| 
 | ||||
|     test('should allow defineContext() referencing scope var', () => { | ||||
|     test('should allow useOptions() referencing scope var', () => { | ||||
|       assertCode( | ||||
|         compile(`<script setup>
 | ||||
|           import { defineContext } from 'vue' | ||||
|           import { useOptions } from 'vue' | ||||
|           const bar = 1 | ||||
|           defineContext({ | ||||
|           useOptions({ | ||||
|             props: { | ||||
|               foo: { | ||||
|                 default: bar => bar + 1 | ||||
| @ -686,12 +686,12 @@ const { props, emit } = defineContext({ | ||||
|       ) | ||||
|     }) | ||||
| 
 | ||||
|     test('should allow defineContext() referencing imported binding', () => { | ||||
|     test('should allow useOptions() referencing imported binding', () => { | ||||
|       assertCode( | ||||
|         compile(`<script setup>
 | ||||
|           import { defineContext } from 'vue' | ||||
|           import { useOptions } from 'vue' | ||||
|           import { bar } from './bar' | ||||
|           defineContext({ | ||||
|           useOptions({ | ||||
|             props: { | ||||
|               foo: { | ||||
|                 default: () => bar | ||||
| @ -901,8 +901,8 @@ describe('SFC analyze <script> bindings', () => { | ||||
|   it('works for script setup', () => { | ||||
|     const { bindings } = compile(` | ||||
|       <script setup> | ||||
|       import { defineContext } from 'vue' | ||||
|       defineContext({ | ||||
|       import { useOptions } from 'vue' | ||||
|       useOptions({ | ||||
|         props: { | ||||
|           foo: String, | ||||
|         } | ||||
|  | ||||
| @ -28,7 +28,7 @@ import { genCssVarsCode, injectCssVarsCalls } from './genCssVars' | ||||
| import { compileTemplate, SFCTemplateCompileOptions } from './compileTemplate' | ||||
| import { BindingTypes } from 'packages/compiler-core/src/options' | ||||
| 
 | ||||
| const CTX_FN_NAME = 'defineContext' | ||||
| const USE_OPTIONS = 'useOptions' | ||||
| 
 | ||||
| export interface SFCScriptCompileOptions { | ||||
|   /** | ||||
| @ -143,10 +143,10 @@ export function compileScript( | ||||
|   const refIdentifiers: Set<Identifier> = new Set() | ||||
|   const enableRefSugar = options.refSugar !== false | ||||
|   let defaultExport: Node | undefined | ||||
|   let hasContextCall = false | ||||
|   let setupContextExp: string | undefined | ||||
|   let setupContextArg: ObjectExpression | undefined | ||||
|   let setupContextType: TSTypeLiteral | undefined | ||||
|   let hasOptionsCall = false | ||||
|   let optionsExp: string | undefined | ||||
|   let optionsArg: ObjectExpression | undefined | ||||
|   let optionsType: TSTypeLiteral | undefined | ||||
|   let hasAwait = false | ||||
| 
 | ||||
|   const s = new MagicString(source) | ||||
| @ -183,39 +183,39 @@ export function compileScript( | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   function processContextCall(node: Node): boolean { | ||||
|   function processUseOptions(node: Node): boolean { | ||||
|     if ( | ||||
|       node.type === 'CallExpression' && | ||||
|       node.callee.type === 'Identifier' && | ||||
|       node.callee.name === CTX_FN_NAME | ||||
|       node.callee.name === USE_OPTIONS | ||||
|     ) { | ||||
|       if (hasContextCall) { | ||||
|         error('duplicate defineContext() call', node) | ||||
|       if (hasOptionsCall) { | ||||
|         error(`duplicate ${USE_OPTIONS}() call`, node) | ||||
|       } | ||||
|       hasContextCall = true | ||||
|       hasOptionsCall = true | ||||
|       const optsArg = node.arguments[0] | ||||
|       if (optsArg) { | ||||
|         if (optsArg.type === 'ObjectExpression') { | ||||
|           setupContextArg = optsArg | ||||
|           optionsArg = optsArg | ||||
|         } else { | ||||
|           error(`${CTX_FN_NAME}() argument must be an object literal.`, optsArg) | ||||
|           error(`${USE_OPTIONS}() argument must be an object literal.`, optsArg) | ||||
|         } | ||||
|       } | ||||
|       // context call has type parameters - infer runtime types from it
 | ||||
|       if (node.typeParameters) { | ||||
|         if (setupContextArg) { | ||||
|         if (optionsArg) { | ||||
|           error( | ||||
|             `${CTX_FN_NAME}() cannot accept both type and non-type arguments ` + | ||||
|             `${USE_OPTIONS}() cannot accept both type and non-type arguments ` + | ||||
|               `at the same time. Use one or the other.`, | ||||
|             node | ||||
|           ) | ||||
|         } | ||||
|         const typeArg = node.typeParameters.params[0] | ||||
|         if (typeArg.type === 'TSTypeLiteral') { | ||||
|           setupContextType = typeArg | ||||
|           optionsType = typeArg | ||||
|         } else { | ||||
|           error( | ||||
|             `type argument passed to ${CTX_FN_NAME}() must be a literal type.`, | ||||
|             `type argument passed to ${USE_OPTIONS}() must be a literal type.`, | ||||
|             typeArg | ||||
|           ) | ||||
|         } | ||||
| @ -513,7 +513,7 @@ export function compileScript( | ||||
|           specifier.imported.name | ||||
|         const source = node.source.value | ||||
|         const existing = userImports[local] | ||||
|         if (source === 'vue' && imported === CTX_FN_NAME) { | ||||
|         if (source === 'vue' && imported === USE_OPTIONS) { | ||||
|           removed++ | ||||
|           s.remove( | ||||
|             prev ? prev.end! + startOffset : specifier.start! + startOffset, | ||||
| @ -545,18 +545,15 @@ export function compileScript( | ||||
| 
 | ||||
|     if ( | ||||
|       node.type === 'ExpressionStatement' && | ||||
|       processContextCall(node.expression) | ||||
|       processUseOptions(node.expression) | ||||
|     ) { | ||||
|       s.remove(node.start! + startOffset, node.end! + startOffset) | ||||
|     } | ||||
| 
 | ||||
|     if (node.type === 'VariableDeclaration' && !node.declare) { | ||||
|       for (const decl of node.declarations) { | ||||
|         if (decl.init && processContextCall(decl.init)) { | ||||
|           setupContextExp = scriptSetup.content.slice( | ||||
|             decl.id.start!, | ||||
|             decl.id.end! | ||||
|           ) | ||||
|         if (decl.init && processUseOptions(decl.init)) { | ||||
|           optionsExp = scriptSetup.content.slice(decl.id.start!, decl.id.end!) | ||||
|           if (node.declarations.length === 1) { | ||||
|             s.remove(node.start! + startOffset, node.end! + startOffset) | ||||
|           } else { | ||||
| @ -649,8 +646,8 @@ export function compileScript( | ||||
|   } | ||||
| 
 | ||||
|   // 5. extract runtime props/emits code from setup context type
 | ||||
|   if (setupContextType) { | ||||
|     for (const m of setupContextType.members) { | ||||
|   if (optionsType) { | ||||
|     for (const m of optionsType.members) { | ||||
|       if (m.type === 'TSPropertySignature' && m.key.type === 'Identifier') { | ||||
|         const typeNode = m.typeAnnotation!.typeAnnotation | ||||
|         const typeString = scriptSetup.content.slice( | ||||
| @ -688,13 +685,13 @@ export function compileScript( | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 5. check useSetupContext args to make sure it doesn't reference setup scope
 | ||||
|   // 5. check useOptions args to make sure it doesn't reference setup scope
 | ||||
|   // variables
 | ||||
|   if (setupContextArg) { | ||||
|     walkIdentifiers(setupContextArg, id => { | ||||
|   if (optionsArg) { | ||||
|     walkIdentifiers(optionsArg, id => { | ||||
|       if (setupBindings[id.name]) { | ||||
|         error( | ||||
|           `\`${CTX_FN_NAME}()\` in <script setup> cannot reference locally ` + | ||||
|           `\`${USE_OPTIONS}()\` in <script setup> cannot reference locally ` + | ||||
|             `declared variables because it will be hoisted outside of the ` + | ||||
|             `setup() function. If your component options requires initialization ` + | ||||
|             `in the module scope, use a separate normal <script> to export ` + | ||||
| @ -725,8 +722,8 @@ export function compileScript( | ||||
|   } | ||||
| 
 | ||||
|   // 7. finalize setup argument signature.
 | ||||
|   let args = setupContextExp ? `__props, ${setupContextExp}` : `` | ||||
|   if (setupContextExp && setupContextType) { | ||||
|   let args = optionsExp ? `__props, ${optionsExp}` : `` | ||||
|   if (optionsExp && optionsType) { | ||||
|     if (slotsType === 'Slots') { | ||||
|       helperImports.add('Slots') | ||||
|     } | ||||
| @ -761,13 +758,13 @@ export function compileScript( | ||||
|   if (scriptAst) { | ||||
|     Object.assign(bindingMetadata, analyzeScriptBindings(scriptAst)) | ||||
|   } | ||||
|   if (setupContextType) { | ||||
|   if (optionsType) { | ||||
|     for (const key in typeDeclaredProps) { | ||||
|       bindingMetadata[key] = BindingTypes.PROPS | ||||
|     } | ||||
|   } | ||||
|   if (setupContextArg) { | ||||
|     Object.assign(bindingMetadata, analyzeBindingsFromOptions(setupContextArg)) | ||||
|   if (optionsArg) { | ||||
|     Object.assign(bindingMetadata, analyzeBindingsFromOptions(optionsArg)) | ||||
|   } | ||||
|   for (const [key, { source }] of Object.entries(userImports)) { | ||||
|     bindingMetadata[key] = source.endsWith('.vue') | ||||
| @ -818,11 +815,11 @@ export function compileScript( | ||||
| 
 | ||||
|   // 12. finalize default export
 | ||||
|   let runtimeOptions = `` | ||||
|   if (setupContextArg) { | ||||
|   if (optionsArg) { | ||||
|     runtimeOptions = `\n  ${scriptSetup.content | ||||
|       .slice(setupContextArg.start! + 1, setupContextArg.end! - 1) | ||||
|       .slice(optionsArg.start! + 1, optionsArg.end! - 1) | ||||
|       .trim()},` | ||||
|   } else if (setupContextType) { | ||||
|   } else if (optionsType) { | ||||
|     runtimeOptions = | ||||
|       genRuntimeProps(typeDeclaredProps) + genRuntimeEmits(typeDeclaredEmits) | ||||
|   } | ||||
| @ -896,18 +893,18 @@ function walkDeclaration( | ||||
|     const isConst = node.kind === 'const' | ||||
|     // export const foo = ...
 | ||||
|     for (const { id, init } of node.declarations) { | ||||
|       const isContextCall = !!( | ||||
|       const isUseOptionsCall = !!( | ||||
|         isConst && | ||||
|         init && | ||||
|         init.type === 'CallExpression' && | ||||
|         init.callee.type === 'Identifier' && | ||||
|         init.callee.name === CTX_FN_NAME | ||||
|         init.callee.name === USE_OPTIONS | ||||
|       ) | ||||
|       if (id.type === 'Identifier') { | ||||
|         bindings[id.name] = | ||||
|           // if a declaration is a const literal, we can mark it so that
 | ||||
|           // the generated render fn code doesn't need to unref() it
 | ||||
|           isContextCall || | ||||
|           isUseOptionsCall || | ||||
|           (isConst && | ||||
|           init!.type !== 'Identifier' && // const a = b
 | ||||
|           init!.type !== 'CallExpression' && // const a = ref()
 | ||||
| @ -915,9 +912,9 @@ function walkDeclaration( | ||||
|             ? BindingTypes.CONST | ||||
|             : BindingTypes.SETUP | ||||
|       } else if (id.type === 'ObjectPattern') { | ||||
|         walkObjectPattern(id, bindings, isConst, isContextCall) | ||||
|         walkObjectPattern(id, bindings, isConst, isUseOptionsCall) | ||||
|       } else if (id.type === 'ArrayPattern') { | ||||
|         walkArrayPattern(id, bindings, isConst, isContextCall) | ||||
|         walkArrayPattern(id, bindings, isConst, isUseOptionsCall) | ||||
|       } | ||||
|     } | ||||
|   } else if ( | ||||
| @ -934,7 +931,7 @@ function walkObjectPattern( | ||||
|   node: ObjectPattern, | ||||
|   bindings: Record<string, BindingTypes>, | ||||
|   isConst: boolean, | ||||
|   isContextCall = false | ||||
|   isUseOptionsCall = false | ||||
| ) { | ||||
|   for (const p of node.properties) { | ||||
|     if (p.type === 'ObjectProperty') { | ||||
| @ -942,11 +939,11 @@ function walkObjectPattern( | ||||
|       if (p.key.type === 'Identifier') { | ||||
|         if (p.key === p.value) { | ||||
|           // const { x } = ...
 | ||||
|           bindings[p.key.name] = isContextCall | ||||
|           bindings[p.key.name] = isUseOptionsCall | ||||
|             ? BindingTypes.CONST | ||||
|             : BindingTypes.SETUP | ||||
|         } else { | ||||
|           walkPattern(p.value, bindings, isConst, isContextCall) | ||||
|           walkPattern(p.value, bindings, isConst, isUseOptionsCall) | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
| @ -963,10 +960,10 @@ function walkArrayPattern( | ||||
|   node: ArrayPattern, | ||||
|   bindings: Record<string, BindingTypes>, | ||||
|   isConst: boolean, | ||||
|   isContextCall = false | ||||
|   isUseOptionsCall = false | ||||
| ) { | ||||
|   for (const e of node.elements) { | ||||
|     e && walkPattern(e, bindings, isConst, isContextCall) | ||||
|     e && walkPattern(e, bindings, isConst, isUseOptionsCall) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -974,10 +971,10 @@ function walkPattern( | ||||
|   node: Node, | ||||
|   bindings: Record<string, BindingTypes>, | ||||
|   isConst: boolean, | ||||
|   isContextCall = false | ||||
|   isUseOptionsCall = false | ||||
| ) { | ||||
|   if (node.type === 'Identifier') { | ||||
|     bindings[node.name] = isContextCall | ||||
|     bindings[node.name] = isUseOptionsCall | ||||
|       ? BindingTypes.CONST | ||||
|       : BindingTypes.SETUP | ||||
|   } else if (node.type === 'RestElement') { | ||||
| @ -991,7 +988,7 @@ function walkPattern( | ||||
|     walkArrayPattern(node, bindings, isConst) | ||||
|   } else if (node.type === 'AssignmentPattern') { | ||||
|     if (node.left.type === 'Identifier') { | ||||
|       bindings[node.left.name] = isContextCall | ||||
|       bindings[node.left.name] = isUseOptionsCall | ||||
|         ? BindingTypes.CONST | ||||
|         : BindingTypes.SETUP | ||||
|     } else { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { Slots } from './componentSlots' | ||||
| import { warn } from './warning' | ||||
| import { Slots } from '../componentSlots' | ||||
| import { warn } from '../warning' | ||||
| 
 | ||||
| interface DefaultContext { | ||||
|   props: Record<string, unknown> | ||||
| @ -8,7 +8,13 @@ interface DefaultContext { | ||||
|   slots: Slots | ||||
| } | ||||
| 
 | ||||
| export function defineContext<T extends Partial<DefaultContext> = {}>( | ||||
| /** | ||||
|  * Compile-time-only helper used for declaring options and retrieving props | ||||
|  * and the setup context inside <script setup>. | ||||
|  * This is stripped away in the compiled code and should never be actually | ||||
|  * called at runtime. | ||||
|  */ | ||||
| export function useOptions<T extends Partial<DefaultContext> = {}>( | ||||
|   opts?: any // TODO infer
 | ||||
| ): { [K in keyof DefaultContext]: T[K] extends {} ? T[K] : DefaultContext[K] } { | ||||
|   if (__DEV__) { | ||||
| @ -43,7 +43,7 @@ export { provide, inject } from './apiInject' | ||||
| export { nextTick } from './scheduler' | ||||
| export { defineComponent } from './apiDefineComponent' | ||||
| export { defineAsyncComponent } from './apiAsyncComponent' | ||||
| export { defineContext } from './apiDefineContext' | ||||
| export { useOptions } from './helpers/useOptions' | ||||
| 
 | ||||
| // Advanced API ----------------------------------------------------------------
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user