]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: useOptions -> defineOptions
authorEvan You <yyx990803@gmail.com>
Fri, 13 Nov 2020 22:38:28 +0000 (17:38 -0500)
committerEvan You <yyx990803@gmail.com>
Fri, 13 Nov 2020 22:38:28 +0000 (17:38 -0500)
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/compileScript.spec.ts
packages/compiler-sfc/src/compileScript.ts
packages/runtime-core/src/apiDefineOptions.ts [moved from packages/runtime-core/src/helpers/useOptions.ts with 85% similarity]
packages/runtime-core/src/index.ts
test-dts/defineOptions.test-d.ts [moved from test-dts/useOptions.test-d.ts with 85% similarity]

index c48e1ff45b1d593bd15a933cda4d40e420816f6a..a6db4207344b334765bafa6786bfbbe1f7cf92be 100644 (file)
@@ -56,7 +56,25 @@ return { color }
 }"
 `;
 
-exports[`SFC compile <script setup> errors should allow useOptions() referencing imported binding 1`] = `
+exports[`SFC compile <script setup> defineOptions() 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 defineOptions() referencing imported binding 1`] = `
 "import { bar } from './bar'
           
 export default {
@@ -75,7 +93,7 @@ return { bar }
 }"
 `;
 
-exports[`SFC compile <script setup> errors should allow useOptions() referencing scope var 1`] = `
+exports[`SFC compile <script setup> errors should allow defineOptions() referencing scope var 1`] = `
 "export default {
   props: {
               foo: {
@@ -375,40 +393,7 @@ return { a, b, c, d, x }
 }"
 `;
 
-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`] = `
+exports[`SFC compile <script setup> with TypeScript defineOptions w/ runtime options 1`] = `
 "import { defineComponent } from 'vue'
 
 
@@ -425,7 +410,7 @@ return { props, emit }
 })"
 `;
 
-exports[`SFC compile <script setup> with TypeScript useOptions w/ type / extract emits (union) 1`] = `
+exports[`SFC compile <script setup> with TypeScript defineOptions w/ type / extract emits (union) 1`] = `
 "import { Slots, defineComponent } from 'vue'
 
       
@@ -446,7 +431,7 @@ return { emit }
 })"
 `;
 
-exports[`SFC compile <script setup> with TypeScript useOptions w/ type / extract emits 1`] = `
+exports[`SFC compile <script setup> with TypeScript defineOptions w/ type / extract emits 1`] = `
 "import { Slots, defineComponent } from 'vue'
 
       
@@ -467,7 +452,7 @@ return { emit }
 })"
 `;
 
-exports[`SFC compile <script setup> with TypeScript useOptions w/ type / extract props 1`] = `
+exports[`SFC compile <script setup> with TypeScript defineOptions w/ type / extract props 1`] = `
 "import { defineComponent } from 'vue'
 
       interface Test {}
@@ -503,6 +488,21 @@ 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 {  }
 }
 
index b172368764209106917139ba6e3a14613f07c854..958e81ec46a798cf452daf59877492d64fdf8ba3 100644 (file)
@@ -36,11 +36,11 @@ describe('SFC compile <script setup>', () => {
     expect(content).toMatch('return { a, b, c, d, x }')
   })
 
-  test('useOptions()', () => {
+  test('defineOptions()', () => {
     const { content, bindings } = compile(`
 <script setup>
