BREAKING CHANGE: Reactivity Transform was marked deprecated in 3.3 and is now removed in 3.4. This change does not require a major due to the feature being experimental. Users who wish to continue using the feature can do so via the external plugin at https://vue-macros.dev/features/reactivity-transform.html
},
// Packages targeting Node
{
- files: [
- 'packages/{compiler-sfc,compiler-ssr,server-renderer,reactivity-transform}/**'
- ],
+ files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
rules: {
'no-restricted-globals': ['error', ...DOMGlobals],
'no-restricted-syntax': 'off'
"serve": "serve",
"open": "open http://localhost:3000/packages/template-explorer/local.html",
"build-sfc-playground": "run-s build-all-cjs build-runtime-esm build-ssr-esm build-sfc-playground-self",
- "build-all-cjs": "node scripts/build.js vue runtime compiler reactivity reactivity-transform shared -af cjs",
+ "build-all-cjs": "node scripts/build.js vue runtime compiler reactivity shared -af cjs",
"build-runtime-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js vue -f esm-browser-runtime",
"build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer -f esm-browser",
"build-sfc-playground-self": "cd packages/sfc-playground && npm run build",
`;
exports[`SFC compile <script setup> > async/await detection > ref 1`] = `
-"import { withAsyncContext as _withAsyncContext, ref as _ref } from 'vue'
+"import { withAsyncContext as _withAsyncContext } from 'vue'
export default {
async setup(__props, { expose: __expose }) {
__expose();
let __temp, __restore
-let a = _ref(1 + ((
+let a = ref(1 + ((
([__temp,__restore] = _withAsyncContext(() => foo)),
__temp = await __temp,
__restore(),
__temp
)))
-return { a }
+return { get a() { return a }, set a(v) { a = v } }
}
}"
`;
exports[`SFC compile <script setup> > imports > dedupe between user & helper 1`] = `
-"import { ref as _ref } from 'vue'
-import { ref } from 'vue'
+"import { useCssVars as _useCssVars, unref as _unref } from 'vue'
+import { useCssVars, ref } from 'vue'
export default {
setup(__props, { expose: __expose }) {
__expose();
- let foo = _ref(1)
+_useCssVars(_ctx => ({
+ \\"xxxxxxxx-msg\\": (msg.value)
+}))
+
+ const msg = ref()
-return { foo, ref }
+return { msg, useCssVars, ref }
}
}"
const { content } = compile(
`
<script setup>
- import { ref } from 'vue'
- let foo = $ref(1)
+ import { useCssVars, ref } from 'vue'
+ const msg = ref()
</script>
- `,
- { reactivityTransform: true }
+
+ <style>
+ .foo {
+ color: v-bind(msg)
+ }
+ </style>
+ `
)
assertCode(content)
- expect(content).toMatch(`import { ref } from 'vue'`)
+ expect(content).toMatch(
+ `import { useCssVars as _useCssVars, unref as _unref } from 'vue'`
+ )
+ expect(content).toMatch(`import { useCssVars, ref } from 'vue'`)
})
test('import dedupe between <script> and <script setup>', () => {
describe('async/await detection', () => {
function assertAwaitDetection(code: string, shouldAsync = true) {
- const { content } = compile(`<script setup>${code}</script>`, {
- reactivityTransform: true
- })
+ const { content } = compile(`<script setup>${code}</script>`)
if (shouldAsync) {
expect(content).toMatch(`let __temp, __restore`)
}
})
test('ref', () => {
- assertAwaitDetection(`let a = $ref(1 + (await foo))`)
+ assertAwaitDetection(`let a = ref(1 + (await foo))`)
})
// #4448
+++ /dev/null
-// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-
-exports[`sfc ref transform > $ unwrapping 1`] = `
-"import { ref, shallowRef } from 'vue'
-
-export default {
- setup(__props, { expose: __expose }) {
- __expose();
-
- let foo = (ref())
- let a = (ref(1))
- let b = (shallowRef({
- count: 0
- }))
- let c = () => {}
- let d
-
-return { foo, a, b, get c() { return c }, set c(v) { c = v }, get d() { return d }, set d(v) { d = v }, 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 }) {
- __expose();
-
- let foo = _ref()
- let a = _ref(1)
- let b = _shallowRef({
- count: 0
- })
- let c = () => {}
- let d
-
-return { foo, a, b, get c() { return c }, set c(v) { c = v }, get d() { return d }, set d(v) { d = v } }
-}
-
-}"
-`;
-
-exports[`sfc ref transform > usage /w typescript 1`] = `
-"import { ref as _ref, defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
- setup(__props, { expose: __expose }) {
- __expose();
-
- let msg = _ref<string | number>('foo');
- let bar = _ref <string | number>('bar');
-
-return { msg, bar }
-}
-
-})"
-`;
-
-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> (has macro usage) + <script setup> (no macro usage) 1`] = `
-"import { ref as _ref } from 'vue'
-
- let data = _ref()
-
-export default {
- setup(__props, { expose: __expose }) {
- __expose();
-
- console.log(data.value)
-
-return { data }
-}
-
-}"
-`;
-
-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 }) {
- __expose();
-
- let b = _ref(0)
- let c = 0
- function change() {
- a.value++
- b.value++
- c++
- }
-
-return { a, c, b, change }
-}
-
-}"
-`;
+++ /dev/null
-// TODO remove in 3.4
-import { BindingTypes } from '@vue/compiler-core'
-import { compileSFCScript as compile, assertCode } from '../utils'
-
-// this file only tests integration with SFC - main test case for the ref
-// transform can be found in <root>/packages/reactivity-transform/__tests__
-describe('sfc ref transform', () => {
- function compileWithReactivityTransform(src: string) {
- return compile(src, { reactivityTransform: true })
- }
-
- test('$ unwrapping', () => {
- const { content, bindings } = compileWithReactivityTransform(`<script setup>
- import { ref, shallowRef } from 'vue'
- let foo = $(ref())
- let a = $(ref(1))
- let b = $(shallowRef({
- count: 0
- }))
- let c = () => {}
- let d
- </script>`)
- expect(content).not.toMatch(`$(ref())`)
- expect(content).not.toMatch(`$(ref(1))`)
- expect(content).not.toMatch(`$(shallowRef({`)
- expect(content).toMatch(`let foo = (ref())`)
- expect(content).toMatch(`let a = (ref(1))`)
- expect(content).toMatch(`
- let b = (shallowRef({
- count: 0
- }))
- `)
- // normal declarations left untouched
- expect(content).toMatch(`let c = () => {}`)
- expect(content).toMatch(`let d`)
- expect(content).toMatch(
- `return { foo, a, b, get c() { return c }, set c(v) { c = v }, ` +
- `get d() { return d }, set d(v) { d = v }, ref, shallowRef }`
- )
- assertCode(content)
- expect(bindings).toStrictEqual({
- foo: BindingTypes.SETUP_REF,
- a: BindingTypes.SETUP_REF,
- b: BindingTypes.SETUP_REF,
- c: BindingTypes.SETUP_LET,
- d: BindingTypes.SETUP_LET,
- ref: BindingTypes.SETUP_CONST,
- shallowRef: BindingTypes.SETUP_CONST
- })
- })
-
- test('$ref & $shallowRef declarations', () => {
- const { content, bindings } = compileWithReactivityTransform(`<script setup>
- let foo = $ref()
- let a = $ref(1)
- let b = $shallowRef({
- count: 0
- })
- let c = () => {}
- let d
- </script>`)
- expect(content).toMatch(
- `import { ref as _ref, shallowRef as _shallowRef } from 'vue'`
- )
- expect(content).not.toMatch(`$ref()`)
- expect(content).not.toMatch(`$ref(1)`)
- expect(content).not.toMatch(`$shallowRef({`)
- expect(content).toMatch(`let foo = _ref()`)
- expect(content).toMatch(`let a = _ref(1)`)
- expect(content).toMatch(`
- let b = _shallowRef({
- count: 0
- })
- `)
- // normal declarations left untouched
- expect(content).toMatch(`let c = () => {}`)
- expect(content).toMatch(`let d`)
- assertCode(content)
- expect(bindings).toStrictEqual({
- foo: BindingTypes.SETUP_REF,
- a: BindingTypes.SETUP_REF,
- b: BindingTypes.SETUP_REF,
- c: BindingTypes.SETUP_LET,
- d: BindingTypes.SETUP_LET
- })
- })
-
- test('usage in normal <script>', () => {
- const { content } = compileWithReactivityTransform(`<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 /w typescript', () => {
- const { content } = compileWithReactivityTransform(`
- <script setup lang="ts">
- let msg = $ref<string | number>('foo');
- let bar = $ref <string | number>('bar');
- </script>
- `)
- expect(content).toMatch(`import { ref as _ref`)
- expect(content).toMatch(`let msg = _ref<string | number>('foo')`)
- expect(content).toMatch(`let bar = _ref <string | number>('bar')`)
- assertCode(content)
- })
-
- test('usage with normal <script> + <script setup>', () => {
- const { content, bindings } = compileWithReactivityTransform(`<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
- })
- })
-
- test('usage with normal <script> (has macro usage) + <script setup> (no macro usage)', () => {
- const { content } = compileWithReactivityTransform(`
- <script>
- let data = $ref()
- </script>
- <script setup>
- console.log(data)
- </script>
- `)
- expect(content).toMatch(`console.log(data.value)`)
- assertCode(content)
- })
-
- describe('errors', () => {
- test('defineProps/Emit() referencing ref declarations', () => {
- expect(() =>
- compile(
- `<script setup>
- let bar = $ref(1)
- defineProps({
- bar
- })
- </script>`,
- { reactivityTransform: true }
- )
- ).toThrow(`cannot reference locally declared variables`)
-
- expect(() =>
- compile(
- `<script setup>
- let bar = $ref(1)
- defineEmits({
- bar
- })
- </script>`,
- { reactivityTransform: true }
- )
- ).toThrow(`cannot reference locally declared variables`)
- })
- })
-})
"@vue/compiler-core": "workspace:*",
"@vue/compiler-dom": "workspace:*",
"@vue/compiler-ssr": "workspace:*",
- "@vue/reactivity-transform": "workspace:*",
"@vue/shared": "workspace:*",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.5",
import { CSS_VARS_HELPER, genCssVarsCode } from './style/cssVars'
import { compileTemplate, SFCTemplateCompileOptions } from './compileTemplate'
import { warnOnce } from './warn'
-import { shouldTransform, transformAST } from '@vue/reactivity-transform'
import { transformDestructuredProps } from './script/definePropsDestructure'
import { ScriptCompileContext } from './script/context'
import {
fileExists(file: string): boolean
readFile(file: string): string | undefined
}
- /**
- * (Experimental) Enable syntax transform for using refs without `.value` and
- * using destructured props with reactivity
- * @deprecated the Reactivity Transform proposal has been dropped. This
- * feature will be removed from Vue core in 3.4. If you intend to continue
- * using it, disable this and switch to the [Vue Macros implementation](https://vue-macros.sxzz.moe/features/reactivity-transform.html).
- */
- reactivityTransform?: boolean
}
export interface ImportBinding {
const scriptLang = script && script.lang
const scriptSetupLang = scriptSetup && scriptSetup.lang
- // TODO remove in 3.4
- const enableReactivityTransform = !!options.reactivityTransform
let refBindings: string[] | undefined
if (!scriptSetup) {
}
}
- // apply reactivity transform
- // TODO remove in 3.4
- if (enableReactivityTransform && shouldTransform(script.content)) {
- const { rootRefs, importedHelpers } = transformAST(
- scriptAst,
- ctx.s,
- scriptStartOffset!
- )
- refBindings = rootRefs
- for (const h of importedHelpers) {
- ctx.helperImports.add(h)
- }
- }
-
// <script> after <script setup>
// we need to move the block up so that `const __default__` is
// declared before being used in the actual component definition
transformDestructuredProps(ctx, vueImportAliases)
}
- // 4. Apply reactivity transform
- // TODO remove in 3.4
- if (
- enableReactivityTransform &&
- // normal <script> had ref bindings that maybe used in <script setup>
- (refBindings || shouldTransform(scriptSetup.content))
- ) {
- const { rootRefs, importedHelpers } = transformAST(
- scriptSetupAst,
- ctx.s,
- startOffset,
- refBindings
- )
- refBindings = refBindings ? [...refBindings, ...rootRefs] : rootRefs
- for (const h of importedHelpers) {
- ctx.helperImports.add(h)
- }
- }
-
- // 5. check macro args to make sure it doesn't reference setup scope
+ // 4. check macro args to make sure it doesn't reference setup scope
// variables
checkInvalidScopeReference(ctx.propsRuntimeDecl, DEFINE_PROPS)
checkInvalidScopeReference(ctx.propsRuntimeDefaults, DEFINE_PROPS)
checkInvalidScopeReference(ctx.emitsRuntimeDecl, DEFINE_EMITS)
checkInvalidScopeReference(ctx.optionsRuntimeDecl, DEFINE_OPTIONS)
- // 6. remove non-script content
+ // 5. remove non-script content
if (script) {
if (startOffset < scriptStartOffset!) {
// <script setup> before <script>
ctx.s.remove(endOffset, source.length)
}
- // 7. analyze binding metadata
+ // 6. analyze binding metadata
// `defineProps` & `defineModel` also register props bindings
if (scriptAst) {
Object.assign(ctx.bindingMetadata, analyzeScriptBindings(scriptAst.body))
}
}
- // 8. inject `useCssVars` calls
+ // 7. inject `useCssVars` calls
if (
sfc.cssVars.length &&
// no need to do this when targeting SSR
)
}
- // 9. finalize setup() argument signature
+ // 8. finalize setup() argument signature
let args = `__props`
if (ctx.propsTypeDecl) {
// mark as any and only cast on assignment
args += `, { ${destructureElements.join(', ')} }`
}
- // 10. generate return statement
+ // 9. generate return statement
let returned
if (
!options.inlineTemplate ||
ctx.s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)
}
- // 11. finalize default export
+ // 10. finalize default export
const genDefaultAs = options.genDefaultAs
? `const ${options.genDefaultAs} =`
: `export default`
}
}
- // 12. finalize Vue helper imports
+ // 11. finalize Vue helper imports
if (ctx.helperImports.size > 0) {
ctx.s.prepend(
`import { ${[...ctx.helperImports]
// #9521 export parseCache as a simple map to avoid exposing LRU types
export const parseCache = _parseCache as Map<string, SFCParseResult>
-// TODO remove in 3.4
-export {
- shouldTransform as shouldTransformRef,
- transform as transformRef,
- transformAST as transformRefAST
-} from '@vue/reactivity-transform'
-
// Utilities
export { parse as babelParse } from '@babel/parser'
import MagicString from 'magic-string'
ctx: ScriptCompileContext,
declId: ObjectPattern
) {
- if (!ctx.options.propsDestructure && !ctx.options.reactivityTransform) {
+ if (!ctx.options.propsDestructure) {
return
}
ctx: ScriptCompileContext,
vueImportAliases: Record<string, string>
) {
- if (!ctx.options.propsDestructure && !ctx.options.reactivityTransform) {
+ if (!ctx.options.propsDestructure) {
return
}
-import { shouldTransform, transformAST } from '@vue/reactivity-transform'
import { analyzeScriptBindings } from './analyzeScriptBindings'
import { ScriptCompileContext } from './context'
import MagicString from 'magic-string'
-import { RawSourceMap } from 'source-map-js'
import { rewriteDefaultAST } from '../rewriteDefault'
import { genNormalScriptCssVarsCode } from '../style/cssVars'
let map = script.map
const scriptAst = ctx.scriptAst!
const bindings = analyzeScriptBindings(scriptAst.body)
- const { source, filename, cssVars } = ctx.descriptor
- const { sourceMap, genDefaultAs, isProd } = ctx.options
-
- // TODO remove in 3.4
- if (ctx.options.reactivityTransform && shouldTransform(content)) {
- const s = new MagicString(source)
- const startOffset = script.loc.start.offset
- const endOffset = script.loc.end.offset
- const { importedHelpers } = transformAST(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()
- if (sourceMap !== false) {
- map = s.generateMap({
- source: filename,
- hires: true,
- includeContent: true
- }) as unknown as RawSourceMap
- }
- }
+ const { cssVars } = ctx.descriptor
+ const { genDefaultAs, isProd } = ctx.options
if (cssVars.length || genDefaultAs) {
const defaultVar = genDefaultAs || normalScriptDefaultVar
+++ /dev/null
-import { ref, computed, Ref, ComputedRef, WritableComputedRef } from 'vue'
-import 'vue/macros-global'
-import { RefType, RefTypes } from 'vue/macros'
-import { expectType } from './utils'
-
-// wrapping refs
-
-// normal
-let n = $(ref(1))
-n = 2
-// @ts-expect-error
-n = 'foo'
-
-// #4499 nullable
-let msg = $(ref<string | null>(null))
-msg = 'hello world'
-msg = null
-expectType<RefTypes.Ref | undefined>(msg![RefType])
-
-// computed
-let m = $(computed(() => n + 1))
-m * 1
-// @ts-expect-error
-m.slice()
-expectType<RefTypes.ComputedRef | undefined>(m[RefType])
-
-// writable computed
-let wc = $(
- computed({
- get: () => n + 1,
- set: v => (n = v - 1)
- })
-)
-wc = 2
-// @ts-expect-error
-wc = 'foo'
-expectType<RefTypes.WritableComputedRef | undefined>(wc[RefType])
-
-// destructure
-function useFoo() {
- let x = $ref(1)
- let y = $computed(() => 'hi')
-
- return $$({
- x,
- y,
- z: 123
- })
-}
-
-const fooRes = useFoo()
-const { x, y, z } = $(fooRes)
-expectType<number>(x)
-expectType<string>(y)
-expectType<number>(z)
-
-// $ref
-expectType<number>($ref(1))
-expectType<number>($ref(ref(1)))
-expectType<{ foo: number }>($ref({ foo: ref(1) }))
-
-// $shallowRef
-expectType<number>($shallowRef(1))
-expectType<{ foo: Ref<number> }>($shallowRef({ foo: ref(1) }))
-
-// $computed
-expectType<number>($computed(() => 1))
-let b = $ref(1)
-expectType<number>(
- $computed(() => b, {
- onTrack() {}
- })
-)
-
-// writable computed
-expectType<number>(
- $computed({
- get: () => 1,
- set: () => {}
- })
-)
-
-// $$
-const xRef = $$(x)
-expectType<Ref<number>>(xRef)
-
-const yRef = $$(y)
-expectType<ComputedRef<string>>(yRef)
-
-const c = $computed(() => 1)
-const cRef = $$(c)
-expectType<ComputedRef<number>>(cRef)
-
-const c2 = $computed({
- get: () => 1,
- set: () => {}
-})
-const c2Ref = $$(c2)
-expectType<WritableComputedRef<number>>(c2Ref)
-
-// $$ on object
-const obj = $$({
- n,
- m,
- wc
-})
-
-expectType<Ref<number>>(obj.n)
-expectType<ComputedRef<number>>(obj.m)
-expectType<WritableComputedRef<number>>(obj.wc)
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) 2018-present, Yuxi (Evan) You
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+++ /dev/null
-# @vue/reactivity-transform
-
-> ⚠️ This is experimental and the proposal has been dropped.
-> The feature is now marked as deprecated and will be removed from Vue core
-> in 3.4.
->
-> See reason for deprecation [here](https://github.com/vuejs/rfcs/discussions/369#discussioncomment-5059028).
-
-## Basic Rules
-
-- Ref-creating APIs have `$`-prefixed versions that create reactive variables instead. They also do not need to be explicitly imported. These include:
- - `ref`
- - `computed`
- - `shallowRef`
- - `customRef`
- - `toRef`
-- `$()` can be used to destructure an object into reactive variables, or turn existing refs into reactive variables
-- `$$()` to "escape" the transform, which allows access to underlying refs
-
-```js
-import { watchEffect } from 'vue'
-
-// bind ref as a variable
-let count = $ref(0)
-
-watchEffect(() => {
- // no need for .value
- console.log(count)
-})
-
-// assignments are reactive
-count++
-
-// get the actual ref
-console.log($$(count)) // { value: 1 }
-```
-
-Macros can be optionally imported to make it more explicit:
-
-```js
-// not necessary, but also works
-import { $, $ref } from 'vue/macros'
-
-let count = $ref(0)
-const { x, y } = $(useMouse())
-```
-
-### Global Types
-
-To enable types for the macros globally, include the following in a `.d.ts` file:
-
-```ts
-/// <reference types="vue/macros-global" />
-```
-
-## API
-
-This package is the lower-level transform that can be used standalone. Higher-level tooling (e.g. `@vitejs/plugin-vue` and `vue-loader`) will provide integration via options.
-
-### `shouldTransform`
-
-Can be used to do a cheap check to determine whether full transform should be performed.
-
-```js
-import { shouldTransform } from '@vue/reactivity-transform'
-
-shouldTransform(`let a = ref(0)`) // false
-shouldTransform(`let a = $ref(0)`) // true
-```
-
-### `transform`
-
-```js
-import { transform } from '@vue/reactivity-transform'
-
-const src = `let a = $ref(0); a++`
-const {
- code, // import { ref as _ref } from 'vue'; let a = (ref(0)); a.value++"
- map
-} = transform(src, {
- filename: 'foo.ts',
- sourceMap: true,
-
- // @babel/parser plugins to enable.
- // 'typescript' and 'jsx' will be auto-inferred from filename if provided,
- // so in most cases explicit parserPlugins are not necessary
- parserPlugins: [
- /* ... */
- ]
-})
-```
-
-**Options**
-
-```ts
-interface RefTransformOptions {
- filename?: string
- sourceMap?: boolean // default: false
- parserPlugins?: ParserPlugin[]
- importHelpersFrom?: string // default: "vue"
-}
-```
-
-### `transformAST`
-
-Transform with an existing Babel AST + MagicString instance. This is used internally by `@vue/compiler-sfc` to avoid double parse/transform cost.
-
-```js
-import { transformAST } from '@vue/reactivity-transform'
-import { parse } from '@babel/parser'
-import MagicString from 'magic-string'
-
-const src = `let a = $ref(0); a++`
-const ast = parse(src, { sourceType: 'module' })
-const s = new MagicString(src)
-
-const {
- rootRefs, // ['a']
- importedHelpers // ['ref']
-} = transformAST(ast, s)
-
-console.log(s.toString()) // let a = _ref(0); a.value++
-```
+++ /dev/null
-// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-
-exports[`$ unwrapping 1`] = `
-"
- import { ref, shallowRef } from 'vue'
- let foo = (ref())
- export let a = (ref(1))
- let b = (shallowRef({
- count: 0
- }))
- let c = () => {}
- let d
- label: var e = (ref())
- "
-`;
-
-exports[`$$ 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(1)
- const b = (a)
- const c = ({ a })
- callExternal((a))
- "
-`;
-
-exports[`$$ with some edge cases 1`] = `
-"import { ref as _ref } from 'vue'
-
- ;( /* 2 */ count /* 2 */ )
- ;( count /* 2 */, /**/ a )
- ;( (count /* 2 */, /**/ a) /**/ )
- {
- a:(count,a)
- }
- ;((count) + 1)
- ;([count])
- ; (count )
- console.log(((a)))
- ;(a,b)
- ;(((a++,b)))
- count = ( a++ ,b)
- count = ()=>(a++,b)
- let r1 = _ref(a, (a++,b))
- let r2 = { a:(a++,b),b: (a) }
- switch((c)){
- case d:
- ;(a)
- ;((h,f))
- break
- }
- ((count++,(count),(count,a)))
- "
-`;
-
-exports[`$computed declaration 1`] = `
-"import { computed as _computed } from 'vue'
-
- let a = _computed(() => 1)
- "
-`;
-
-exports[`$ref & $shallowRef declarations 1`] = `
-"import { ref as _ref, shallowRef as _shallowRef } from 'vue'
-
- let foo = _ref()
- export let a = _ref(1)
- let b = _shallowRef({
- count: 0
- })
- let c = () => {}
- let d
- label: var e = _ref()
- "
-`;
-
-exports[`accessing ref binding 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(1)
- console.log(a.value)
- function get() {
- return a.value + 1
- }
- "
-`;
-
-exports[`array destructure 1`] = `
-"import { ref as _ref, toRef as _toRef } from 'vue'
-
- let n = _ref(1), __$temp_1 = (useFoo()),
- a = _toRef(__$temp_1, 0),
- b = _toRef(__$temp_1, 1, 1);
- console.log(n.value, a.value, b.value)
- "
-`;
-
-exports[`handle TS casting syntax 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(1)
- console.log(a.value!)
- console.log(a.value! + 1)
- console.log(a.value as number)
- console.log((a.value as number) + 1)
- console.log(<number>a.value)
- console.log(<number>a.value + 1)
- console.log(a.value! + (a.value as number))
- console.log(a.value! + <number>a.value)
- console.log((a.value as number) + <number>a.value)
- "
-`;
-
-exports[`macro import alias and removal 1`] = `
-"import { ref as _ref, toRef as _toRef } from 'vue'
-
-
-
- let a = _ref(1)
- const __$temp_1 = (useMouse()),
- x = _toRef(__$temp_1, 'x'),
- y = _toRef(__$temp_1, 'y');
- "
-`;
-
-exports[`mixing $ref & $computed declarations 1`] = `
-"import { ref as _ref, computed as _computed } from 'vue'
-
- let a = _ref(1), b = _computed(() => a.value + 1)
- "
-`;
-
-exports[`multi $ref declarations 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(1), b = _ref(2), c = _ref({
- count: 0
- })
- "
-`;
-
-exports[`mutating ref binding 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(1)
- let b = _ref({ count: 0 })
- function inc() {
- a.value++
- a.value = a.value + 1
- b.value.count++
- b.value.count = b.value.count + 1
- ;({ a: a.value } = { a: 2 })
- ;[a.value] = [1]
- }
- "
-`;
-
-exports[`nested destructure 1`] = `
-"import { toRef as _toRef } from 'vue'
-
- let __$temp_1 = (useFoo()),
- b = _toRef(__$temp_1[0].a, 'b');
- let __$temp_2 = (useBar()),
- d = _toRef(__$temp_2.c, 0),
- e = _toRef(__$temp_2.c, 1);
- console.log(b.value, d.value, e.value)
- "
-`;
-
-exports[`nested scopes 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(0)
- let b = _ref(0)
- let c = 0
-
- a.value++ // outer a
- 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
- let c = _ref(0)
- c.value++ // inner c
- let d = _ref(0)
-
- function bar(c) {
- c++ // nested c
- d.value++ // nested d
- }
- bar() // inner bar
-
- if (true) {
- let a = _ref(0)
- a.value++ // if block a
- }
-
- return ({ a, b, c, d })
- }
- "
-`;
-
-exports[`object destructure 1`] = `
-"import { ref as _ref, toRef as _toRef } from 'vue'
-
- let n = _ref(1), __$temp_1 = (useFoo()),
- a = _toRef(__$temp_1, 'a'),
- c = _toRef(__$temp_1, 'b'),
- d = _toRef(__$temp_1, 'd', 1),
- f = _toRef(__$temp_1, 'e', 2),
- h = _toRef(__$temp_1, g);
- let __$temp_2 = (useSomething(() => 1)),
- foo = _toRef(__$temp_2, 'foo');;
- console.log(n.value, a.value, c.value, d.value, f.value, h.value, foo.value)
- "
-`;
-
-exports[`object destructure w/ mid-path default values 1`] = `
-"import { toRef as _toRef } from 'vue'
-
- const __$temp_1 = (useFoo()),
- b = _toRef((__$temp_1.a || { b: 123 }), 'b');
- console.log(b.value)
- "
-`;
-
-exports[`should not overwrite current scope 1`] = `
-"
- const fn = () => {
- const $ = () => 'foo'
- const $ref = () => 'bar'
- const $$ = () => 'baz'
- console.log($())
- console.log($ref())
- console.log($$())
- }
- "
-`;
-
-exports[`should not overwrite importing 1`] = `
-"
- import { $, $$ } from './foo'
- $('foo')
- $$('bar')
- "
-`;
-
-exports[`should not rewrite scope variable 1`] = `
-"import { ref as _ref } from 'vue'
-
-
- let a = _ref(1)
- let b = _ref(1)
- let d = _ref(1)
- const e = 1
- function test() {
- const a = 2
- console.log(a)
- console.log(b.value)
- let c = { c: 3 }
- console.log(c)
- console.log(d.value)
- console.log(e)
- }
- let err = _ref(null)
- try {
- } catch (err) {
- console.log(err)
- }
- "
-`;
-
-exports[`should not rewrite type identifiers 1`] = `
-"import { ref as _ref } from 'vue'
-const props = defineProps<{msg: string; ids?: string[]}>()
- let ids = _ref([])"
-`;
-
-exports[`using ref binding in property shorthand 1`] = `
-"import { ref as _ref } from 'vue'
-
- let a = _ref(1)
- const b = { a: a.value }
- function test() {
- const { a } = b
- }
- "
-`;
+++ /dev/null
-import { parse } from '@babel/parser'
-import { transform } from '../src'
-
-function assertCode(code: string) {
- // parse the generated code to make sure it is valid
- try {
- parse(code, {
- sourceType: 'module',
- plugins: ['typescript']
- })
- } catch (e: any) {
- console.log(code)
- throw e
- }
- expect(code).toMatchSnapshot()
-}
-
-test('$ unwrapping', () => {
- const { code, rootRefs } = transform(`
- import { ref, shallowRef } from 'vue'
- let foo = $(ref())
- export let a = $(ref(1))
- let b = $(shallowRef({
- count: 0
- }))
- let c = () => {}
- let d
- label: var e = $(ref())
- `)
- expect(code).not.toMatch(`$(ref())`)
- expect(code).not.toMatch(`$(ref(1))`)
- expect(code).not.toMatch(`$(shallowRef({`)
- expect(code).toMatch(`let foo = (ref())`)
- expect(code).toMatch(`export let a = (ref(1))`)
- expect(code).toMatch(`
- let b = (shallowRef({
- count: 0
- }))
- `)
- // normal declarations left untouched
- expect(code).toMatch(`let c = () => {}`)
- expect(code).toMatch(`let d`)
- expect(code).toMatch(`label: var e = (ref())`)
- expect(rootRefs).toStrictEqual(['foo', 'a', 'b', 'e'])
- assertCode(code)
-})
-
-test('$ref & $shallowRef declarations', () => {
- const { code, rootRefs, importedHelpers } = transform(`
- let foo = $ref()
- export let a = $ref(1)
- let b = $shallowRef({
- count: 0
- })
- let c = () => {}
- let d
- label: var e = $ref()
- `)
- expect(code).toMatch(
- `import { ref as _ref, shallowRef as _shallowRef } from 'vue'`
- )
- expect(code).not.toMatch(`$ref()`)
- expect(code).not.toMatch(`$ref(1)`)
- expect(code).not.toMatch(`$shallowRef({`)
- expect(code).toMatch(`let foo = _ref()`)
- expect(code).toMatch(`let a = _ref(1)`)
- expect(code).toMatch(`
- let b = _shallowRef({
- count: 0
- })
- `)
- // normal declarations left untouched
- expect(code).toMatch(`let c = () => {}`)
- expect(code).toMatch(`let d`)
- expect(code).toMatch(`label: var e = _ref()`)
- expect(rootRefs).toStrictEqual(['foo', 'a', 'b', 'e'])
- expect(importedHelpers).toStrictEqual(['ref', 'shallowRef'])
- assertCode(code)
-})
-
-test('multi $ref declarations', () => {
- const { code, rootRefs, importedHelpers } = transform(`
- let a = $ref(1), b = $ref(2), c = $ref({
- count: 0
- })
- `)
- expect(code).toMatch(`
- let a = _ref(1), b = _ref(2), c = _ref({
- count: 0
- })
- `)
- expect(rootRefs).toStrictEqual(['a', 'b', 'c'])
- expect(importedHelpers).toStrictEqual(['ref'])
- assertCode(code)
-})
-
-test('$computed declaration', () => {
- const { code, rootRefs, importedHelpers } = transform(`
- let a = $computed(() => 1)
- `)
- expect(code).toMatch(`
- let a = _computed(() => 1)
- `)
- expect(rootRefs).toStrictEqual(['a'])
- expect(importedHelpers).toStrictEqual(['computed'])
- assertCode(code)
-})
-
-test('mixing $ref & $computed declarations', () => {
- const { code, rootRefs, importedHelpers } = transform(`
- let a = $ref(1), b = $computed(() => a + 1)
- `)
- expect(code).toMatch(`
- let a = _ref(1), b = _computed(() => a.value + 1)
- `)
- expect(rootRefs).toStrictEqual(['a', 'b'])
- expect(importedHelpers).toStrictEqual(['ref', 'computed'])
- assertCode(code)
-})
-
-test('accessing ref binding', () => {
- const { code } = transform(`
- let a = $ref(1)
- console.log(a)
- function get() {
- return a + 1
- }
- `)
- expect(code).toMatch(`console.log(a.value)`)
- expect(code).toMatch(`return a.value + 1`)
- assertCode(code)
-})
-
-describe('cases that should not append .value', () => {
- test('member expression', () => {
- const { code } = transform(`
- let a = $ref(1)
- console.log(b.a)
- `)
- expect(code).not.toMatch(`a.value`)
- })
-
- test('function argument', () => {
- const { code } = transform(`
- let a = $ref(1)
- function get(a) {
- return a + 1
- }
- function get2({ a }) {
- return a + 1
- }
- function get3([a]) {
- return a + 1
- }
- `)
- expect(code).not.toMatch(`a.value`)
- })
-
- test('for in/of loops', () => {
- const { code } = transform(`
- let a = $ref(1)
- for (const [a, b] of arr) {
- console.log(a)
- }
- for (let a in arr) {
- console.log(a)
- }
- `)
- expect(code).not.toMatch(`a.value`)
- })
-})
-
-test('mutating ref binding', () => {
- const { code } = transform(`
- let a = $ref(1)
- let b = $ref({ count: 0 })
- function inc() {
- a++
- a = a + 1
- b.count++
- b.count = b.count + 1
- ;({ a } = { a: 2 })
- ;[a] = [1]
- }
- `)
- expect(code).toMatch(`a.value++`)
- expect(code).toMatch(`a.value = a.value + 1`)
- expect(code).toMatch(`b.value.count++`)
- expect(code).toMatch(`b.value.count = b.value.count + 1`)
- expect(code).toMatch(`;({ a: a.value } = { a: 2 })`)
- expect(code).toMatch(`;[a.value] = [1]`)
- assertCode(code)
-})
-
-test('using ref binding in property shorthand', () => {
- const { code } = transform(`
- let a = $ref(1)
- const b = { a }
- function test() {
- const { a } = b
- }
- `)
- expect(code).toMatch(`const b = { a: a.value }`)
- // should not convert destructure
- expect(code).toMatch(`const { a } = b`)
- assertCode(code)
-})
-
-test('should not rewrite scope variable', () => {
- const { code } = transform(`
-
- let a = $ref(1)
- let b = $ref(1)
- let d = $ref(1)
- const e = 1
- function test() {
- const a = 2
- console.log(a)
- console.log(b)
- let c = { c: 3 }
- console.log(c)
- console.log(d)
- console.log(e)
- }
- let err = $ref(null)
- try {
- } catch (err) {
- console.log(err)
- }
- `)
- expect(code).toMatch('console.log(a)')
- expect(code).toMatch('console.log(b.value)')
- expect(code).toMatch('console.log(c)')
- expect(code).toMatch('console.log(d.value)')
- expect(code).toMatch('console.log(e)')
- expect(code).toMatch('console.log(err)')
- assertCode(code)
-})
-
-test('object destructure', () => {
- const { code, rootRefs } = transform(`
- let n = $ref(1), { a, b: c, d = 1, e: f = 2, [g]: h } = $(useFoo())
- let { foo } = $(useSomething(() => 1));
- console.log(n, a, c, d, f, h, foo)
- `)
- expect(code).toMatch(`a = _toRef(__$temp_1, 'a')`)
- expect(code).toMatch(`c = _toRef(__$temp_1, 'b')`)
- expect(code).toMatch(`d = _toRef(__$temp_1, 'd', 1)`)
- expect(code).toMatch(`f = _toRef(__$temp_1, 'e', 2)`)
- expect(code).toMatch(`h = _toRef(__$temp_1, g)`)
- expect(code).toMatch(`foo = _toRef(__$temp_2, 'foo')`)
- expect(code).toMatch(
- `console.log(n.value, a.value, c.value, d.value, f.value, h.value, foo.value)`
- )
- expect(rootRefs).toStrictEqual(['n', 'a', 'c', 'd', 'f', 'h', 'foo'])
- assertCode(code)
-})
-
-test('object destructure w/ mid-path default values', () => {
- const { code, rootRefs } = transform(`
- const { a: { b } = { b: 123 }} = $(useFoo())
- console.log(b)
- `)
- expect(code).toMatch(`b = _toRef((__$temp_1.a || { b: 123 }), 'b')`)
- expect(code).toMatch(`console.log(b.value)`)
- expect(rootRefs).toStrictEqual(['b'])
- assertCode(code)
-})
-
-test('array destructure', () => {
- const { code, rootRefs } = transform(`
- let n = $ref(1), [a, b = 1] = $(useFoo())
- console.log(n, a, b)
- `)
- expect(code).toMatch(`a = _toRef(__$temp_1, 0)`)
- expect(code).toMatch(`b = _toRef(__$temp_1, 1, 1)`)
- expect(code).toMatch(`console.log(n.value, a.value, b.value)`)
- expect(rootRefs).toStrictEqual(['n', 'a', 'b'])
- assertCode(code)
-})
-
-test('nested destructure', () => {
- const { code, rootRefs } = transform(`
- let [{ a: { b }}] = $(useFoo())
- let { c: [d, e] } = $(useBar())
- console.log(b, d, e)
- `)
- expect(code).toMatch(`b = _toRef(__$temp_1[0].a, 'b')`)
- expect(code).toMatch(`d = _toRef(__$temp_2.c, 0)`)
- expect(code).toMatch(`e = _toRef(__$temp_2.c, 1)`)
- expect(rootRefs).toStrictEqual(['b', 'd', 'e'])
- assertCode(code)
-})
-
-test('$$', () => {
- const { code } = transform(`
- let a = $ref(1)
- const b = $$(a)
- const c = $$({ a })
- callExternal($$(a))
- `)
- expect(code).toMatch(`const b = (a)`)
- expect(code).toMatch(`const c = ({ a })`)
- expect(code).toMatch(`callExternal((a))`)
- assertCode(code)
-})
-
-test('$$ with some edge cases', () => {
- const { code } = transform(`
- $$( /* 2 */ count /* 2 */ )
- $$( count /* 2 */, /**/ a )
- $$( (count /* 2 */, /**/ a) /**/ )
- {
- a:$$(count,a)
- }
- $$((count) + 1)
- $$([count])
- $$ (count )
- console.log($$($$(a)))
- $$(a,b)
- $$($$((a++,b)))
- count = $$( a++ ,b)
- count = ()=>$$(a++,b)
- let r1 = $ref(a, $$(a++,b))
- let r2 = { a:$$(a++,b),b:$$ (a) }
- switch($$(c)){
- case d:
- $$(a)
- $$($$(h,f))
- break
- }
- ($$(count++,$$(count),$$(count,a)))
- `)
- expect(code).toMatch(`/* 2 */ count /* 2 */`)
- expect(code).toMatch(`;( count /* 2 */, /**/ a )`)
- expect(code).toMatch(`;( (count /* 2 */, /**/ a) /**/ )`)
- expect(code).toMatch(`a:(count,a)`)
- expect(code).toMatch(`;((count) + 1)`)
- expect(code).toMatch(`;([count])`)
- expect(code).toMatch(`;(a,b)`)
- expect(code).toMatch(`log(((a)))`)
- expect(code).toMatch(`count = ( a++ ,b)`)
- expect(code).toMatch(`()=>(a++,b)`)
- expect(code).toMatch(`_ref(a, (a++,b))`)
- expect(code).toMatch(`{ a:(a++,b),b: (a) }`)
- expect(code).toMatch(`switch((c))`)
- expect(code).toMatch(`;((h,f))`)
- expect(code).toMatch(`((count++,(count),(count,a)))`)
- assertCode(code)
-})
-
-test('nested scopes', () => {
- const { code, rootRefs } = transform(`
- let a = $ref(0)
- let b = $ref(0)
- let c = 0
-
- a++ // outer a
- b++ // outer b
- c++ // outer c
-
- let bar = $ref(0)
- bar++ // outer bar
-
- function foo({ a }) {
- a++ // inner a
- b++ // inner b
- let c = $ref(0)
- c++ // inner c
- let d = $ref(0)
-
- function bar(c) {
- c++ // nested c
- d++ // nested d
- }
- bar() // inner bar
-
- if (true) {
- let a = $ref(0)
- a++ // if block a
- }
-
- return $$({ a, b, c, d })
- }
- `)
- expect(rootRefs).toStrictEqual(['a', 'b', 'bar'])
-
- expect(code).toMatch('a.value++ // outer a')
- expect(code).toMatch('b.value++ // outer b')
- expect(code).toMatch('c++ // outer c')
-
- expect(code).toMatch('a++ // inner a') // shadowed by function arg
- expect(code).toMatch('b.value++ // inner b')
- expect(code).toMatch('c.value++ // inner c') // shadowed by local ref binding
-
- expect(code).toMatch('c++ // nested c') // shadowed by inline fn arg
- expect(code).toMatch(`d.value++ // nested d`)
-
- 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)
-})
-
-//#4062
-test('should not rewrite type identifiers', () => {
- const { code } = transform(
- `const props = defineProps<{msg: string; ids?: string[]}>()
- let ids = $ref([])`,
- {
- parserPlugins: ['typescript']
- }
- )
- expect(code).not.toMatch('.value')
- assertCode(code)
-})
-
-// #4254
-test('handle TS casting syntax', () => {
- const { code } = transform(
- `
- let a = $ref(1)
- console.log(a!)
- console.log(a! + 1)
- console.log(a as number)
- console.log((a as number) + 1)
- console.log(<number>a)
- console.log(<number>a + 1)
- console.log(a! + (a as number))
- console.log(a! + <number>a)
- console.log((a as number) + <number>a)
- `,
- {
- parserPlugins: ['typescript']
- }
- )
- expect(code).toMatch('console.log(a.value!)')
- expect(code).toMatch('console.log(a.value as number)')
- expect(code).toMatch('console.log(<number>a.value)')
- assertCode(code)
-})
-
-test('macro import alias and removal', () => {
- const { code } = transform(
- `
- import { $ as fromRefs, $ref } from 'vue/macros'
-
- let a = $ref(1)
- const { x, y } = fromRefs(useMouse())
- `
- )
- // should remove imports
- expect(code).not.toMatch(`from 'vue/macros'`)
- expect(code).toMatch(`let a = _ref(1)`)
- expect(code).toMatch(`const __$temp_1 = (useMouse())`)
- assertCode(code)
-})
-
-// #6838
-test('should not overwrite importing', () => {
- const { code } = transform(
- `
- import { $, $$ } from './foo'
- $('foo')
- $$('bar')
- `
- )
- assertCode(code)
-})
-
-// #6838
-test('should not overwrite current scope', () => {
- const { code } = transform(
- `
- const fn = () => {
- const $ = () => 'foo'
- const $ref = () => 'bar'
- const $$ = () => 'baz'
- console.log($())
- console.log($ref())
- console.log($$())
- }
- `
- )
- assertCode(code)
-})
-
-describe('errors', () => {
- test('$ref w/ destructure', () => {
- expect(() => transform(`let { a } = $ref(1)`)).toThrow(
- `cannot be used with destructure`
- )
- })
-
- test('$computed w/ destructure', () => {
- expect(() => transform(`let { a } = $computed(() => 1)`)).toThrow(
- `cannot be used with destructure`
- )
- })
-
- test('warn usage in non-init positions', () => {
- expect(() =>
- transform(
- `let bar = $ref(1)
- bar = $ref(2)`
- )
- ).toThrow(`$ref can only be used as the initializer`)
-
- expect(() => transform(`let bar = { foo: $computed(1) }`)).toThrow(
- `$computed can only be used as the initializer`
- )
- })
-
- test('not transform the prototype attributes', () => {
- const { code } = transform(`
- const hasOwnProperty = Object.prototype.hasOwnProperty
- const hasOwn = (val, key) => hasOwnProperty.call(val, key)
- `)
- expect(code).not.toMatch('.value')
- })
-
- test('rest element in $() destructure', () => {
- expect(() => transform(`let { a, ...b } = $(foo())`)).toThrow(
- `does not support rest element`
- )
- expect(() => transform(`let [a, ...b] = $(foo())`)).toThrow(
- `does not support rest element`
- )
- })
-
- test('assignment to constant variable', () => {
- expect(() =>
- transform(`
- const foo = $ref(0)
- foo = 1
- `)
- ).toThrow(`Assignment to constant variable.`)
-
- expect(() =>
- transform(`
- const [a, b] = $([1, 2])
- a = 1
- `)
- ).toThrow(`Assignment to constant variable.`)
-
- expect(() =>
- transform(`
- const foo = $ref(0)
- foo++
- `)
- ).toThrow(`Assignment to constant variable.`)
-
- expect(() =>
- transform(`
- const foo = $ref(0)
- bar = foo
- `)
- ).not.toThrow()
- })
-})
+++ /dev/null
-{
- "name": "@vue/reactivity-transform",
- "version": "3.4.0-alpha.1",
- "description": "@vue/reactivity-transform",
- "main": "dist/reactivity-transform.cjs.js",
- "files": [
- "dist"
- ],
- "buildOptions": {
- "formats": [
- "cjs"
- ],
- "prod": false
- },
- "types": "dist/reactivity-transform.d.ts",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/vuejs/core.git",
- "directory": "packages/reactivity-transform"
- },
- "keywords": [
- "vue"
- ],
- "author": "Evan You",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/vuejs/core/issues"
- },
- "homepage": "https://github.com/vuejs/core/tree/dev/packages/reactivity-transform#readme",
- "dependencies": {
- "@babel/parser": "^7.23.3",
- "@vue/compiler-core": "workspace:*",
- "@vue/shared": "workspace:*",
- "estree-walker": "^2.0.2",
- "magic-string": "^0.30.5"
- },
- "devDependencies": {
- "@babel/core": "^7.23.3",
- "@babel/types": "^7.23.3"
- }
-}
+++ /dev/null
-export function plugin() {
- // TODO
-}
+++ /dev/null
-export * from './reactivityTransform'
+++ /dev/null
-import {
- Node,
- Identifier,
- BlockStatement,
- CallExpression,
- ObjectPattern,
- ArrayPattern,
- Program,
- VariableDeclarator,
- Expression,
- VariableDeclaration,
- ImportDeclaration,
- ImportSpecifier,
- ImportDefaultSpecifier,
- ImportNamespaceSpecifier
-} from '@babel/types'
-import MagicString, { SourceMap } from 'magic-string'
-import { walk } from 'estree-walker'
-import {
- extractIdentifiers,
- isFunctionType,
- isInDestructureAssignment,
- isReferencedIdentifier,
- isStaticProperty,
- walkFunctionParams
-} from '@vue/compiler-core'
-import { parse, ParserPlugin } from '@babel/parser'
-import { hasOwn, isArray, isString, genPropsAccessExp } from '@vue/shared'
-
-const CONVERT_SYMBOL = '$'
-const ESCAPE_SYMBOL = '$$'
-const IMPORT_SOURCE = 'vue/macros'
-const shorthands = ['ref', 'computed', 'shallowRef', 'toRef', 'customRef']
-const transformCheckRE = /[^\w]\$(?:\$|ref|computed|shallowRef)?\s*(\(|\<)/
-
-/**
- * @deprecated will be removed in 3.4
- */
-export function shouldTransform(src: string): boolean {
- return transformCheckRE.test(src)
-}
-
-interface Binding {
- isConst?: boolean
- isProp?: boolean
-}
-type Scope = Record<string, Binding | false>
-
-export interface RefTransformOptions {
- filename?: string
- sourceMap?: boolean
- parserPlugins?: ParserPlugin[]
- importHelpersFrom?: string
-}
-
-export interface RefTransformResults {
- code: string
- map: SourceMap | null
- rootRefs: string[]
- importedHelpers: string[]
-}
-
-export interface ImportBinding {
- local: string
- imported: string
- source: string
- specifier: ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier
-}
-
-/**
- * @deprecated will be removed in 3.4
- */
-export function transform(
- src: string,
- {
- filename,
- sourceMap,
- parserPlugins,
- importHelpersFrom = 'vue'
- }: RefTransformOptions = {}
-): RefTransformResults {
- const plugins: ParserPlugin[] = parserPlugins || []
- if (filename) {
- if (/\.tsx?$/.test(filename)) {
- plugins.push('typescript')
- }
- if (filename.endsWith('x')) {
- plugins.push('jsx')
- }
- }
-
- const ast = parse(src, {
- sourceType: 'module',
- plugins
- })
- const s = new MagicString(src)
- const res = transformAST(ast.program, s, 0)
-
- // inject helper imports
- if (res.importedHelpers.length) {
- s.prepend(
- `import { ${res.importedHelpers
- .map(h => `${h} as _${h}`)
- .join(', ')} } from '${importHelpersFrom}'\n`
- )
- }
-
- return {
- ...res,
- code: s.toString(),
- map: sourceMap
- ? s.generateMap({
- source: filename,
- hires: true,
- includeContent: true
- })
- : null
- }
-}
-
-/**
- * @deprecated will be removed in 3.4
- */
-export function transformAST(
- ast: Program,
- s: MagicString,
- offset = 0,
- knownRefs?: string[],
- knownProps?: Record<
- string, // public prop key
- {
- local: string // local identifier, may be different
- default?: any
- isConst?: boolean
- }
- >
-): {
- rootRefs: string[]
- importedHelpers: string[]
-} {
- warnExperimental()
-
- const userImports: Record<string, ImportBinding> = Object.create(null)
- for (const node of ast.body) {
- if (node.type !== 'ImportDeclaration') continue
- walkImportDeclaration(node)
- }
-
- // macro import handling
- let convertSymbol: string | undefined
- let escapeSymbol: string | undefined
- for (const { local, imported, source, specifier } of Object.values(
- userImports
- )) {
- if (source === IMPORT_SOURCE) {
- if (imported === ESCAPE_SYMBOL) {
- escapeSymbol = local
- } else if (imported === CONVERT_SYMBOL) {
- convertSymbol = local
- } else if (imported !== local) {
- error(
- `macro imports for ref-creating methods do not support aliasing.`,
- specifier
- )
- }
- }
- }
-
- // default symbol
- if (!convertSymbol && !userImports[CONVERT_SYMBOL]) {
- convertSymbol = CONVERT_SYMBOL
- }
- if (!escapeSymbol && !userImports[ESCAPE_SYMBOL]) {
- escapeSymbol = ESCAPE_SYMBOL
- }
-
- const importedHelpers = new Set<string>()
- const rootScope: Scope = {}
- const scopeStack: Scope[] = [rootScope]
- let currentScope: Scope = rootScope
- let escapeScope: CallExpression | undefined // inside $$()
- const excludedIds = new WeakSet<Identifier>()
- const parentStack: Node[] = []
- const propsLocalToPublicMap: Record<string, string> = Object.create(null)
-
- if (knownRefs) {
- for (const key of knownRefs) {
- rootScope[key] = {}
- }
- }
- if (knownProps) {
- for (const key in knownProps) {
- const { local, isConst } = knownProps[key]
- rootScope[local] = {
- isProp: true,
- isConst: !!isConst
- }
- propsLocalToPublicMap[local] = key
- }
- }
-
- function walkImportDeclaration(node: ImportDeclaration) {
- const source = node.source.value
- if (source === IMPORT_SOURCE) {
- s.remove(node.start! + offset, node.end! + offset)
- }
-
- for (const specifier of node.specifiers) {
- const local = specifier.local.name
- const imported =
- (specifier.type === 'ImportSpecifier' &&
- specifier.imported.type === 'Identifier' &&
- specifier.imported.name) ||
- 'default'
- userImports[local] = {
- source,
- local,
- imported,
- specifier
- }
- }
- }
-
- function isRefCreationCall(callee: string): string | false {
- if (!convertSymbol || currentScope[convertSymbol] !== undefined) {
- return false
- }
- if (callee === convertSymbol) {
- return convertSymbol
- }
- if (callee[0] === '$' && shorthands.includes(callee.slice(1))) {
- return callee
- }
- return false
- }
-
- function error(msg: string, node: Node): never {
- const e = new Error(msg)
- ;(e as any).node = node
- throw e
- }
-
- function helper(msg: string) {
- importedHelpers.add(msg)
- return `_${msg}`
- }
-
- function registerBinding(id: Identifier, binding?: Binding) {
- excludedIds.add(id)
- if (currentScope) {
- currentScope[id.name] = binding ? binding : false
- } else {
- error(
- 'registerBinding called without active scope, something is wrong.',
- id
- )
- }
- }
-
- const registerRefBinding = (id: Identifier, isConst = false) =>
- registerBinding(id, { isConst })
-
- let tempVarCount = 0
- function genTempVar() {
- return `__$temp_${++tempVarCount}`
- }
-
- function snip(node: Node) {
- return s.original.slice(node.start! + offset, node.end! + offset)
- }
-
- function walkScope(node: Program | BlockStatement, isRoot = false) {
- for (const stmt of node.body) {
- if (stmt.type === 'VariableDeclaration') {
- walkVariableDeclaration(stmt, isRoot)
- } else if (
- stmt.type === 'FunctionDeclaration' ||
- stmt.type === 'ClassDeclaration'
- ) {
- if (stmt.declare || !stmt.id) continue
- registerBinding(stmt.id)
- } else if (
- (stmt.type === 'ForOfStatement' || stmt.type === 'ForInStatement') &&
- stmt.left.type === 'VariableDeclaration'
- ) {
- walkVariableDeclaration(stmt.left)
- } else if (
- stmt.type === 'ExportNamedDeclaration' &&
- stmt.declaration &&
- stmt.declaration.type === 'VariableDeclaration'
- ) {
- walkVariableDeclaration(stmt.declaration, isRoot)
- } else if (
- stmt.type === 'LabeledStatement' &&
- stmt.body.type === 'VariableDeclaration'
- ) {
- walkVariableDeclaration(stmt.body, isRoot)
- }
- }
- }
-
- function walkVariableDeclaration(stmt: VariableDeclaration, isRoot = false) {
- if (stmt.declare) {
- return
- }
- for (const decl of stmt.declarations) {
- let refCall
- const isCall =
- decl.init &&
- decl.init.type === 'CallExpression' &&
- decl.init.callee.type === 'Identifier'
- if (
- isCall &&
- (refCall = isRefCreationCall((decl as any).init.callee.name))
- ) {
- processRefDeclaration(
- refCall,
- decl.id,
- decl.init as CallExpression,
- stmt.kind === 'const'
- )
- } else {
- const isProps =
- isRoot && isCall && (decl as any).init.callee.name === 'defineProps'
- for (const id of extractIdentifiers(decl.id)) {
- if (isProps) {
- // for defineProps destructure, only exclude them since they
- // are already passed in as knownProps
- excludedIds.add(id)
- } else {
- registerBinding(id)
- }
- }
- }
- }
- }
-
- function processRefDeclaration(
- method: string,
- id: VariableDeclarator['id'],
- call: CallExpression,
- isConst: boolean
- ) {
- excludedIds.add(call.callee as Identifier)
- if (method === convertSymbol) {
- // $
- // remove macro
- s.remove(call.callee.start! + offset, call.callee.end! + offset)
- if (id.type === 'Identifier') {
- // single variable
- registerRefBinding(id, isConst)
- } else if (id.type === 'ObjectPattern') {
- processRefObjectPattern(id, call, isConst)
- } else if (id.type === 'ArrayPattern') {
- processRefArrayPattern(id, call, isConst)
- }
- } else {
- // shorthands
- if (id.type === 'Identifier') {
- registerRefBinding(id, isConst)
- // replace call
- s.overwrite(
- call.start! + offset,
- call.start! + method.length + offset,
- helper(method.slice(1))
- )
- } else {
- error(`${method}() cannot be used with destructure patterns.`, call)
- }
- }
- }
-
- function processRefObjectPattern(
- pattern: ObjectPattern,
- call: CallExpression,
- isConst: boolean,
- tempVar?: string,
- path: PathSegment[] = []
- ) {
- if (!tempVar) {
- tempVar = genTempVar()
- // const { x } = $(useFoo()) --> const __$temp_1 = useFoo()
- s.overwrite(pattern.start! + offset, pattern.end! + offset, tempVar)
- }
-
- let nameId: Identifier | undefined
- for (const p of pattern.properties) {
- let key: Expression | string | undefined
- let defaultValue: Expression | undefined
- if (p.type === 'ObjectProperty') {
- if (p.key.start! === p.value.start!) {
- // shorthand { foo }
- nameId = p.key as Identifier
- if (p.value.type === 'Identifier') {
- // avoid shorthand value identifier from being processed
- excludedIds.add(p.value)
- } else if (
- p.value.type === 'AssignmentPattern' &&
- p.value.left.type === 'Identifier'
- ) {
- // { foo = 1 }
- excludedIds.add(p.value.left)
- defaultValue = p.value.right
- }
- } else {
- key = p.computed ? (p.key as Expression) : (p.key as Identifier).name
- if (p.value.type === 'Identifier') {
- // { foo: bar }
- nameId = p.value
- } else if (p.value.type === 'ObjectPattern') {
- processRefObjectPattern(p.value, call, isConst, tempVar, [
- ...path,
- key
- ])
- } else if (p.value.type === 'ArrayPattern') {
- processRefArrayPattern(p.value, call, isConst, tempVar, [
- ...path,
- key
- ])
- } else if (p.value.type === 'AssignmentPattern') {
- if (p.value.left.type === 'Identifier') {
- // { foo: bar = 1 }
- nameId = p.value.left
- defaultValue = p.value.right
- } else if (p.value.left.type === 'ObjectPattern') {
- processRefObjectPattern(p.value.left, call, isConst, tempVar, [
- ...path,
- [key, p.value.right]
- ])
- } else if (p.value.left.type === 'ArrayPattern') {
- processRefArrayPattern(p.value.left, call, isConst, tempVar, [
- ...path,
- [key, p.value.right]
- ])
- } else {
- // MemberExpression case is not possible here, ignore
- }
- }
- }
- } else {
- // rest element { ...foo }
- error(`reactivity destructure does not support rest elements.`, p)
- }
- if (nameId) {
- registerRefBinding(nameId, isConst)
- // inject toRef() after original replaced pattern
- const source = pathToString(tempVar, path)
- const keyStr = isString(key)
- ? `'${key}'`
- : key
- ? snip(key)
- : `'${nameId.name}'`
- const defaultStr = defaultValue ? `, ${snip(defaultValue)}` : ``
- s.appendLeft(
- call.end! + offset,
- `,\n ${nameId.name} = ${helper(
- 'toRef'
- )}(${source}, ${keyStr}${defaultStr})`
- )
- }
- }
- if (nameId) {
- s.appendLeft(call.end! + offset, ';')
- }
- }
-
- function processRefArrayPattern(
- pattern: ArrayPattern,
- call: CallExpression,
- isConst: boolean,
- tempVar?: string,
- path: PathSegment[] = []
- ) {
- if (!tempVar) {
- // const [x] = $(useFoo()) --> const __$temp_1 = useFoo()
- tempVar = genTempVar()
- s.overwrite(pattern.start! + offset, pattern.end! + offset, tempVar)
- }
-
- let nameId: Identifier | undefined
- for (let i = 0; i < pattern.elements.length; i++) {
- const e = pattern.elements[i]
- if (!e) continue
- let defaultValue: Expression | undefined
- if (e.type === 'Identifier') {
- // [a] --> [__a]
- nameId = e
- } else if (e.type === 'AssignmentPattern') {
- // [a = 1]
- nameId = e.left as Identifier
- defaultValue = e.right
- } else if (e.type === 'RestElement') {
- // [...a]
- error(`reactivity destructure does not support rest elements.`, e)
- } else if (e.type === 'ObjectPattern') {
- processRefObjectPattern(e, call, isConst, tempVar, [...path, i])
- } else if (e.type === 'ArrayPattern') {
- processRefArrayPattern(e, call, isConst, tempVar, [...path, i])
- }
- if (nameId) {
- registerRefBinding(nameId, isConst)
- // inject toRef() after original replaced pattern
- const source = pathToString(tempVar, path)
- const defaultStr = defaultValue ? `, ${snip(defaultValue)}` : ``
- s.appendLeft(
- call.end! + offset,
- `,\n ${nameId.name} = ${helper(
- 'toRef'
- )}(${source}, ${i}${defaultStr})`
- )
- }
- }
- if (nameId) {
- s.appendLeft(call.end! + offset, ';')
- }
- }
-
- type PathSegmentAtom = Expression | string | number
-
- type PathSegment =
- | PathSegmentAtom
- | [PathSegmentAtom, Expression /* default value */]
-
- function pathToString(source: string, path: PathSegment[]): string {
- if (path.length) {
- for (const seg of path) {
- if (isArray(seg)) {
- source = `(${source}${segToString(seg[0])} || ${snip(seg[1])})`
- } else {
- source += segToString(seg)
- }
- }
- }
- return source
- }
-
- function segToString(seg: PathSegmentAtom): string {
- if (typeof seg === 'number') {
- return `[${seg}]`
- } else if (typeof seg === 'string') {
- return `.${seg}`
- } else {
- return snip(seg)
- }
- }
-
- function rewriteId(
- scope: Scope,
- id: Identifier,
- parent: Node,
- parentStack: Node[]
- ): boolean {
- if (hasOwn(scope, id.name)) {
- const binding = scope[id.name]
-
- if (binding) {
- if (
- binding.isConst &&
- ((parent.type === 'AssignmentExpression' && id === parent.left) ||
- parent.type === 'UpdateExpression')
- ) {
- error(`Assignment to constant variable.`, id)
- }
-
- const { isProp } = binding
- if (isStaticProperty(parent) && parent.shorthand) {
- // let binding used in a property shorthand
- // skip for destructure patterns
- if (
- !(parent as any).inPattern ||
- isInDestructureAssignment(parent, parentStack)
- ) {
- if (isProp) {
- if (escapeScope) {
- // prop binding in $$()
- // { prop } -> { prop: __props_prop }
- registerEscapedPropBinding(id)
- s.appendLeft(
- id.end! + offset,
- `: __props_${propsLocalToPublicMap[id.name]}`
- )
- } else {
- // { prop } -> { prop: __props.prop }
- s.appendLeft(
- id.end! + offset,
- `: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`
- )
- }
- } else {
- // { foo } -> { foo: foo.value }
- s.appendLeft(id.end! + offset, `: ${id.name}.value`)
- }
- }
- } else {
- if (isProp) {
- if (escapeScope) {
- // x --> __props_x
- registerEscapedPropBinding(id)
- s.overwrite(
- id.start! + offset,
- id.end! + offset,
- `__props_${propsLocalToPublicMap[id.name]}`
- )
- } else {
- // x --> __props.x
- s.overwrite(
- id.start! + offset,
- id.end! + offset,
- genPropsAccessExp(propsLocalToPublicMap[id.name])
- )
- }
- } else {
- // x --> x.value
- s.appendLeft(id.end! + offset, '.value')
- }
- }
- }
- return true
- }
- return false
- }
-
- const propBindingRefs: Record<string, true> = {}
- function registerEscapedPropBinding(id: Identifier) {
- if (!propBindingRefs.hasOwnProperty(id.name)) {
- propBindingRefs[id.name] = true
- const publicKey = propsLocalToPublicMap[id.name]
- s.prependRight(
- offset,
- `const __props_${publicKey} = ${helper(
- `toRef`
- )}(__props, '${publicKey}');\n`
- )
- }
- }
-
- // check root scope first
- walkScope(ast, true)
- walk(ast, {
- enter(node: Node, parent?: Node) {
- parent && parentStack.push(parent)
-
- // function scopes
- if (isFunctionType(node)) {
- scopeStack.push((currentScope = {}))
- walkFunctionParams(node, registerBinding)
- if (node.body.type === 'BlockStatement') {
- walkScope(node.body)
- }
- return
- }
-
- // catch param
- if (node.type === 'CatchClause') {
- scopeStack.push((currentScope = {}))
- if (node.param && node.param.type === 'Identifier') {
- registerBinding(node.param)
- }
- walkScope(node.body)
- return
- }
-
- // non-function block scopes
- if (node.type === 'BlockStatement' && !isFunctionType(parent!)) {
- scopeStack.push((currentScope = {}))
- walkScope(node)
- return
- }
-
- // skip type nodes
- if (
- parent &&
- parent.type.startsWith('TS') &&
- parent.type !== 'TSAsExpression' &&
- parent.type !== 'TSNonNullExpression' &&
- parent.type !== 'TSTypeAssertion'
- ) {
- return this.skip()
- }
-
- if (node.type === 'Identifier') {
- const binding = rootScope[node.name]
- if (
- // if inside $$(), skip unless this is a destructured prop binding
- !(escapeScope && (!binding || !binding.isProp)) &&
- isReferencedIdentifier(node, parent!, parentStack) &&
- !excludedIds.has(node)
- ) {
- // walk up the scope chain to check if id should be appended .value
- let i = scopeStack.length
- while (i--) {
- if (rewriteId(scopeStack[i], node, parent!, parentStack)) {
- return
- }
- }
- }
- }
-
- if (node.type === 'CallExpression' && node.callee.type === 'Identifier') {
- const callee = node.callee.name
-
- const refCall = isRefCreationCall(callee)
- if (refCall && (!parent || parent.type !== 'VariableDeclarator')) {
- return error(
- `${refCall} can only be used as the initializer of ` +
- `a variable declaration.`,
- node
- )
- }
-
- if (
- escapeSymbol &&
- currentScope[escapeSymbol] === undefined &&
- callee === escapeSymbol
- ) {
- escapeScope = node
- s.remove(node.callee.start! + offset, node.callee.end! + offset)
-
- if (parent?.type === 'ExpressionStatement') {
- // edge case where the call expression is an expression statement
- // if its own - prepend semicolon to avoid it being parsed as
- // function invocation of previous line
- let i =
- (node.leadingComments
- ? node.leadingComments[0].start
- : node.start)! + offset
- while (i--) {
- const char = s.original.charAt(i)
- if (char === '\n') {
- // only insert semi if it's actually the first thing after
- // newline
- s.prependRight(node.start! + offset, ';')
- break
- } else if (!/\s/.test(char)) {
- break
- }
- }
- }
- }
- }
- },
- leave(node: Node, parent?: Node) {
- parent && parentStack.pop()
- if (
- (node.type === 'BlockStatement' && !isFunctionType(parent!)) ||
- isFunctionType(node)
- ) {
- scopeStack.pop()
- currentScope = scopeStack[scopeStack.length - 1] || null
- }
- if (node === escapeScope) {
- escapeScope = undefined
- }
- }
- })
-
- return {
- rootRefs: Object.keys(rootScope).filter(key => {
- const binding = rootScope[key]
- return binding && !binding.isProp
- }),
- importedHelpers: [...importedHelpers]
- }
-}
-
-const hasWarned: Record<string, boolean> = {}
-
-function warnExperimental() {
- // eslint-disable-next-line
- if (typeof window !== 'undefined') {
- return
- }
- warnOnce(
- `Reactivity Transform was an experimental feature and has now been deprecated. ` +
- `It will be removed from Vue core in 3.4. If you intend to continue using it, ` +
- `switch to https://vue-macros.sxzz.moe/features/reactivity-transform.html.\n` +
- `See reason for deprecation here: https://github.com/vuejs/rfcs/discussions/369#discussioncomment-5059028`
- )
-}
-
-function warnOnce(msg: string) {
- const isNodeProd =
- typeof process !== 'undefined' && process.env.NODE_ENV === 'production'
- if (!isNodeProd && !__TEST__ && !hasWarned[msg]) {
- hasWarned[msg] = true
- warn(msg)
- }
-}
-
-function warn(msg: string) {
- console.warn(
- `\x1b[1m\x1b[33m[@vue/reactivity-transform]\x1b[0m\x1b[33m ${msg}\x1b[0m\n`
- )
-}
script: {
inlineTemplate: !useDevMode.value,
isProd: !useDevMode.value,
- reactivityTransform: true,
+ propsDestructure: true,
defineModel: true
},
style: {
+++ /dev/null
-import {
- $ as _$,
- $$ as _$$,
- $ref as _$ref,
- $shallowRef as _$shallowRef,
- $computed as _$computed,
- $customRef as _$customRef,
- $toRef as _$toRef
-} from './macros'
-
-declare global {
- const $: typeof _$
- const $$: typeof _$$
- const $ref: typeof _$ref
- const $shallowRef: typeof _$shallowRef
- const $computed: typeof _$computed
- const $customRef: typeof _$customRef
- const $toRef: typeof _$toRef
-}
"compiler-sfc",
"server-renderer",
"jsx-runtime",
- "jsx.d.ts",
- "macros.d.ts",
- "macros-global.d.ts",
- "ref-macros.d.ts"
+ "jsx.d.ts"
],
"exports": {
".": {
},
"./jsx": "./jsx.d.ts",
"./dist/*": "./dist/*",
- "./package.json": "./package.json",
- "./macros": "./macros.d.ts",
- "./macros-global": "./macros-global.d.ts",
- "./ref-macros": "./ref-macros.d.ts"
+ "./package.json": "./package.json"
},
"buildOptions": {
"name": "Vue",
+++ /dev/null
-// TODO remove in 3.4
-import './macros-global'
'@vue/compiler-ssr':
specifier: workspace:*
version: link:../compiler-ssr
- '@vue/reactivity-transform':
- specifier: workspace:*
- version: link:../reactivity-transform
'@vue/shared':
specifier: workspace:*
version: link:../shared
specifier: workspace:*
version: link:../shared
- packages/reactivity-transform:
- dependencies:
- '@babel/parser':
- specifier: ^7.23.3
- version: 7.23.3
- '@vue/compiler-core':
- specifier: workspace:*
- version: link:../compiler-core
- '@vue/shared':
- specifier: workspace:*
- version: link:../shared
- estree-walker:
- specifier: ^2.0.2
- version: 2.0.2
- magic-string:
- specifier: ^0.30.5
- version: 0.30.5
- devDependencies:
- '@babel/core':
- specifier: ^7.23.3
- version: 7.23.3
- '@babel/types':
- specifier: ^7.23.3
- version: 7.23.3
-
packages/runtime-core:
dependencies:
'@vue/reactivity':
'compiler-core',
'compiler-dom',
'compiler-ssr',
- 'reactivity-transform',
'shared'
]