-import { useOptions } from 'vue'
-const { props, emit } = useOptions({
+import { defineOptions } from 'vue'
+const { props, emit } = defineOptions({
   props: {
     foo: String
   },
@@ -60,8 +60,8 @@ const bar = 1
       emit: 'const'
     })
 
-    // should remove useOptions import and call
-    expect(content).not.toMatch('useOptions')
+    // should remove defineOptions import and call
+    expect(content).not.toMatch('defineOptions')
     // 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, useOptions } from 'vue'
+        import { ref, defineOptions } 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('useOptions w/ runtime options', () => {
+    test('defineOptions w/ runtime options', () => {
       const { content } = compile(`
 <script setup lang="ts">
-import { useOptions } from 'vue'
-const { props, emit } = useOptions({
+import { defineOptions } from 'vue'
+const { props, emit } = defineOptions({
   props: { foo: String },
   emits: ['a', 'b']
 })
@@ -200,15 +200,15 @@ const { props, emit } = useOptions({
   setup(__props, { props, emit }) {`)
     })
 
-    test('useOptions w/ type / extract props', () => {
+    test('defineOptions w/ type / extract props', () => {
       const { content, bindings } = compile(`
       <script setup lang="ts">
-      import { useOptions } from 'vue'
+      import { defineOptions } from 'vue'
       interface Test {}
 
       type Alias = number[]
 
-      useOptions<{
+      defineOptions<{
         props: {
           string: string
           number: number
@@ -288,11 +288,11 @@ const { props, emit } = useOptions({
       })
     })
 
-    test('useOptions w/ type / extract emits', () => {
+    test('defineOptions w/ type / extract emits', () => {
       const { content } = compile(`
       <script setup lang="ts">
-      import { useOptions } from 'vue'
-      const { emit } = useOptions<{
+      import { defineOptions } from 'vue'
+      const { emit } = defineOptions<{
         emit: (e: 'foo' | 'bar') => void
       }>()
       </script>
@@ -302,11 +302,11 @@ const { props, emit } = useOptions({
       expect(content).toMatch(`emits: ["foo", "bar"] as unknown as undefined`)
     })
 
-    test('useOptions w/ type / extract emits (union)', () => {
+    test('defineOptions w/ type / extract emits (union)', () => {
       const { content } = compile(`
       <script setup lang="ts">
-      import { useOptions } from 'vue'
-      const { emit } = useOptions<{
+      import { defineOptions } from 'vue'
+      const { emit } = defineOptions<{
         emit: ((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)
       }>()
       </script>
@@ -633,21 +633,21 @@ const { props, emit } = useOptions({
       ).toThrow(`ref: statements can only contain assignment expressions`)
     })
 
-    test('useOptions() w/ both type and non-type args', () => {
+    test('defineOptions() w/ both type and non-type args', () => {
       expect(() => {
         compile(`<script setup lang="ts">
-        import { useOptions } from 'vue'
-        useOptions<{}>({})
+        import { defineOptions } from 'vue'
+        defineOptions<{}>({})
         </script>`)
       }).toThrow(`cannot accept both type and non-type arguments`)
     })
 
-    test('useOptions() referencing local var', () => {
+    test('defineOptions() referencing local var', () => {
       expect(() =>
         compile(`<script setup>
-        import { useOptions } from 'vue'
+        import { defineOptions } from 'vue'
         const bar = 1
-        useOptions({
+        defineOptions({
           props: {
             foo: {
               default: () => bar
@@ -658,24 +658,24 @@ const { props, emit } = useOptions({
       ).toThrow(`cannot reference locally declared variables`)
     })
 
-    test('useOptions() referencing ref declarations', () => {
+    test('defineOptions() referencing ref declarations', () => {
       expect(() =>
         compile(`<script setup>
-        import { useOptions } from 'vue'
+        import { defineOptions } from 'vue'
         ref: bar = 1
-        useOptions({
+        defineOptions({
           props: { bar }
         })
       </script>`)
       ).toThrow(`cannot reference locally declared variables`)
     })
 
-    test('should allow useOptions() referencing scope var', () => {
+    test('should allow defineOptions() referencing scope var', () => {
       assertCode(
         compile(`<script setup>
-          import { useOptions } from 'vue'
+          import { defineOptions } from 'vue'
           const bar = 1
-          useOptions({
+          defineOptions({
             props: {
               foo: {
                 default: bar => bar + 1
@@ -686,12 +686,12 @@ const { props, emit } = useOptions({
       )
     })
 
-    test('should allow useOptions() referencing imported binding', () => {
+    test('should allow defineOptions() referencing imported binding', () => {
       assertCode(
         compile(`<script setup>
-          import { useOptions } from 'vue'
+          import { defineOptions } from 'vue'
           import { bar } from './bar'
-          useOptions({
+          defineOptions({
             props: {
               foo: {
                 default: () => bar
@@ -901,8 +901,8 @@ describe('SFC analyze <script> bindings', () => {
   it('works for script setup', () => {
     const { bindings } = compile(`
       <script setup>
-      import { useOptions } from 'vue'
-      useOptions({
+      import { defineOptions } from 'vue'
+      defineOptions({
         props: {
           foo: String,
         }
index a82db356d44ec14f4a0ec9db1e064bf7d8cf7175..5829e715524a47ec1add949da2c8e3968efcb75a 100644 (file)
@@ -27,7 +27,7 @@ import { RawSourceMap } from 'source-map'
 import { genCssVarsCode, injectCssVarsCalls } from './genCssVars'
 import { compileTemplate, SFCTemplateCompileOptions } from './compileTemplate'
 
-const USE_OPTIONS = 'useOptions'
+const DEFINE_OPTIONS = 'defineOptions'
 
 export interface SFCScriptCompileOptions {
   /**
@@ -147,7 +147,18 @@ export function compileScript(
   let optionsArg: ObjectExpression | undefined
   let optionsType: TSTypeLiteral | undefined
   let hasAwait = false
+  // context types to generate
+  let propsType = `{}`
+  let emitType = `(e: string, ...args: any[]) => void`
+  let slotsType = `Slots`
+  let attrsType = `Record<string, any>`
+  // props/emits declared via types
+  const typeDeclaredProps: Record<string, PropTypeData> = {}
+  const typeDeclaredEmits: Set<string> = new Set()
+  // record declared types for runtime props type generation
+  const declaredTypes: Record<string, string[]> = {}
 
+  // magic-string state
   const s = new MagicString(source)
   const startOffset = scriptSetup.loc.start.offset
   const endOffset = scriptSetup.loc.end.offset
@@ -182,14 +193,14 @@ export function compileScript(
     )
   }
 
-  function processUseOptions(node: Node): boolean {
+  function processDefineOptions(node: Node): boolean {
     if (
       node.type === 'CallExpression' &&
       node.callee.type === 'Identifier' &&
-      node.callee.name === USE_OPTIONS
+      node.callee.name === DEFINE_OPTIONS
     ) {
       if (hasOptionsCall) {
-        error(`duplicate ${USE_OPTIONS}() call`, node)
+        error(`duplicate ${DEFINE_OPTIONS}() call`, node)
       }
       hasOptionsCall = true
       const optsArg = node.arguments[0]
@@ -197,14 +208,17 @@ export function compileScript(
         if (optsArg.type === 'ObjectExpression') {
           optionsArg = optsArg
         } else {
-          error(`${USE_OPTIONS}() argument must be an object literal.`, optsArg)
+          error(
+            `${DEFINE_OPTIONS}() argument must be an object literal.`,
+            optsArg
+          )
         }
       }
       // context call has type parameters - infer runtime types from it
       if (node.typeParameters) {
         if (optionsArg) {
           error(
-            `${USE_OPTIONS}() cannot accept both type and non-type arguments ` +
+            `${DEFINE_OPTIONS}() cannot accept both type and non-type arguments ` +
               `at the same time. Use one or the other.`,
             node
           )
@@ -214,7 +228,7 @@ export function compileScript(
           optionsType = typeArg
         } else {
           error(
-            `type argument passed to ${USE_OPTIONS}() must be a literal type.`,
+            `type argument passed to ${DEFINE_OPTIONS}() must be a literal type.`,
             typeArg
           )
         }
@@ -427,18 +441,7 @@ export function compileScript(
     }
   }
 
-  let propsType = `{}`
-  let emitType = `(e: string, ...args: any[]) => void`
-  let slotsType = `Slots`
-  let attrsType = `Record<string, any>`
-
-  // props/emits declared via types
-  const typeDeclaredProps: Record<string, PropTypeData> = {}
-  const typeDeclaredEmits: Set<string> = new Set()
-  // record declared types for runtime props type generation
-  const declaredTypes: Record<string, string[]> = {}
-
-  // 3. parse <script setup> and  walk over top level statements
+  // 2. parse <script setup> and  walk over top level statements
   const scriptSetupAst = parse(
     scriptSetup.content,
     {
@@ -512,7 +515,7 @@ export function compileScript(
           specifier.imported.name
         const source = node.source.value
         const existing = userImports[local]
-        if (source === 'vue' && imported === USE_OPTIONS) {
+        if (source === 'vue' && imported === DEFINE_OPTIONS) {
           removed++
           s.remove(
             prev ? prev.end! + startOffset : specifier.start! + startOffset,
@@ -544,14 +547,14 @@ export function compileScript(
 
     if (
       node.type === 'ExpressionStatement' &&
-      processUseOptions(node.expression)
+      processDefineOptions(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 && processUseOptions(decl.init)) {
+        if (decl.init && processDefineOptions(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)
@@ -618,7 +621,7 @@ export function compileScript(
     }
   }
 
-  // 4. Do a full walk to rewrite identifiers referencing let exports with ref
+  // 3. Do a full walk to rewrite identifiers referencing let exports with ref
   // value access
   if (enableRefSugar && Object.keys(refBindings).length) {
     for (const node of scriptSetupAst) {
@@ -644,7 +647,7 @@ export function compileScript(
     }
   }
 
-  // 5. extract runtime props/emits code from setup context type
+  // 4. extract runtime props/emits code from setup context type
   if (optionsType) {
     for (const m of optionsType.members) {
       if (m.type === 'TSPropertySignature' && m.key.type === 'Identifier') {
@@ -690,7 +693,7 @@ export function compileScript(
     walkIdentifiers(optionsArg, id => {
       if (setupBindings[id.name]) {
         error(
-          `\`${USE_OPTIONS}()\` in <script setup> cannot reference locally ` +
+          `\`${DEFINE_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 ` +
@@ -739,7 +742,7 @@ export function compileScript(
     allBindings[key] = true
   }
 
-  // 9. inject `useCssVars` calls
+  // 8. inject `useCssVars` calls
   if (hasCssVars) {
     helperImports.add(`useCssVars`)
     for (const style of styles) {
@@ -753,7 +756,7 @@ export function compileScript(
     }
   }
 
-  // 10. analyze binding metadata
+  // 9. analyze binding metadata
   if (scriptAst) {
     Object.assign(bindingMetadata, analyzeScriptBindings(scriptAst))
   }
@@ -774,7 +777,7 @@ export function compileScript(
     bindingMetadata[key] = setupBindings[key]
   }
 
-  // 11. generate return statement
+  // 10. generate return statement
   let returned
   if (options.inlineTemplate) {
     if (sfc.template) {
@@ -812,7 +815,7 @@ export function compileScript(
   }
   s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)
 
-  // 12. finalize default export
+  // 11. finalize default export
   let runtimeOptions = ``
   if (optionsArg) {
     runtimeOptions = `\n  ${scriptSetup.content
@@ -822,7 +825,6 @@ export function compileScript(
     runtimeOptions =
       genRuntimeProps(typeDeclaredProps) + genRuntimeEmits(typeDeclaredEmits)
   }
-
   if (isTS) {
     // for TS, make sure the exported type is still valid type with
     // correct props information
@@ -861,7 +863,7 @@ export function compileScript(
     }
   }
 
-  // 13. finalize Vue helper imports
+  // 12. finalize Vue helper imports
   // TODO account for cases where user imports a helper with the same name
   // from a non-vue source
   const helpers = [...helperImports].filter(i => !userImports[i])
@@ -897,7 +899,7 @@ function walkDeclaration(
         init &&
         init.type === 'CallExpression' &&
         init.callee.type === 'Identifier' &&
-        init.callee.name === USE_OPTIONS
+        init.callee.name === DEFINE_OPTIONS
       )
       if (id.type === 'Identifier') {
         bindings[id.name] =
similarity index 85%
rename from packages/runtime-core/src/helpers/useOptions.ts
rename to packages/runtime-core/src/apiDefineOptions.ts
index 055f2807845d4a7cf69b0c257909d55e64accf8a..624b11676fc77fa702ceef2d144d9c89df6aa5f5 100644 (file)
@@ -1,11 +1,8 @@
-import { EmitFn, EmitsOptions } from '../componentEmits'
-import {
-  ComponentObjectPropsOptions,
-  ExtractPropTypes
-} from '../componentProps'
-import { Slots } from '../componentSlots'
-import { Directive } from '../directives'
-import { warn } from '../warning'
+import { EmitFn, EmitsOptions } from './componentEmits'
+import { ComponentObjectPropsOptions, ExtractPropTypes } from './componentProps'
+import { Slots } from './componentSlots'
+import { Directive } from './directives'
+import { warn } from './warning'
 
 interface DefaultContext {
   props: {}
@@ -45,7 +42,7 @@ interface Options<E extends EmitsOptions, EE extends string> {
  * called at runtime.
  */
 // overload 1: no props
-export function useOptions<
+export function defineOptions<
   T extends Partial<DefaultContext> = {},
   E extends EmitsOptions = EmitsOptions,
   EE extends string = string
@@ -56,7 +53,7 @@ export function useOptions<
 ): InferContext<T, {}, E>
 
 // overload 2: object props
-export function useOptions<
+export function defineOptions<
   T extends Partial<DefaultContext> = {},
   E extends EmitsOptions = EmitsOptions,
   EE extends string = string,
@@ -69,7 +66,7 @@ export function useOptions<
 ): InferContext<T, P, E>
 
 // overload 3: object props
-export function useOptions<
+export function defineOptions<
   T extends Partial<DefaultContext> = {},
   E extends EmitsOptions = EmitsOptions,
   EE extends string = string,
@@ -82,7 +79,7 @@ export function useOptions<
 ): InferContext<T, P, E>
 
 // implementation
-export function useOptions() {
+export function defineOptions() {
   if (__DEV__) {
     warn(
       `defineContext() is a compiler-hint helper that is only usable inside ` +
index 22bf9f2ee8f23148d78aaddb80eada873343412d..828850279ecf598063f1ba200fba486f3b076571 100644 (file)
@@ -43,7 +43,7 @@ export { provide, inject } from './apiInject'
 export { nextTick } from './scheduler'
 export { defineComponent } from './apiDefineComponent'
 export { defineAsyncComponent } from './apiAsyncComponent'
-export { useOptions } from './helpers/useOptions'
+export { defineOptions } from './apiDefineOptions'
 
 // Advanced API ----------------------------------------------------------------
 
similarity index 85%
rename from test-dts/useOptions.test-d.ts
rename to test-dts/defineOptions.test-d.ts
index 8330c5325f2402073c867c1ee497646edbee5358..d1125db35dfe8416ccbbad88f6abe31dc58187d6 100644 (file)
@@ -1,7 +1,7 @@
-import { expectType, useOptions, Slots, describe } from './index'
+import { expectType, defineOptions, Slots, describe } from './index'
 
 describe('no args', () => {
-  const { props, attrs, emit, slots } = useOptions()
+  const { props, attrs, emit, slots } = defineOptions()
   expectType<{}>(props)
   expectType<Record<string, unknown>>(attrs)
   expectType<(...args: any[]) => void>(emit)
@@ -15,7 +15,7 @@ describe('no args', () => {
 })
 
 describe('with type arg', () => {
-  const { props, attrs, emit, slots } = useOptions<{
+  const { props, attrs, emit, slots } = defineOptions<{
     props: {
       foo: string
     }
@@ -40,7 +40,7 @@ describe('with type arg', () => {
 
 // with runtime arg
 describe('with runtime arg (array syntax)', () => {
-  const { props, emit } = useOptions({
+  const { props, emit } = defineOptions({
     props: ['foo', 'bar'],
     emits: ['foo', 'bar']
   })
@@ -59,7 +59,7 @@ describe('with runtime arg (array syntax)', () => {
 })
 
 describe('with runtime arg (object syntax)', () => {
-  const { props, emit } = useOptions({
+  const { props, emit } = defineOptions({
     props: {
       foo: String,
       bar: {