mirror of https://github.com/vuejs/core.git
chore: Merge branch 'main' into minor
This commit is contained in:
commit
e12b10ac3e
33
CHANGELOG.md
33
CHANGELOG.md
|
@ -1,3 +1,34 @@
|
|||
## [3.3.10](https://github.com/vuejs/core/compare/v3.3.9...v3.3.10) (2023-12-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **app:** prevent template from being cached between apps with different options ([#9724](https://github.com/vuejs/core/issues/9724)) ([ec71585](https://github.com/vuejs/core/commit/ec715854ca12520b2afc9e9b3981cbae05ae5206)), closes [#9618](https://github.com/vuejs/core/issues/9618)
|
||||
* **compiler-sfc:** avoid passing forEach index to genMap ([f12db7f](https://github.com/vuejs/core/commit/f12db7fb564a534cef2e5805cc9f54afe5d72fbf))
|
||||
* **compiler-sfc:** deindent pug/jade templates ([6345197](https://github.com/vuejs/core/commit/634519720a21fb5a6871454e1cadad7053a568b8)), closes [#3231](https://github.com/vuejs/core/issues/3231) [#3842](https://github.com/vuejs/core/issues/3842) [#7723](https://github.com/vuejs/core/issues/7723)
|
||||
* **compiler-sfc:** fix :where and :is selector in scoped mode with multiple selectors ([#9735](https://github.com/vuejs/core/issues/9735)) ([c3e2c55](https://github.com/vuejs/core/commit/c3e2c556b532656b50b8ab5cd2d9eabc26622d63)), closes [#9707](https://github.com/vuejs/core/issues/9707)
|
||||
* **compiler-sfc:** generate more treeshaking friendly code ([#9507](https://github.com/vuejs/core/issues/9507)) ([8d74ca0](https://github.com/vuejs/core/commit/8d74ca0e6fa2738ca6854b7e879ff59419f948c7)), closes [#9500](https://github.com/vuejs/core/issues/9500)
|
||||
* **compiler-sfc:** support inferring generic types ([#8511](https://github.com/vuejs/core/issues/8511)) ([eb5e307](https://github.com/vuejs/core/commit/eb5e307c0be62002e62c4c800d0dfacb39b0d4ca)), closes [#8482](https://github.com/vuejs/core/issues/8482)
|
||||
* **compiler-sfc:** support resolving components from props ([#8785](https://github.com/vuejs/core/issues/8785)) ([7cbcee3](https://github.com/vuejs/core/commit/7cbcee3d831241a8bd3588ae92d3f27e3641e25f))
|
||||
* **compiler-sfc:** throw error when failing to load TS during type resolution ([#8883](https://github.com/vuejs/core/issues/8883)) ([4936d2e](https://github.com/vuejs/core/commit/4936d2e11a8d0ca3704bfe408548cb26bb3fd5e9))
|
||||
* **cssVars:** cssVar names should be double-escaped when generating code for ssr ([#8824](https://github.com/vuejs/core/issues/8824)) ([5199a12](https://github.com/vuejs/core/commit/5199a12f8855cd06f24bf355708b5a2134f63176)), closes [#7823](https://github.com/vuejs/core/issues/7823)
|
||||
* **deps:** update compiler to ^7.23.4 ([#9681](https://github.com/vuejs/core/issues/9681)) ([31f6ebc](https://github.com/vuejs/core/commit/31f6ebc4df84490ed29fb75e7bf4259200eb51f0))
|
||||
* **runtime-core:** Suspense get anchor properly in Transition ([#9309](https://github.com/vuejs/core/issues/9309)) ([65f3fe2](https://github.com/vuejs/core/commit/65f3fe273127a8b68e1222fbb306d28d85f01757)), closes [#8105](https://github.com/vuejs/core/issues/8105)
|
||||
* **runtime-dom:** set width/height with units as attribute ([#8781](https://github.com/vuejs/core/issues/8781)) ([bfc1838](https://github.com/vuejs/core/commit/bfc1838f31199de3f189198a3c234fa7bae91386))
|
||||
* **ssr:** avoid computed being accidentally cached before server render ([#9688](https://github.com/vuejs/core/issues/9688)) ([30d5d93](https://github.com/vuejs/core/commit/30d5d93a92b2154406ec04f8aca6b217fa01177c)), closes [#5300](https://github.com/vuejs/core/issues/5300)
|
||||
* **types:** expose emits as props in functional components ([#9234](https://github.com/vuejs/core/issues/9234)) ([887e54c](https://github.com/vuejs/core/commit/887e54c347ea9eac4c721b5e2288f054873d1d30))
|
||||
* **types:** fix reactive collection types ([#8960](https://github.com/vuejs/core/issues/8960)) ([ad27473](https://github.com/vuejs/core/commit/ad274737015c36906d76f3189203093fa3a2e4e7)), closes [#8904](https://github.com/vuejs/core/issues/8904)
|
||||
* **types:** improve return type withKeys and withModifiers ([#9734](https://github.com/vuejs/core/issues/9734)) ([43c3cfd](https://github.com/vuejs/core/commit/43c3cfdec5ae5d70fa2a21e857abc2d73f1a0d07))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* optimize on* prop check ([38aaa8c](https://github.com/vuejs/core/commit/38aaa8c88648c54fe2616ad9c0961288092fcb44))
|
||||
* **runtime-dom:** cache modifier wrapper functions ([da4a4fb](https://github.com/vuejs/core/commit/da4a4fb5e8eee3c6d31f24ebd79a9d0feca56cb2)), closes [#8882](https://github.com/vuejs/core/issues/8882)
|
||||
* **v-on:** constant handlers with modifiers should not be treated as dynamic ([4d94ebf](https://github.com/vuejs/core/commit/4d94ebfe75174b340d2b794e699cad1add3600a9))
|
||||
|
||||
|
||||
|
||||
# [3.4.0-alpha.3](https://github.com/vuejs/core/compare/v3.4.0-alpha.2...v3.4.0-alpha.3) (2023-11-28)
|
||||
|
||||
|
||||
|
@ -97,7 +128,7 @@
|
|||
* **compiler-sfc:** fix dynamic directive arguments usage check for slots ([#9495](https://github.com/vuejs/core/issues/9495)) ([b39fa1f](https://github.com/vuejs/core/commit/b39fa1f8157647859331ce439c42ae016a49b415)), closes [#9493](https://github.com/vuejs/core/issues/9493)
|
||||
* **deps:** update dependency @vue/repl to ^2.6.2 ([#9536](https://github.com/vuejs/core/issues/9536)) ([5cef325](https://github.com/vuejs/core/commit/5cef325f41e3b38657c72fa1a38dedeee1c7a60a))
|
||||
* **deps:** update dependency @vue/repl to ^2.6.3 ([#9540](https://github.com/vuejs/core/issues/9540)) ([176d590](https://github.com/vuejs/core/commit/176d59058c9aecffe9da4d4311e98496684f06d4))
|
||||
* **hydration:** fix tagName access eeror on comment/text node hydration mismatch ([dd8a0cf](https://github.com/vuejs/core/commit/dd8a0cf5dcde13d2cbd899262a0e07f16e14e489)), closes [#9531](https://github.com/vuejs/core/issues/9531)
|
||||
* **hydration:** fix tagName access error on comment/text node hydration mismatch ([dd8a0cf](https://github.com/vuejs/core/commit/dd8a0cf5dcde13d2cbd899262a0e07f16e14e489)), closes [#9531](https://github.com/vuejs/core/issues/9531)
|
||||
* **types:** avoid exposing lru-cache types in generated dts ([462aeb3](https://github.com/vuejs/core/commit/462aeb3b600765e219ded2ee9a0ed1e74df61de0)), closes [#9521](https://github.com/vuejs/core/issues/9521)
|
||||
* **warn:** avoid warning on empty children with Suspense ([#3962](https://github.com/vuejs/core/issues/3962)) ([405f345](https://github.com/vuejs/core/commit/405f34587a63a5f1e3d147b9848219ea98acc22d))
|
||||
|
||||
|
|
10
package.json
10
package.json
|
@ -57,8 +57,8 @@
|
|||
"node": ">=18.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "^7.23.4",
|
||||
"@babel/types": "^7.23.4",
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@babel/types": "^7.23.5",
|
||||
"@rollup/plugin-alias": "^5.0.1",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-json": "^6.0.1",
|
||||
|
@ -67,7 +67,7 @@
|
|||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@types/hash-sum": "^1.0.2",
|
||||
"@types/minimist": "^1.2.5",
|
||||
"@types/node": "^20.10.0",
|
||||
"@types/node": "^20.10.3",
|
||||
"@types/semver": "^7.5.5",
|
||||
"@typescript-eslint/parser": "^6.13.0",
|
||||
"@vitest/coverage-istanbul": "^0.34.6",
|
||||
|
@ -93,7 +93,7 @@
|
|||
"prettier": "^3.1.0",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"pug": "^3.0.2",
|
||||
"puppeteer": "~21.5.1",
|
||||
"puppeteer": "~21.5.2",
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^4.1.4",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
|
@ -105,7 +105,7 @@
|
|||
"terser": "^5.22.0",
|
||||
"todomvc-app-css": "^2.4.3",
|
||||
"tslib": "^2.6.2",
|
||||
"tsx": "^4.5.0",
|
||||
"tsx": "^4.6.2",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.0.0",
|
||||
"vitest": "^0.34.6"
|
||||
|
|
|
@ -152,6 +152,28 @@ describe('compiler: element transform', () => {
|
|||
expect(node.tag).toBe(`Foo.Example`)
|
||||
})
|
||||
|
||||
test('resolve namespaced component from props bindings (inline)', () => {
|
||||
const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {
|
||||
inline: true,
|
||||
bindingMetadata: {
|
||||
Foo: BindingTypes.PROPS
|
||||
}
|
||||
})
|
||||
expect(root.helpers).not.toContain(RESOLVE_COMPONENT)
|
||||
expect(node.tag).toBe(`_unref(__props["Foo"]).Example`)
|
||||
})
|
||||
|
||||
test('resolve namespaced component from props bindings (non-inline)', () => {
|
||||
const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {
|
||||
inline: false,
|
||||
bindingMetadata: {
|
||||
Foo: BindingTypes.PROPS
|
||||
}
|
||||
})
|
||||
expect(root.helpers).not.toContain(RESOLVE_COMPONENT)
|
||||
expect(node.tag).toBe('_unref($props["Foo"]).Example')
|
||||
})
|
||||
|
||||
test('do not resolve component from non-script-setup bindings', () => {
|
||||
const bindingMetadata = {
|
||||
Example: BindingTypes.SETUP_MAYBE_REF
|
||||
|
@ -1138,6 +1160,20 @@ describe('compiler: element transform', () => {
|
|||
genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION])
|
||||
)
|
||||
})
|
||||
|
||||
test('should not have PROPS patchflag for constant v-on handlers', () => {
|
||||
const { node } = parseWithElementTransform(`<div @keydown="foo" />`, {
|
||||
prefixIdentifiers: true,
|
||||
bindingMetadata: {
|
||||
foo: BindingTypes.SETUP_CONST
|
||||
},
|
||||
directiveTransforms: {
|
||||
on: transformOn
|
||||
}
|
||||
})
|
||||
// should only have hydration flag
|
||||
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
|
||||
})
|
||||
})
|
||||
|
||||
describe('dynamic component', () => {
|
||||
|
|
|
@ -32,13 +32,13 @@
|
|||
},
|
||||
"homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-core#readme",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.4",
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@vue/shared": "workspace:*",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.23.4"
|
||||
"@babel/types": "^7.23.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import {
|
|||
TemplateTextChildNode,
|
||||
DirectiveArguments,
|
||||
createVNodeCall,
|
||||
ConstantTypes
|
||||
ConstantTypes,
|
||||
JSChildNode
|
||||
} from '../ast'
|
||||
import {
|
||||
PatchFlags,
|
||||
|
@ -370,6 +371,13 @@ function resolveSetupReference(name: string, context: TransformContext) {
|
|||
`${context.helperString(UNREF)}(${fromMaybeRef})`
|
||||
: `$setup[${JSON.stringify(fromMaybeRef)}]`
|
||||
}
|
||||
|
||||
const fromProps = checkType(BindingTypes.PROPS)
|
||||
if (fromProps) {
|
||||
return `${context.helperString(UNREF)}(${
|
||||
context.inline ? '__props' : '$props'
|
||||
}[${JSON.stringify(fromProps)}])`
|
||||
}
|
||||
}
|
||||
|
||||
export type PropsExpression = ObjectExpression | CallExpression | ExpressionNode
|
||||
|
@ -437,6 +445,12 @@ export function buildProps(
|
|||
hasVnodeHook = true
|
||||
}
|
||||
|
||||
if (isEventHandler && value.type === NodeTypes.JS_CALL_EXPRESSION) {
|
||||
// handler wrapped with internal helper e.g. withModifiers(fn)
|
||||
// extract the actual expression
|
||||
value = value.arguments[0] as JSChildNode
|
||||
}
|
||||
|
||||
if (
|
||||
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
|
||||
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
||||
|
|
|
@ -7,7 +7,8 @@ import {
|
|||
NodeTypes,
|
||||
ObjectExpression,
|
||||
transform,
|
||||
VNodeCall
|
||||
VNodeCall,
|
||||
BindingTypes
|
||||
} from '@vue/compiler-core'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers'
|
||||
|
@ -25,12 +26,11 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
|
|||
},
|
||||
...options
|
||||
})
|
||||
const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall
|
||||
return {
|
||||
root: ast,
|
||||
props: (
|
||||
((ast.children[0] as ElementNode).codegenNode as VNodeCall)
|
||||
.props as ObjectExpression
|
||||
).properties
|
||||
node,
|
||||
props: (node.props as ObjectExpression).properties
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,4 +288,18 @@ describe('compiler-dom: transform v-on', () => {
|
|||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('should not have PROPS patchFlag for constant v-on handlers with modifiers', () => {
|
||||
const { node } = parseWithVOn(`<div @keydown.up="foo" />`, {
|
||||
prefixIdentifiers: true,
|
||||
bindingMetadata: {
|
||||
foo: BindingTypes.SETUP_CONST
|
||||
},
|
||||
directiveTransforms: {
|
||||
on: transformOn
|
||||
}
|
||||
})
|
||||
// should only have hydration flag
|
||||
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1065,10 +1065,12 @@ export default {
|
|||
setup(__props) {
|
||||
|
||||
const count = ref(0)
|
||||
const style = { color: 'red' }
|
||||
|
||||
return (_ctx, _push, _parent, _attrs) => {
|
||||
const _cssVars = { style: {
|
||||
\\"--xxxxxxxx-count\\": (count.value)
|
||||
\\"--xxxxxxxx-count\\": (count.value),
|
||||
\\"--xxxxxxxx-style\\\\\\\\.color\\": (style.color)
|
||||
}}
|
||||
_push(\`<!--[--><div\${
|
||||
_ssrRenderAttrs(_cssVars)
|
||||
|
|
|
@ -826,6 +826,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const count = ref(0)
|
||||
const style = { color: 'red' }
|
||||
</script>
|
||||
<template>
|
||||
<div>{{ count }}</div>
|
||||
|
@ -833,6 +834,7 @@ describe('SFC compile <script setup>', () => {
|
|||
</template>
|
||||
<style>
|
||||
div { color: v-bind(count) }
|
||||
span { color: v-bind(style.color) }
|
||||
</style>
|
||||
`,
|
||||
{
|
||||
|
@ -847,6 +849,7 @@ describe('SFC compile <script setup>', () => {
|
|||
expect(content).toMatch(`ssrInterpolate`)
|
||||
expect(content).not.toMatch(`useCssVars`)
|
||||
expect(content).toMatch(`"--${mockId}-count": (count.value)`)
|
||||
expect(content).toMatch(`"--${mockId}-style\\\\.color": (style.color)`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ exports[`defineModel() > w/ array props 1`] = `
|
|||
"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'
|
||||
|
||||
export default {
|
||||
props: _mergeModels(['foo', 'bar'], {
|
||||
props: /*#__PURE__*/_mergeModels(['foo', 'bar'], {
|
||||
\\"count\\": {},
|
||||
}),
|
||||
emits: [\\"update:count\\"],
|
||||
|
@ -47,10 +47,10 @@ exports[`defineModel() > w/ defineProps and defineEmits 1`] = `
|
|||
"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'
|
||||
|
||||
export default {
|
||||
props: _mergeModels({ foo: String }, {
|
||||
props: /*#__PURE__*/_mergeModels({ foo: String }, {
|
||||
\\"modelValue\\": { default: 0 },
|
||||
}),
|
||||
emits: _mergeModels(['change'], [\\"update:modelValue\\"]),
|
||||
emits: /*#__PURE__*/_mergeModels(['change'], [\\"update:modelValue\\"]),
|
||||
setup(__props, { expose: __expose }) {
|
||||
__expose();
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ exports[`defineProps > withDefaults (dynamic) 1`] = `
|
|||
import { defaults } from './foo'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: _mergeDefaults({
|
||||
props: /*#__PURE__*/_mergeDefaults({
|
||||
foo: { type: String, required: false },
|
||||
bar: { type: Number, required: false },
|
||||
baz: { type: Boolean, required: true }
|
||||
|
@ -353,7 +353,7 @@ exports[`defineProps > withDefaults (dynamic) w/ production mode 1`] = `
|
|||
import { defaults } from './foo'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: _mergeDefaults({
|
||||
props: /*#__PURE__*/_mergeDefaults({
|
||||
foo: { type: Function },
|
||||
bar: { type: Boolean },
|
||||
baz: { type: [Boolean, Function] },
|
||||
|
@ -375,7 +375,7 @@ exports[`defineProps > withDefaults (reference) 1`] = `
|
|||
import { defaults } from './foo'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: _mergeDefaults({
|
||||
props: /*#__PURE__*/_mergeDefaults({
|
||||
foo: { type: String, required: false },
|
||||
bar: { type: Number, required: false },
|
||||
baz: { type: Boolean, required: true }
|
||||
|
@ -462,7 +462,7 @@ exports[`defineProps > withDefaults w/ dynamic object method 1`] = `
|
|||
"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: _mergeDefaults({
|
||||
props: /*#__PURE__*/_mergeDefaults({
|
||||
foo: { type: Function, required: false }
|
||||
}, {
|
||||
['fo' + 'o']() { return 'foo' }
|
||||
|
|
|
@ -62,7 +62,7 @@ exports[`sfc reactive props destructure > default values w/ array runtime declar
|
|||
"import { mergeDefaults as _mergeDefaults } from 'vue'
|
||||
|
||||
export default {
|
||||
props: _mergeDefaults(['foo', 'bar', 'baz'], {
|
||||
props: /*#__PURE__*/_mergeDefaults(['foo', 'bar', 'baz'], {
|
||||
foo: 1,
|
||||
bar: () => ({}),
|
||||
func: () => {}, __skip_func: true
|
||||
|
@ -81,7 +81,7 @@ exports[`sfc reactive props destructure > default values w/ object runtime decla
|
|||
"import { mergeDefaults as _mergeDefaults } from 'vue'
|
||||
|
||||
export default {
|
||||
props: _mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {
|
||||
props: /*#__PURE__*/_mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {
|
||||
foo: 1,
|
||||
bar: () => ({}),
|
||||
func: () => {}, __skip_func: true,
|
||||
|
@ -101,7 +101,7 @@ exports[`sfc reactive props destructure > default values w/ runtime declaration
|
|||
"import { mergeDefaults as _mergeDefaults } from 'vue'
|
||||
|
||||
export default {
|
||||
props: _mergeDefaults(['foo', 'foo:bar'], {
|
||||
props: /*#__PURE__*/_mergeDefaults(['foo', 'foo:bar'], {
|
||||
foo: 1,
|
||||
\\"foo:bar\\": 'foo-bar'
|
||||
}),
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('defineModel()', () => {
|
|||
{ defineModel: true }
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`props: _mergeModels({ foo: String }`)
|
||||
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels({ foo: String }`)
|
||||
expect(content).toMatch(`"modelValue": { default: 0 }`)
|
||||
expect(content).toMatch(`const count = _useModel(__props, "modelValue")`)
|
||||
expect(content).not.toMatch('defineModel')
|
||||
|
@ -70,7 +70,7 @@ describe('defineModel()', () => {
|
|||
{ defineModel: true }
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`props: _mergeModels(['foo', 'bar'], {
|
||||
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels(['foo', 'bar'], {
|
||||
"count": {},
|
||||
})`)
|
||||
expect(content).toMatch(`const count = _useModel(__props, "count")`)
|
||||
|
|
|
@ -78,7 +78,8 @@ describe('sfc reactive props destructure', () => {
|
|||
// literals can be used as-is, non-literals are always returned from a
|
||||
// function
|
||||
// functions need to be marked with a skip marker
|
||||
expect(content).toMatch(`props: _mergeDefaults(['foo', 'bar', 'baz'], {
|
||||
expect(content)
|
||||
.toMatch(`props: /*#__PURE__*/_mergeDefaults(['foo', 'bar', 'baz'], {
|
||||
foo: 1,
|
||||
bar: () => ({}),
|
||||
func: () => {}, __skip_func: true
|
||||
|
@ -98,7 +99,7 @@ describe('sfc reactive props destructure', () => {
|
|||
// safely infer whether runtime type is Function (e.g. if the runtime decl
|
||||
// is imported, or spreads another object)
|
||||
expect(content)
|
||||
.toMatch(`props: _mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {
|
||||
.toMatch(`props: /*#__PURE__*/_mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {
|
||||
foo: 1,
|
||||
bar: () => ({}),
|
||||
func: () => {}, __skip_func: true,
|
||||
|
@ -122,7 +123,7 @@ describe('sfc reactive props destructure', () => {
|
|||
})
|
||||
|
||||
expect(content).toMatch(`
|
||||
props: _mergeDefaults(['foo', 'foo:bar'], {
|
||||
props: /*#__PURE__*/_mergeDefaults(['foo', 'foo:bar'], {
|
||||
foo: 1,
|
||||
"foo:bar": 'foo-bar'
|
||||
}),`)
|
||||
|
|
|
@ -455,6 +455,88 @@ describe('resolveType', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('generics', () => {
|
||||
test('generic with type literal', () => {
|
||||
expect(
|
||||
resolve(`
|
||||
type Props<T> = T
|
||||
defineProps<Props<{ foo: string }>>()
|
||||
`).props
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
})
|
||||
})
|
||||
|
||||
test('generic used in intersection', () => {
|
||||
expect(
|
||||
resolve(`
|
||||
type Foo = { foo: string; }
|
||||
type Bar = { bar: number; }
|
||||
type Props<T,U> = T & U & { baz: boolean }
|
||||
defineProps<Props<Foo, Bar>>()
|
||||
`).props
|
||||
).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number'],
|
||||
baz: ['Boolean']
|
||||
})
|
||||
})
|
||||
|
||||
test('generic type /w generic type alias', () => {
|
||||
expect(
|
||||
resolve(`
|
||||
type Aliased<T> = Readonly<Partial<T>>
|
||||
type Props<T> = Aliased<T>
|
||||
type Foo = { foo: string; }
|
||||
defineProps<Props<Foo>>()
|
||||
`).props
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
})
|
||||
})
|
||||
|
||||
test('generic type /w aliased type literal', () => {
|
||||
expect(
|
||||
resolve(`
|
||||
type Aliased<T> = { foo: T }
|
||||
defineProps<Aliased<string>>()
|
||||
`).props
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
})
|
||||
})
|
||||
|
||||
test('generic type /w interface', () => {
|
||||
expect(
|
||||
resolve(`
|
||||
interface Props<T> {
|
||||
foo: T
|
||||
}
|
||||
type Foo = string
|
||||
defineProps<Props<Foo>>()
|
||||
`).props
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
})
|
||||
})
|
||||
|
||||
test('generic from external-file', () => {
|
||||
const files = {
|
||||
'/foo.ts': 'export type P<T> = { foo: T }'
|
||||
}
|
||||
const { props } = resolve(
|
||||
`
|
||||
import { P } from './foo'
|
||||
defineProps<P<string>>()
|
||||
`,
|
||||
files
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String']
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('external type imports', () => {
|
||||
test('relative ts', () => {
|
||||
const files = {
|
||||
|
|
|
@ -144,6 +144,23 @@ describe('SFC scoped CSS', () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test(':is() and :where() with multiple selectors', () => {
|
||||
expect(compileScoped(`:is(.foo) { color: red; }`)).toMatchInlineSnapshot(`
|
||||
":is(.foo[data-v-test]) { color: red;
|
||||
}"
|
||||
`)
|
||||
expect(compileScoped(`:where(.foo, .bar) { color: red; }`))
|
||||
.toMatchInlineSnapshot(`
|
||||
":where(.foo[data-v-test], .bar[data-v-test]) { color: red;
|
||||
}"
|
||||
`)
|
||||
expect(compileScoped(`:is(.foo, .bar) div { color: red; }`))
|
||||
.toMatchInlineSnapshot(`
|
||||
":is(.foo, .bar) div[data-v-test] { color: red;
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('media query', () => {
|
||||
expect(compileScoped(`@media print { .foo { color: red }}`))
|
||||
.toMatchInlineSnapshot(`
|
||||
|
|
|
@ -61,6 +61,33 @@ body
|
|||
expect(result.errors.length).toBe(0)
|
||||
})
|
||||
|
||||
test('preprocess pug with indents and blank lines', () => {
|
||||
const template = parse(
|
||||
`
|
||||
<template lang="pug">
|
||||
body
|
||||
h1 The next line contains four spaces.
|
||||
|
||||
div.container
|
||||
p The next line is empty.
|
||||
p This is the last line.
|
||||
</template>
|
||||
`,
|
||||
{ filename: 'example.vue', sourceMap: true }
|
||||
).descriptor.template as SFCTemplateBlock
|
||||
|
||||
const result = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.source).toBe(
|
||||
'<body><h1>The next line contains four spaces.</h1><div class="container"><p>The next line is empty.</p></div><p>This is the last line.</p></body>'
|
||||
)
|
||||
})
|
||||
|
||||
test('warn missing preprocessor', () => {
|
||||
const template = parse(`<template lang="unknownLang">hi</template>\n`, {
|
||||
filename: 'example.vue',
|
||||
|
|
|
@ -80,6 +80,26 @@ font-weight: bold;
|
|||
})
|
||||
})
|
||||
|
||||
test('template block with lang + indent', () => {
|
||||
// Padding determines how many blank lines will there be before the style block
|
||||
const padding = Math.round(Math.random() * 10)
|
||||
const template = parse(
|
||||
`${'\n'.repeat(padding)}<template lang="pug">
|
||||
h1 foo
|
||||
div bar
|
||||
span baz
|
||||
</template>\n`
|
||||
).descriptor.template!
|
||||
|
||||
expect(template.map).not.toBeUndefined()
|
||||
|
||||
const consumer = new SourceMapConsumer(template.map!)
|
||||
consumer.eachMapping(mapping => {
|
||||
expect(mapping.originalLine - mapping.generatedLine).toBe(padding)
|
||||
expect(mapping.originalColumn - mapping.generatedColumn).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
test('custom block', () => {
|
||||
const padding = Math.round(Math.random() * 10)
|
||||
const custom = parse(
|
||||
|
|
|
@ -32,18 +32,18 @@
|
|||
},
|
||||
"homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.4",
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@vue/compiler-core": "workspace:*",
|
||||
"@vue/compiler-dom": "workspace:*",
|
||||
"@vue/compiler-ssr": "workspace:*",
|
||||
"@vue/shared": "workspace:*",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.5",
|
||||
"postcss": "^8.4.31",
|
||||
"postcss": "^8.4.32",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.23.4",
|
||||
"@babel/types": "^7.23.5",
|
||||
"@vue/consolidate": "^0.17.3",
|
||||
"hash-sum": "^2.0.0",
|
||||
"lru-cache": "^10.1.0",
|
||||
|
|
|
@ -239,22 +239,34 @@ export function parse(
|
|||
}
|
||||
}
|
||||
|
||||
// dedent pug/jade templates
|
||||
let templateColumnOffset = 0
|
||||
if (
|
||||
descriptor.template &&
|
||||
(descriptor.template.lang === 'pug' || descriptor.template.lang === 'jade')
|
||||
) {
|
||||
;[descriptor.template.content, templateColumnOffset] = dedent(
|
||||
descriptor.template.content
|
||||
)
|
||||
}
|
||||
|
||||
if (sourceMap) {
|
||||
const genMap = (block: SFCBlock | null) => {
|
||||
const genMap = (block: SFCBlock | null, columnOffset = 0) => {
|
||||
if (block && !block.src) {
|
||||
block.map = generateSourceMap(
|
||||
filename,
|
||||
source,
|
||||
block.content,
|
||||
sourceRoot,
|
||||
!pad || block.type === 'template' ? block.loc.start.line - 1 : 0
|
||||
!pad || block.type === 'template' ? block.loc.start.line - 1 : 0,
|
||||
columnOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
genMap(descriptor.template)
|
||||
genMap(descriptor.template, templateColumnOffset)
|
||||
genMap(descriptor.script)
|
||||
descriptor.styles.forEach(genMap)
|
||||
descriptor.customBlocks.forEach(genMap)
|
||||
descriptor.styles.forEach(s => genMap(s))
|
||||
descriptor.customBlocks.forEach(s => genMap(s))
|
||||
}
|
||||
|
||||
// parse CSS vars
|
||||
|
@ -335,7 +347,8 @@ function generateSourceMap(
|
|||
source: string,
|
||||
generated: string,
|
||||
sourceRoot: string,
|
||||
lineOffset: number
|
||||
lineOffset: number,
|
||||
columnOffset: number
|
||||
): RawSourceMap {
|
||||
const map = new SourceMapGenerator({
|
||||
file: filename.replace(/\\/g, '/'),
|
||||
|
@ -351,7 +364,7 @@ function generateSourceMap(
|
|||
if (!/\s/.test(line[i])) {
|
||||
map._mappings.add({
|
||||
originalLine,
|
||||
originalColumn: i,
|
||||
originalColumn: i + columnOffset,
|
||||
generatedLine,
|
||||
generatedColumn: i,
|
||||
source: filename,
|
||||
|
@ -431,3 +444,31 @@ export function hmrShouldReload(
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Dedent a string.
|
||||
*
|
||||
* This removes any whitespace that is common to all lines in the string from
|
||||
* each line in the string.
|
||||
*/
|
||||
function dedent(s: string): [string, number] {
|
||||
const lines = s.split('\n')
|
||||
const minIndent = lines.reduce(function (minIndent, line) {
|
||||
if (line.trim() === '') {
|
||||
return minIndent
|
||||
}
|
||||
const indent = line.match(/^\s*/)?.[0]?.length || 0
|
||||
return Math.min(indent, minIndent)
|
||||
}, Infinity)
|
||||
if (minIndent === 0) {
|
||||
return [s, minIndent]
|
||||
}
|
||||
return [
|
||||
lines
|
||||
.map(function (line) {
|
||||
return line.slice(minIndent)
|
||||
})
|
||||
.join('\n'),
|
||||
minIndent
|
||||
]
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ export function genRuntimeEmits(ctx: ScriptCompileContext): string | undefined {
|
|||
.map(n => JSON.stringify(`update:${n}`))
|
||||
.join(', ')}]`
|
||||
emitsDecl = emitsDecl
|
||||
? `${ctx.helper('mergeModels')}(${emitsDecl}, ${modelEmitsDecl})`
|
||||
? `/*#__PURE__*/${ctx.helper(
|
||||
'mergeModels'
|
||||
)}(${emitsDecl}, ${modelEmitsDecl})`
|
||||
: modelEmitsDecl
|
||||
}
|
||||
return emitsDecl
|
||||
|
|
|
@ -148,7 +148,7 @@ export function genRuntimeProps(ctx: ScriptCompileContext): string | undefined {
|
|||
)
|
||||
}
|
||||
if (defaults.length) {
|
||||
propsDecls = `${ctx.helper(
|
||||
propsDecls = `/*#__PURE__*/${ctx.helper(
|
||||
`mergeDefaults`
|
||||
)}(${propsDecls}, {\n ${defaults.join(',\n ')}\n})`
|
||||
}
|
||||
|
@ -160,7 +160,9 @@ export function genRuntimeProps(ctx: ScriptCompileContext): string | undefined {
|
|||
const modelsDecls = genModelProps(ctx)
|
||||
|
||||
if (propsDecls && modelsDecls) {
|
||||
return `${ctx.helper('mergeModels')}(${propsDecls}, ${modelsDecls})`
|
||||
return `/*#__PURE__*/${ctx.helper(
|
||||
'mergeModels'
|
||||
)}(${propsDecls}, ${modelsDecls})`
|
||||
} else {
|
||||
return modelsDecls || propsDecls
|
||||
}
|
||||
|
@ -190,9 +192,9 @@ export function extractRuntimeProps(
|
|||
${propStrings.join(',\n ')}\n }`
|
||||
|
||||
if (ctx.propsRuntimeDefaults && !hasStaticDefaults) {
|
||||
propsDecls = `${ctx.helper('mergeDefaults')}(${propsDecls}, ${ctx.getString(
|
||||
ctx.propsRuntimeDefaults
|
||||
)})`
|
||||
propsDecls = `/*#__PURE__*/${ctx.helper(
|
||||
'mergeDefaults'
|
||||
)}(${propsDecls}, ${ctx.getString(ctx.propsRuntimeDefaults)})`
|
||||
}
|
||||
|
||||
return propsDecls
|
||||
|
|
|
@ -140,7 +140,8 @@ interface ResolvedElements {
|
|||
export function resolveTypeElements(
|
||||
ctx: TypeResolveContext,
|
||||
node: Node & MaybeWithScope & { _resolvedElements?: ResolvedElements },
|
||||
scope?: TypeScope
|
||||
scope?: TypeScope,
|
||||
typeParameters?: Record<string, Node>
|
||||
): ResolvedElements {
|
||||
if (node._resolvedElements) {
|
||||
return node._resolvedElements
|
||||
|
@ -148,30 +149,37 @@ export function resolveTypeElements(
|
|||
return (node._resolvedElements = innerResolveTypeElements(
|
||||
ctx,
|
||||
node,
|
||||
node._ownerScope || scope || ctxToScope(ctx)
|
||||
node._ownerScope || scope || ctxToScope(ctx),
|
||||
typeParameters
|
||||
))
|
||||
}
|
||||
|
||||
function innerResolveTypeElements(
|
||||
ctx: TypeResolveContext,
|
||||
node: Node,
|
||||
scope: TypeScope
|
||||
scope: TypeScope,
|
||||
typeParameters?: Record<string, Node>
|
||||
): ResolvedElements {
|
||||
switch (node.type) {
|
||||
case 'TSTypeLiteral':
|
||||
return typeElementsToMap(ctx, node.members, scope)
|
||||
return typeElementsToMap(ctx, node.members, scope, typeParameters)
|
||||
case 'TSInterfaceDeclaration':
|
||||
return resolveInterfaceMembers(ctx, node, scope)
|
||||
return resolveInterfaceMembers(ctx, node, scope, typeParameters)
|
||||
case 'TSTypeAliasDeclaration':
|
||||
case 'TSParenthesizedType':
|
||||
return resolveTypeElements(ctx, node.typeAnnotation, scope)
|
||||
return resolveTypeElements(
|
||||
ctx,
|
||||
node.typeAnnotation,
|
||||
scope,
|
||||
typeParameters
|
||||
)
|
||||
case 'TSFunctionType': {
|
||||
return { props: {}, calls: [node] }
|
||||
}
|
||||
case 'TSUnionType':
|
||||
case 'TSIntersectionType':
|
||||
return mergeElements(
|
||||
node.types.map(t => resolveTypeElements(ctx, t, scope)),
|
||||
node.types.map(t => resolveTypeElements(ctx, t, scope, typeParameters)),
|
||||
node.type
|
||||
)
|
||||
case 'TSMappedType':
|
||||
|
@ -193,20 +201,57 @@ function innerResolveTypeElements(
|
|||
scope.imports[typeName]?.source === 'vue'
|
||||
) {
|
||||
return resolveExtractPropTypes(
|
||||
resolveTypeElements(ctx, node.typeParameters.params[0], scope),
|
||||
resolveTypeElements(
|
||||
ctx,
|
||||
node.typeParameters.params[0],
|
||||
scope,
|
||||
typeParameters
|
||||
),
|
||||
scope
|
||||
)
|
||||
}
|
||||
const resolved = resolveTypeReference(ctx, node, scope)
|
||||
if (resolved) {
|
||||
return resolveTypeElements(ctx, resolved, resolved._ownerScope)
|
||||
const typeParams: Record<string, Node> = Object.create(null)
|
||||
if (
|
||||
(resolved.type === 'TSTypeAliasDeclaration' ||
|
||||
resolved.type === 'TSInterfaceDeclaration') &&
|
||||
resolved.typeParameters &&
|
||||
node.typeParameters
|
||||
) {
|
||||
resolved.typeParameters.params.forEach((p, i) => {
|
||||
let param = typeParameters && typeParameters[p.name]
|
||||
if (!param) param = node.typeParameters!.params[i]
|
||||
typeParams[p.name] = param
|
||||
})
|
||||
}
|
||||
return resolveTypeElements(
|
||||
ctx,
|
||||
resolved,
|
||||
resolved._ownerScope,
|
||||
typeParams
|
||||
)
|
||||
} else {
|
||||
if (typeof typeName === 'string') {
|
||||
if (typeParameters && typeParameters[typeName]) {
|
||||
return resolveTypeElements(
|
||||
ctx,
|
||||
typeParameters[typeName],
|
||||
scope,
|
||||
typeParameters
|
||||
)
|
||||
}
|
||||
if (
|
||||
// @ts-ignore
|
||||
SupportedBuiltinsSet.has(typeName)
|
||||
) {
|
||||
return resolveBuiltin(ctx, node, typeName as any, scope)
|
||||
return resolveBuiltin(
|
||||
ctx,
|
||||
node,
|
||||
typeName as any,
|
||||
scope,
|
||||
typeParameters
|
||||
)
|
||||
} else if (typeName === 'ReturnType' && node.typeParameters) {
|
||||
// limited support, only reference types
|
||||
const ret = resolveReturnType(
|
||||
|
@ -265,11 +310,17 @@ function innerResolveTypeElements(
|
|||
function typeElementsToMap(
|
||||
ctx: TypeResolveContext,
|
||||
elements: TSTypeElement[],
|
||||
scope = ctxToScope(ctx)
|
||||
scope = ctxToScope(ctx),
|
||||
typeParameters?: Record<string, Node>
|
||||
): ResolvedElements {
|
||||
const res: ResolvedElements = { props: {} }
|
||||
for (const e of elements) {
|
||||
if (e.type === 'TSPropertySignature' || e.type === 'TSMethodSignature') {
|
||||
// capture generic parameters on node's scope
|
||||
if (typeParameters) {
|
||||
scope = createChildScope(scope)
|
||||
Object.assign(scope.types, typeParameters)
|
||||
}
|
||||
;(e as MaybeWithScope)._ownerScope = scope
|
||||
const name = getId(e.key)
|
||||
if (name && !e.computed) {
|
||||
|
@ -345,9 +396,15 @@ function createProperty(
|
|||
function resolveInterfaceMembers(
|
||||
ctx: TypeResolveContext,
|
||||
node: TSInterfaceDeclaration & MaybeWithScope,
|
||||
scope: TypeScope
|
||||
scope: TypeScope,
|
||||
typeParameters?: Record<string, Node>
|
||||
): ResolvedElements {
|
||||
const base = typeElementsToMap(ctx, node.body.body, node._ownerScope)
|
||||
const base = typeElementsToMap(
|
||||
ctx,
|
||||
node.body.body,
|
||||
node._ownerScope,
|
||||
typeParameters
|
||||
)
|
||||
if (node.extends) {
|
||||
for (const ext of node.extends) {
|
||||
if (
|
||||
|
@ -565,9 +622,15 @@ function resolveBuiltin(
|
|||
ctx: TypeResolveContext,
|
||||
node: TSTypeReference | TSExpressionWithTypeArguments,
|
||||
name: GetSetType<typeof SupportedBuiltinsSet>,
|
||||
scope: TypeScope
|
||||
scope: TypeScope,
|
||||
typeParameters?: Record<string, Node>
|
||||
): ResolvedElements {
|
||||
const t = resolveTypeElements(ctx, node.typeParameters!.params[0], scope)
|
||||
const t = resolveTypeElements(
|
||||
ctx,
|
||||
node.typeParameters!.params[0],
|
||||
scope,
|
||||
typeParameters
|
||||
)
|
||||
switch (name) {
|
||||
case 'Partial': {
|
||||
const res: ResolvedElements = { props: {}, calls: t.calls }
|
||||
|
@ -741,7 +804,25 @@ let loadTS: (() => typeof TS) | undefined
|
|||
* @private
|
||||
*/
|
||||
export function registerTS(_loadTS: () => typeof TS) {
|
||||
loadTS = _loadTS
|
||||
loadTS = () => {
|
||||
try {
|
||||
return _loadTS()
|
||||
} catch (err: any) {
|
||||
if (
|
||||
typeof err.message === 'string' &&
|
||||
err.message.includes('Cannot find module')
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to load TypeScript, which is required for resolving imported types. ' +
|
||||
'Please make sure "typescript" is installed as a project dependency.'
|
||||
)
|
||||
} else {
|
||||
throw new Error(
|
||||
'Failed to load TypeScript for resolving imported types.'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type FS = NonNullable<SFCScriptCompileOptions['fs']>
|
||||
|
@ -790,7 +871,12 @@ function importSourceToScope(
|
|||
scope: TypeScope,
|
||||
source: string
|
||||
): TypeScope {
|
||||
const fs = resolveFS(ctx)
|
||||
let fs: FS | undefined
|
||||
try {
|
||||
fs = resolveFS(ctx)
|
||||
} catch (err: any) {
|
||||
return ctx.error(err.message, node, scope)
|
||||
}
|
||||
if (!fs) {
|
||||
return ctx.error(
|
||||
`No fs option provided to \`compileScript\` in non-Node environment. ` +
|
||||
|
@ -1102,14 +1188,7 @@ function moduleDeclToScope(
|
|||
return node._resolvedChildScope
|
||||
}
|
||||
|
||||
const scope = new TypeScope(
|
||||
parentScope.filename,
|
||||
parentScope.source,
|
||||
parentScope.offset,
|
||||
Object.create(parentScope.imports),
|
||||
Object.create(parentScope.types),
|
||||
Object.create(parentScope.declares)
|
||||
)
|
||||
const scope = createChildScope(parentScope)
|
||||
|
||||
if (node.body.type === 'TSModuleDeclaration') {
|
||||
const decl = node.body as TSModuleDeclaration & WithScope
|
||||
|
@ -1123,6 +1202,17 @@ function moduleDeclToScope(
|
|||
return (node._resolvedChildScope = scope)
|
||||
}
|
||||
|
||||
function createChildScope(parentScope: TypeScope) {
|
||||
return new TypeScope(
|
||||
parentScope.filename,
|
||||
parentScope.source,
|
||||
parentScope.offset,
|
||||
Object.create(parentScope.imports),
|
||||
Object.create(parentScope.types),
|
||||
Object.create(parentScope.declares)
|
||||
)
|
||||
}
|
||||
|
||||
const importExportRE = /^Import|^Export/
|
||||
|
||||
function recordTypes(
|
||||
|
@ -1261,7 +1351,7 @@ function recordType(
|
|||
if (overwriteId || node.id) types[overwriteId || getId(node.id!)] = node
|
||||
break
|
||||
case 'TSTypeAliasDeclaration':
|
||||
types[node.id.name] = node.typeAnnotation
|
||||
types[node.id.name] = node.typeParameters ? node : node.typeAnnotation
|
||||
break
|
||||
case 'TSDeclareFunction':
|
||||
if (node.id) declares[node.id.name] = node
|
||||
|
|
|
@ -121,6 +121,8 @@ export function getEscapedPropName(key: string) {
|
|||
|
||||
export const cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
|
||||
|
||||
export function getEscapedCssVarName(key: string) {
|
||||
return key.replace(cssVarNameEscapeSymbolsRE, s => `\\${s}`)
|
||||
export function getEscapedCssVarName(key: string, doubleEscape: boolean) {
|
||||
return key.replace(cssVarNameEscapeSymbolsRE, s =>
|
||||
doubleEscape ? `\\\\${s}` : `\\${s}`
|
||||
)
|
||||
}
|
||||
|
|
|
@ -22,17 +22,25 @@ export function genCssVarsFromList(
|
|||
): string {
|
||||
return `{\n ${vars
|
||||
.map(
|
||||
key => `"${isSSR ? `--` : ``}${genVarName(id, key, isProd)}": (${key})`
|
||||
key =>
|
||||
`"${isSSR ? `--` : ``}${genVarName(id, key, isProd, isSSR)}": (${key})`
|
||||
)
|
||||
.join(',\n ')}\n}`
|
||||
}
|
||||
|
||||
function genVarName(id: string, raw: string, isProd: boolean): string {
|
||||
function genVarName(
|
||||
id: string,
|
||||
raw: string,
|
||||
isProd: boolean,
|
||||
isSSR = false
|
||||
): string {
|
||||
if (isProd) {
|
||||
return hash(id + raw)
|
||||
} else {
|
||||
// escape ASCII Punctuation & Symbols
|
||||
return `${id}-${getEscapedCssVarName(raw)}`
|
||||
// #7823 need to double-escape in SSR because the attributes are rendered
|
||||
// into an HTML string
|
||||
return `${id}-${getEscapedCssVarName(raw, isSSR)}`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -170,15 +170,23 @@ function rewriteSelector(
|
|||
}
|
||||
}
|
||||
|
||||
if (n.type !== 'pseudo' && n.type !== 'combinator') {
|
||||
if (
|
||||
(n.type !== 'pseudo' && n.type !== 'combinator') ||
|
||||
(n.type === 'pseudo' && (n.value === ':is' || n.value === ':where'))
|
||||
) {
|
||||
node = n
|
||||
}
|
||||
})
|
||||
|
||||
if (n.type === 'pseudo' && (n.value === ':is' || n.value === ':where')) {
|
||||
rewriteSelector(id, n.nodes[0], selectorRoot, slotted)
|
||||
if (node) {
|
||||
const { type, value } = node as selectorParser.Node
|
||||
if (type === 'pseudo' && (value === ':is' || value === ':where')) {
|
||||
;(node as selectorParser.Pseudo).nodes.forEach(value =>
|
||||
rewriteSelector(id, value, selectorRoot, slotted)
|
||||
)
|
||||
shouldInject = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (node) {
|
||||
;(node as selectorParser.Node).spaces.after = ''
|
||||
|
|
|
@ -11,7 +11,9 @@ import {
|
|||
h,
|
||||
SlotsType,
|
||||
Slots,
|
||||
VNode
|
||||
VNode,
|
||||
withKeys,
|
||||
withModifiers
|
||||
} from 'vue'
|
||||
import { describe, expectType, IsUnion } from './utils'
|
||||
|
||||
|
@ -1497,6 +1499,12 @@ describe('should work when props type is incompatible with setup returned type '
|
|||
expectType<SizeType>(CompA.$props.size)
|
||||
})
|
||||
|
||||
describe('withKeys and withModifiers as pro', () => {
|
||||
const onKeydown = withKeys(e => {}, [''])
|
||||
const onClick = withModifiers(e => {}, [''])
|
||||
;<input onKeydown={onKeydown} onClick={onClick} />
|
||||
})
|
||||
|
||||
import {
|
||||
DefineComponent,
|
||||
ComponentOptionsMixin,
|
||||
|
|
|
@ -45,7 +45,7 @@ Bar.emits = {
|
|||
Bar.emits = { baz: () => void 0 }
|
||||
|
||||
// TSX
|
||||
expectType<JSX.Element>(<Bar foo={1} />)
|
||||
expectType<JSX.Element>(<Bar foo={1} onUpdate={() => {}} />)
|
||||
// @ts-expect-error
|
||||
;<Foo />
|
||||
// @ts-expect-error
|
||||
|
|
|
@ -62,3 +62,31 @@ describe('should unwrap tuple correctly', () => {
|
|||
const reactiveTuple = reactive(tuple)
|
||||
expectType<Ref<number>>(reactiveTuple[0])
|
||||
})
|
||||
|
||||
describe('should unwrap Map correctly', () => {
|
||||
const map = reactive(new Map<string, Ref<number>>())
|
||||
expectType<Ref<number>>(map.get('a')!)
|
||||
|
||||
const map2 = reactive(new Map<string, { wrap: Ref<number> }>())
|
||||
expectType<number>(map2.get('a')!.wrap)
|
||||
|
||||
const wm = reactive(new WeakMap<object, Ref<number>>())
|
||||
expectType<Ref<number>>(wm.get({})!)
|
||||
|
||||
const wm2 = reactive(new WeakMap<object, { wrap: Ref<number> }>())
|
||||
expectType<number>(wm2.get({})!.wrap)
|
||||
})
|
||||
|
||||
describe('should unwrap Set correctly', () => {
|
||||
const set = reactive(new Set<Ref<number>>())
|
||||
expectType<Set<Ref<number>>>(set)
|
||||
|
||||
const set2 = reactive(new Set<{ wrap: Ref<number> }>())
|
||||
expectType<Set<{ wrap: number }>>(set2)
|
||||
|
||||
const ws = reactive(new WeakSet<Ref<number>>())
|
||||
expectType<WeakSet<Ref<number>>>(ws)
|
||||
|
||||
const ws2 = reactive(new WeakSet<{ wrap: Ref<number> }>())
|
||||
expectType<WeakSet<{ wrap: number }>>(ws2)
|
||||
})
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
|
||||
import { capitalize, hasOwn, hasChanged, toRawType, isMap } from '@vue/shared'
|
||||
|
||||
export type CollectionTypes = IterableCollections | WeakCollections
|
||||
type CollectionTypes = IterableCollections | WeakCollections
|
||||
|
||||
type IterableCollections = Map<any, any> | Set<any>
|
||||
type WeakCollections = WeakMap<any, any> | WeakSet<any>
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
isShallow
|
||||
} from './reactive'
|
||||
import type { ShallowReactiveMarker } from './reactive'
|
||||
import { CollectionTypes } from './collectionHandlers'
|
||||
import { createDep, Dep } from './dep'
|
||||
import { ComputedRefImpl } from './computed'
|
||||
import { getDepFromReactive } from './reactiveEffect'
|
||||
|
@ -505,16 +504,23 @@ export type UnwrapRef<T> = T extends ShallowRef<infer V>
|
|||
|
||||
export type UnwrapRefSimple<T> = T extends
|
||||
| Function
|
||||
| CollectionTypes
|
||||
| BaseTypes
|
||||
| Ref
|
||||
| RefUnwrapBailTypes[keyof RefUnwrapBailTypes]
|
||||
| { [RawSymbol]?: true }
|
||||
? T
|
||||
: T extends ReadonlyArray<any>
|
||||
? { [K in keyof T]: UnwrapRefSimple<T[K]> }
|
||||
: T extends object & { [ShallowReactiveMarker]?: never }
|
||||
? {
|
||||
[P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
|
||||
}
|
||||
: T
|
||||
: T extends Map<infer K, infer V>
|
||||
? Map<K, UnwrapRefSimple<V>>
|
||||
: T extends WeakMap<infer K, infer V>
|
||||
? WeakMap<K, UnwrapRefSimple<V>>
|
||||
: T extends Set<infer V>
|
||||
? Set<UnwrapRefSimple<V>>
|
||||
: T extends WeakSet<infer V>
|
||||
? WeakSet<UnwrapRefSimple<V>>
|
||||
: T extends ReadonlyArray<any>
|
||||
? { [K in keyof T]: UnwrapRefSimple<T[K]> }
|
||||
: T extends object & { [ShallowReactiveMarker]?: never }
|
||||
? {
|
||||
[P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
|
||||
}
|
||||
: T
|
||||
|
|
|
@ -50,7 +50,8 @@ import {
|
|||
ObjectEmitsOptions,
|
||||
EmitFn,
|
||||
emit,
|
||||
normalizeEmitsOptions
|
||||
normalizeEmitsOptions,
|
||||
EmitsToProps
|
||||
} from './componentEmits'
|
||||
import {
|
||||
EMPTY_OBJ,
|
||||
|
@ -131,7 +132,7 @@ export interface FunctionalComponent<
|
|||
> extends ComponentInternalOptions {
|
||||
// use of any here is intentional so it can be a valid JSX Element constructor
|
||||
(
|
||||
props: P,
|
||||
props: P & EmitsToProps<E>,
|
||||
ctx: Omit<SetupContext<E, IfAny<S, {}, SlotsType<S>>>, 'expose'>
|
||||
): any
|
||||
props?: ComponentPropsOptions<P>
|
||||
|
|
|
@ -504,7 +504,12 @@ function createSuspenseBoundary(
|
|||
if (delayEnter) {
|
||||
activeBranch!.transition!.afterLeave = () => {
|
||||
if (pendingId === suspense.pendingId) {
|
||||
move(pendingBranch!, container, anchor, MoveType.ENTER)
|
||||
move(
|
||||
pendingBranch!,
|
||||
container,
|
||||
next(activeBranch!),
|
||||
MoveType.ENTER
|
||||
)
|
||||
queuePostFlushCb(effects)
|
||||
}
|
||||
}
|
||||
|
@ -577,7 +582,6 @@ function createSuspenseBoundary(
|
|||
// invoke @fallback event
|
||||
triggerEvent(vnode, 'onFallback')
|
||||
|
||||
const anchor = next(activeBranch!)
|
||||
const mountFallback = () => {
|
||||
if (!suspense.isInFallback) {
|
||||
return
|
||||
|
@ -587,7 +591,7 @@ function createSuspenseBoundary(
|
|||
null,
|
||||
fallbackVNode,
|
||||
container,
|
||||
anchor,
|
||||
next(activeBranch!),
|
||||
parentComponent,
|
||||
null, // fallback tree will not have suspense context
|
||||
isSVG,
|
||||
|
|
|
@ -11,9 +11,9 @@ export function initCustomFormatter() {
|
|||
}
|
||||
|
||||
const vueStyle = { style: 'color:#3ba776' }
|
||||
const numberStyle = { style: 'color:#0b1bc9' }
|
||||
const stringStyle = { style: 'color:#b62e24' }
|
||||
const keywordStyle = { style: 'color:#9d288c' }
|
||||
const numberStyle = { style: 'color:#1677ff' }
|
||||
const stringStyle = { style: 'color:#f5222d' }
|
||||
const keywordStyle = { style: 'color:#eb2f96' }
|
||||
|
||||
// custom formatter for Chrome
|
||||
// https://www.mattzeunert.com/2016/02/19/custom-chrome-devtools-object-formatters.html
|
||||
|
|
|
@ -291,6 +291,15 @@ describe('runtime-dom: props patching', () => {
|
|||
expect(el.value).toBe('baz')
|
||||
})
|
||||
|
||||
// #8780
|
||||
test('embedded tag with width and height', () => {
|
||||
// Width and height of some embedded element such as img、video、source、canvas
|
||||
// must be set as attribute
|
||||
const el = document.createElement('img')
|
||||
patchProp(el, 'width', null, '24px')
|
||||
expect(el.getAttribute('width')).toBe('24px')
|
||||
})
|
||||
|
||||
test('translate attribute', () => {
|
||||
const el = document.createElement('div')
|
||||
patchProp(el, 'translate', null, 'no')
|
||||
|
|
|
@ -32,14 +32,22 @@ const modifierGuards: Record<
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
export const withModifiers = (fn: Function, modifiers: string[]) => {
|
||||
return (event: Event, ...args: unknown[]) => {
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const guard = modifierGuards[modifiers[i]]
|
||||
if (guard && guard(event, modifiers)) return
|
||||
}
|
||||
return fn(event, ...args)
|
||||
}
|
||||
export const withModifiers = <
|
||||
T extends (event: Event, ...args: unknown[]) => any
|
||||
>(
|
||||
fn: T & { _withMods?: T },
|
||||
modifiers: string[]
|
||||
) => {
|
||||
return (
|
||||
fn._withMods ||
|
||||
(fn._withMods = ((event, ...args) => {
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const guard = modifierGuards[modifiers[i]]
|
||||
if (guard && guard(event, modifiers)) return
|
||||
}
|
||||
return fn(event, ...args)
|
||||
}) as T)
|
||||
)
|
||||
}
|
||||
|
||||
// Kept for 2.x compat.
|
||||
|
@ -57,7 +65,10 @@ const keyNames: Record<string, string | string[]> = {
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
export const withKeys = (fn: Function, modifiers: string[]) => {
|
||||
export const withKeys = <T extends (event: KeyboardEvent) => any>(
|
||||
fn: T & { _withKeys?: T },
|
||||
modifiers: string[]
|
||||
) => {
|
||||
let globalKeyCodes: LegacyConfig['keyCodes']
|
||||
let instance: ComponentInternalInstance | null = null
|
||||
if (__COMPAT__) {
|
||||
|
@ -77,40 +88,43 @@ export const withKeys = (fn: Function, modifiers: string[]) => {
|
|||
}
|
||||
}
|
||||
|
||||
return (event: KeyboardEvent) => {
|
||||
if (!('key' in event)) {
|
||||
return
|
||||
}
|
||||
return (
|
||||
fn._withKeys ||
|
||||
(fn._withKeys = (event => {
|
||||
if (!('key' in event)) {
|
||||
return
|
||||
}
|
||||
|
||||
const eventKey = hyphenate(event.key)
|
||||
if (modifiers.some(k => k === eventKey || keyNames[k] === eventKey)) {
|
||||
return fn(event)
|
||||
}
|
||||
|
||||
if (__COMPAT__) {
|
||||
const keyCode = String(event.keyCode)
|
||||
if (
|
||||
compatUtils.isCompatEnabled(
|
||||
DeprecationTypes.V_ON_KEYCODE_MODIFIER,
|
||||
instance
|
||||
) &&
|
||||
modifiers.some(mod => mod == keyCode)
|
||||
) {
|
||||
const eventKey = hyphenate(event.key)
|
||||
if (modifiers.some(k => k === eventKey || keyNames[k] === eventKey)) {
|
||||
return fn(event)
|
||||
}
|
||||
if (globalKeyCodes) {
|
||||
for (const mod of modifiers) {
|
||||
const codes = globalKeyCodes[mod]
|
||||
if (codes) {
|
||||
const matches = isArray(codes)
|
||||
? codes.some(code => String(code) === keyCode)
|
||||
: String(codes) === keyCode
|
||||
if (matches) {
|
||||
return fn(event)
|
||||
|
||||
if (__COMPAT__) {
|
||||
const keyCode = String(event.keyCode)
|
||||
if (
|
||||
compatUtils.isCompatEnabled(
|
||||
DeprecationTypes.V_ON_KEYCODE_MODIFIER,
|
||||
instance
|
||||
) &&
|
||||
modifiers.some(mod => mod == keyCode)
|
||||
) {
|
||||
return fn(event)
|
||||
}
|
||||
if (globalKeyCodes) {
|
||||
for (const mod of modifiers) {
|
||||
const codes = globalKeyCodes[mod]
|
||||
if (codes) {
|
||||
const matches = isArray(codes)
|
||||
? codes.some(code => String(code) === keyCode)
|
||||
: String(codes) === keyCode
|
||||
if (matches) {
|
||||
return fn(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}) as T)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,12 @@ import { patchEvent } from './modules/events'
|
|||
import { isOn, isString, isFunction, isModelListener } from '@vue/shared'
|
||||
import { RendererOptions } from '@vue/runtime-core'
|
||||
|
||||
const nativeOnRE = /^on[a-z]/
|
||||
const isNativeOn = (key: string) =>
|
||||
key.charCodeAt(0) === 111 /* o */ &&
|
||||
key.charCodeAt(1) === 110 /* n */ &&
|
||||
// lowercase letter
|
||||
key.charCodeAt(2) > 96 &&
|
||||
key.charCodeAt(2) < 123
|
||||
|
||||
type DOMRendererOptions = RendererOptions<Node, Element>
|
||||
|
||||
|
@ -73,7 +78,7 @@ function shouldSetAsProp(
|
|||
return true
|
||||
}
|
||||
// or native onclick with function values
|
||||
if (key in el && nativeOnRE.test(key) && isFunction(value)) {
|
||||
if (key in el && isNativeOn(key) && isFunction(value)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -105,8 +110,19 @@ function shouldSetAsProp(
|
|||
return false
|
||||
}
|
||||
|
||||
// #8780 the width or heigth of embedded tags must be set as attribute
|
||||
if (key === 'width' || key === 'height') {
|
||||
const tag = el.tagName
|
||||
return !(
|
||||
tag === 'IMG' ||
|
||||
tag === 'VIDEO' ||
|
||||
tag === 'CANVAS' ||
|
||||
tag === 'SOURCE'
|
||||
)
|
||||
}
|
||||
|
||||
// native onclick with string value, must be set as attribute
|
||||
if (nativeOnRE.test(key) && isString(value)) {
|
||||
if (isNativeOn(key) && isString(value)) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,10 @@ import {
|
|||
renderSlot,
|
||||
onErrorCaptured,
|
||||
onServerPrefetch,
|
||||
getCurrentInstance
|
||||
getCurrentInstance,
|
||||
reactive,
|
||||
computed,
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
import { escapeHtml } from '@vue/shared'
|
||||
import { renderToString } from '../src/renderToString'
|
||||
|
@ -1140,5 +1143,47 @@ function testRender(type: string, render: typeof renderToString) {
|
|||
expect(renderError).toBe(null)
|
||||
expect((capturedError as unknown as Error).message).toBe('An error')
|
||||
})
|
||||
|
||||
test('computed reactivity during SSR with onServerPrefetch', async () => {
|
||||
const store = {
|
||||
// initial state could be hydrated
|
||||
state: reactive({ items: null as null | string[] }),
|
||||
|
||||
// pretend to fetch some data from an api
|
||||
async fetchData() {
|
||||
this.state.items = ['hello', 'world']
|
||||
}
|
||||
}
|
||||
|
||||
const getterSpy = vi.fn()
|
||||
|
||||
const App = defineComponent(() => {
|
||||
const msg = computed(() => {
|
||||
getterSpy()
|
||||
return store.state.items?.join(' ')
|
||||
})
|
||||
|
||||
// If msg value is falsy then we are either in ssr context or on the client
|
||||
// and the initial state was not modified/hydrated.
|
||||
// In both cases we need to fetch data.
|
||||
onServerPrefetch(() => store.fetchData())
|
||||
|
||||
// simulate the read from a composable (e.g. filtering a list of results)
|
||||
msg.value
|
||||
|
||||
return () => h('div', null, msg.value)
|
||||
})
|
||||
|
||||
const app = createSSRApp(App)
|
||||
|
||||
// in real world serve this html and append store state for hydration on client
|
||||
const html = await renderToString(app)
|
||||
|
||||
expect(html).toMatch('hello world')
|
||||
|
||||
// should only be called twice since access should be cached
|
||||
// during the render phase
|
||||
expect(getterSpy).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ test('computed reactivity during SSR', async () => {
|
|||
// In both cases we need to fetch data.
|
||||
if (!msg.value) await store.fetchData()
|
||||
|
||||
expect(msg.value).toBe('hello world')
|
||||
return () => h('div', null, msg.value + msg.value + msg.value)
|
||||
})
|
||||
|
||||
|
|
|
@ -144,7 +144,10 @@ function renderComponentSubTree(
|
|||
// perf: enable caching of computed getters during render
|
||||
// since there cannot be state mutations during render.
|
||||
for (const e of instance.scope.effects) {
|
||||
if (e.computed) e.computed._cacheable = true
|
||||
if (e.computed) {
|
||||
e.computed._dirty = true
|
||||
e.computed._cacheable = true
|
||||
}
|
||||
}
|
||||
|
||||
const ssrRender = instance.ssrRender || comp.ssrRender
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"vite": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/repl": "^2.7.0",
|
||||
"@vue/repl": "^3.0.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"jszip": "^3.10.1",
|
||||
"vue": "workspace:*"
|
||||
|
|
|
@ -1,8 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import Header from './Header.vue'
|
||||
import { Repl, ReplStore, SFCOptions } from '@vue/repl'
|
||||
import Monaco from '@vue/repl/monaco-editor'
|
||||
import type Monaco from '@vue/repl/monaco-editor'
|
||||
import type CodeMirror from '@vue/repl/codemirror-editor'
|
||||
import { ref, watchEffect, onMounted } from 'vue'
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
const EditorComponent = shallowRef<typeof Monaco | typeof CodeMirror>()
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
import('@vue/repl/codemirror-editor').then(
|
||||
mod => (EditorComponent.value = mod.default)
|
||||
)
|
||||
} else {
|
||||
import('@vue/repl/monaco-editor').then(
|
||||
mod => (EditorComponent.value = mod.default)
|
||||
)
|
||||
}
|
||||
|
||||
const setVH = () => {
|
||||
document.documentElement.style.setProperty('--vh', window.innerHeight + `px`)
|
||||
|
@ -97,8 +111,9 @@ onMounted(() => {
|
|||
@toggle-ssr="toggleSSR"
|
||||
/>
|
||||
<Repl
|
||||
v-if="EditorComponent"
|
||||
:theme="theme"
|
||||
:editor="Monaco"
|
||||
:editor="EditorComponent"
|
||||
@keydown.ctrl.s.prevent
|
||||
@keydown.meta.s.prevent
|
||||
:ssr="useSSRMode"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import '@vue/repl/style.css'
|
||||
|
||||
// @ts-expect-error Custom window property
|
||||
window.VUE_DEVTOOLS_CONFIG = {
|
||||
|
|
|
@ -12,8 +12,11 @@ export const NOOP = () => {}
|
|||
*/
|
||||
export const NO = () => false
|
||||
|
||||
const onRE = /^on[^a-z]/
|
||||
export const isOn = (key: string) => onRE.test(key)
|
||||
export const isOn = (key: string) =>
|
||||
key.charCodeAt(0) === 111 /* o */ &&
|
||||
key.charCodeAt(1) === 110 /* n */ &&
|
||||
// uppercase letter
|
||||
(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97)
|
||||
|
||||
export const isModelListener = (key: string) => key.startsWith('onUpdate:')
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
--bg: #1D1F21;
|
||||
--border: #333;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
},
|
||||
"homepage": "https://github.com/vuejs/core/tree/main/packages/vue-compat#readme",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.4",
|
||||
"@babel/parser": "^7.23.5",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
|
|
|
@ -1586,6 +1586,72 @@ describe('e2e: Transition', () => {
|
|||
expect(barMountSpy).toBeCalledTimes(1)
|
||||
expect(barMountSpy).toHaveBeenNthCalledWith(1, true, false, true)
|
||||
})
|
||||
|
||||
// #8105
|
||||
test(
|
||||
'trigger again when transition is not finished',
|
||||
async () => {
|
||||
await page().evaluate(duration => {
|
||||
const { createApp, shallowRef, h } = (window as any).Vue
|
||||
const One = {
|
||||
async setup() {
|
||||
return () => h('div', { class: 'test' }, 'one')
|
||||
}
|
||||
}
|
||||
const Two = {
|
||||
async setup() {
|
||||
return () => h('div', { class: 'test' }, 'two')
|
||||
}
|
||||
}
|
||||
createApp({
|
||||
template: `
|
||||
<div id="container">
|
||||
<transition name="test" mode="out-in" duration="${duration}">
|
||||
<Suspense>
|
||||
<component :is="view"/>
|
||||
</Suspense>
|
||||
</transition>
|
||||
</div>
|
||||
<button id="toggleBtn" @click="click">button</button>
|
||||
`,
|
||||
setup: () => {
|
||||
const view = shallowRef(One)
|
||||
const click = () => {
|
||||
view.value = view.value === One ? Two : One
|
||||
}
|
||||
return { view, click }
|
||||
}
|
||||
}).mount('#app')
|
||||
}, duration)
|
||||
|
||||
await nextFrame()
|
||||
expect(await html('#container')).toBe(
|
||||
'<div class="test test-enter-active test-enter-to">one</div>'
|
||||
)
|
||||
|
||||
await transitionFinish()
|
||||
expect(await html('#container')).toBe('<div class="test">one</div>')
|
||||
|
||||
// trigger twice
|
||||
classWhenTransitionStart()
|
||||
classWhenTransitionStart()
|
||||
await nextFrame()
|
||||
expect(await html('#container')).toBe(
|
||||
'<div class="test test-leave-active test-leave-to">one</div>'
|
||||
)
|
||||
|
||||
await transitionFinish()
|
||||
await nextFrame()
|
||||
expect(await html('#container')).toBe(
|
||||
'<div class="test test-enter-active test-enter-to">one</div>'
|
||||
)
|
||||
|
||||
await transitionFinish()
|
||||
await nextFrame()
|
||||
expect(await html('#container')).toBe('<div class="test">one</div>')
|
||||
},
|
||||
E2E_TIMEOUT
|
||||
)
|
||||
})
|
||||
|
||||
describe('transition with v-show', () => {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
if (typeof require !== 'undefined') {
|
||||
try {
|
||||
require('@vue/compiler-sfc').registerTS(() => require('typescript'))
|
||||
} catch (e) {}
|
||||
require('@vue/compiler-sfc').registerTS(() => require('typescript'))
|
||||
}
|
||||
|
|
|
@ -4,14 +4,32 @@ import { initDev } from './dev'
|
|||
import { compile, CompilerOptions, CompilerError } from '@vue/compiler-dom'
|
||||
import { registerRuntimeCompiler, RenderFunction, warn } from '@vue/runtime-dom'
|
||||
import * as runtimeDom from '@vue/runtime-dom'
|
||||
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
|
||||
import {
|
||||
isString,
|
||||
NOOP,
|
||||
generateCodeFrame,
|
||||
extend,
|
||||
EMPTY_OBJ
|
||||
} from '@vue/shared'
|
||||
import { InternalRenderFunction } from 'packages/runtime-core/src/component'
|
||||
|
||||
if (__DEV__) {
|
||||
initDev()
|
||||
}
|
||||
|
||||
const compileCache: Record<string, RenderFunction> = Object.create(null)
|
||||
const compileCache = new WeakMap<
|
||||
CompilerOptions,
|
||||
Record<string, RenderFunction>
|
||||
>()
|
||||
|
||||
function getCache(options?: CompilerOptions) {
|
||||
let c = compileCache.get(options ?? EMPTY_OBJ)
|
||||
if (!c) {
|
||||
c = Object.create(null) as Record<string, RenderFunction>
|
||||
compileCache.set(options ?? EMPTY_OBJ, c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
function compileToFunction(
|
||||
template: string | HTMLElement,
|
||||
|
@ -27,7 +45,8 @@ function compileToFunction(
|
|||
}
|
||||
|
||||
const key = template
|
||||
const cached = compileCache[key]
|
||||
const cache = getCache(options)
|
||||
const cached = cache[key]
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
|
@ -84,7 +103,7 @@ function compileToFunction(
|
|||
// mark the function as runtime compiled
|
||||
;(render as InternalRenderFunction)._rc = true
|
||||
|
||||
return (compileCache[key] = render)
|
||||
return (cache[key] = render)
|
||||
}
|
||||
|
||||
registerRuntimeCompiler(compileToFunction)
|
||||
|
|
255
pnpm-lock.yaml
255
pnpm-lock.yaml
|
@ -9,11 +9,11 @@ importers:
|
|||
.:
|
||||
devDependencies:
|
||||
'@babel/parser':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
'@babel/types':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
'@rollup/plugin-alias':
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1(rollup@4.1.4)
|
||||
|
@ -39,8 +39,8 @@ importers:
|
|||
specifier: ^1.2.5
|
||||
version: 1.2.5
|
||||
'@types/node':
|
||||
specifier: ^20.10.0
|
||||
version: 20.10.0
|
||||
specifier: ^20.10.3
|
||||
version: 20.10.3
|
||||
'@types/semver':
|
||||
specifier: ^7.5.5
|
||||
version: 7.5.5
|
||||
|
@ -117,8 +117,8 @@ importers:
|
|||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
puppeteer:
|
||||
specifier: ~21.5.1
|
||||
version: 21.5.1(typescript@5.2.2)
|
||||
specifier: ~21.5.2
|
||||
version: 21.5.2(typescript@5.2.2)
|
||||
rimraf:
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.5
|
||||
|
@ -153,14 +153,14 @@ importers:
|
|||
specifier: ^2.6.2
|
||||
version: 2.6.2
|
||||
tsx:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0
|
||||
specifier: ^4.6.2
|
||||
version: 4.6.2
|
||||
typescript:
|
||||
specifier: ^5.2.2
|
||||
version: 5.2.2
|
||||
vite:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0(@types/node@20.10.0)(terser@5.22.0)
|
||||
version: 5.0.0(@types/node@20.10.3)(terser@5.22.0)
|
||||
vitest:
|
||||
specifier: ^0.34.6
|
||||
version: 0.34.6(jsdom@22.1.0)(terser@5.22.0)
|
||||
|
@ -168,8 +168,8 @@ importers:
|
|||
packages/compiler-core:
|
||||
dependencies:
|
||||
'@babel/parser':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
'@vue/shared':
|
||||
specifier: workspace:*
|
||||
version: link:../shared
|
||||
|
@ -184,8 +184,8 @@ importers:
|
|||
version: 1.0.2
|
||||
devDependencies:
|
||||
'@babel/types':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
|
||||
packages/compiler-dom:
|
||||
dependencies:
|
||||
|
@ -199,8 +199,8 @@ importers:
|
|||
packages/compiler-sfc:
|
||||
dependencies:
|
||||
'@babel/parser':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
'@vue/compiler-core':
|
||||
specifier: workspace:*
|
||||
version: link:../compiler-core
|
||||
|
@ -220,15 +220,15 @@ importers:
|
|||
specifier: ^0.30.5
|
||||
version: 0.30.5
|
||||
postcss:
|
||||
specifier: ^8.4.31
|
||||
version: 8.4.31
|
||||
specifier: ^8.4.32
|
||||
version: 8.4.32
|
||||
source-map-js:
|
||||
specifier: ^1.0.2
|
||||
version: 1.0.2
|
||||
devDependencies:
|
||||
'@babel/types':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
'@vue/consolidate':
|
||||
specifier: ^0.17.3
|
||||
version: 0.17.3
|
||||
|
@ -246,7 +246,7 @@ importers:
|
|||
version: 9.0.3
|
||||
postcss-modules:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(postcss@8.4.31)
|
||||
version: 6.0.0(postcss@8.4.32)
|
||||
postcss-selector-parser:
|
||||
specifier: ^6.0.13
|
||||
version: 6.0.13
|
||||
|
@ -338,8 +338,8 @@ importers:
|
|||
packages/sfc-playground:
|
||||
dependencies:
|
||||
'@vue/repl':
|
||||
specifier: ^2.7.0
|
||||
version: 2.7.0
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
file-saver:
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5
|
||||
|
@ -355,7 +355,7 @@ importers:
|
|||
version: 4.4.0(vite@5.0.0)(vue@packages+vue)
|
||||
vite:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0(@types/node@20.10.0)(terser@5.22.0)
|
||||
version: 5.0.0(@types/node@20.10.3)(terser@5.22.0)
|
||||
|
||||
packages/shared: {}
|
||||
|
||||
|
@ -392,8 +392,8 @@ importers:
|
|||
packages/vue-compat:
|
||||
dependencies:
|
||||
'@babel/parser':
|
||||
specifier: ^7.23.4
|
||||
version: 7.23.4
|
||||
specifier: ^7.23.5
|
||||
version: 7.23.5
|
||||
estree-walker:
|
||||
specifier: ^2.0.2
|
||||
version: 2.0.2
|
||||
|
@ -428,25 +428,33 @@ packages:
|
|||
chalk: 2.4.2
|
||||
dev: true
|
||||
|
||||
/@babel/code-frame@7.23.5:
|
||||
resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/highlight': 7.23.4
|
||||
chalk: 2.4.2
|
||||
dev: true
|
||||
|
||||
/@babel/compat-data@7.23.2:
|
||||
resolution: {integrity: sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/core@7.23.3:
|
||||
resolution: {integrity: sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==}
|
||||
/@babel/core@7.23.5:
|
||||
resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.2.1
|
||||
'@babel/code-frame': 7.22.13
|
||||
'@babel/generator': 7.23.3
|
||||
'@babel/code-frame': 7.23.5
|
||||
'@babel/generator': 7.23.5
|
||||
'@babel/helper-compilation-targets': 7.22.15
|
||||
'@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.3)
|
||||
'@babel/helpers': 7.23.2
|
||||
'@babel/parser': 7.23.4
|
||||
'@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
|
||||
'@babel/helpers': 7.23.5
|
||||
'@babel/parser': 7.23.5
|
||||
'@babel/template': 7.22.15
|
||||
'@babel/traverse': 7.23.3
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/traverse': 7.23.5
|
||||
'@babel/types': 7.23.5
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.3.4
|
||||
gensync: 1.0.0-beta.2
|
||||
|
@ -456,11 +464,11 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/generator@7.23.3:
|
||||
resolution: {integrity: sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==}
|
||||
/@babel/generator@7.23.5:
|
||||
resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
'@jridgewell/gen-mapping': 0.3.3
|
||||
'@jridgewell/trace-mapping': 0.3.20
|
||||
jsesc: 2.5.2
|
||||
|
@ -487,30 +495,30 @@ packages:
|
|||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/template': 7.22.15
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/helper-hoist-variables@7.22.5:
|
||||
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/helper-module-imports@7.22.15:
|
||||
resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/helper-module-transforms@7.23.3(@babel/core@7.23.3):
|
||||
/@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5):
|
||||
resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.3
|
||||
'@babel/core': 7.23.5
|
||||
'@babel/helper-environment-visitor': 7.22.20
|
||||
'@babel/helper-module-imports': 7.22.15
|
||||
'@babel/helper-simple-access': 7.22.5
|
||||
|
@ -522,14 +530,14 @@ packages:
|
|||
resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/helper-split-export-declaration@7.22.6:
|
||||
resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/helper-string-parser@7.23.4:
|
||||
|
@ -546,13 +554,13 @@ packages:
|
|||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helpers@7.23.2:
|
||||
resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==}
|
||||
/@babel/helpers@7.23.5:
|
||||
resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/template': 7.22.15
|
||||
'@babel/traverse': 7.23.3
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/traverse': 7.23.5
|
||||
'@babel/types': 7.23.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
@ -567,42 +575,51 @@ packages:
|
|||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
|
||||
/@babel/parser@7.23.4:
|
||||
resolution: {integrity: sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==}
|
||||
/@babel/highlight@7.23.4:
|
||||
resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.22.20
|
||||
chalk: 2.4.2
|
||||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
|
||||
/@babel/parser@7.23.5:
|
||||
resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
|
||||
/@babel/template@7.22.15:
|
||||
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.22.13
|
||||
'@babel/parser': 7.23.4
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/code-frame': 7.23.5
|
||||
'@babel/parser': 7.23.5
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/traverse@7.23.3:
|
||||
resolution: {integrity: sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==}
|
||||
/@babel/traverse@7.23.5:
|
||||
resolution: {integrity: sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.22.13
|
||||
'@babel/generator': 7.23.3
|
||||
'@babel/code-frame': 7.23.5
|
||||
'@babel/generator': 7.23.5
|
||||
'@babel/helper-environment-visitor': 7.22.20
|
||||
'@babel/helper-function-name': 7.23.0
|
||||
'@babel/helper-hoist-variables': 7.22.5
|
||||
'@babel/helper-split-export-declaration': 7.22.6
|
||||
'@babel/parser': 7.23.4
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/parser': 7.23.5
|
||||
'@babel/types': 7.23.5
|
||||
debug: 4.3.4
|
||||
globals: 11.12.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/types@7.23.4:
|
||||
resolution: {integrity: sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==}
|
||||
/@babel/types@7.23.5:
|
||||
resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.23.4
|
||||
|
@ -1527,8 +1544,8 @@ packages:
|
|||
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
|
||||
dev: true
|
||||
|
||||
/@types/node@20.10.0:
|
||||
resolution: {integrity: sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==}
|
||||
/@types/node@20.10.3:
|
||||
resolution: {integrity: sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==}
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
dev: true
|
||||
|
@ -1549,7 +1566,7 @@ packages:
|
|||
resolution: {integrity: sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@types/node': 20.10.0
|
||||
'@types/node': 20.10.3
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
|
@ -1689,7 +1706,7 @@ packages:
|
|||
vite: ^4.0.0
|
||||
vue: ^3.2.25
|
||||
dependencies:
|
||||
vite: 5.0.0(@types/node@20.10.0)(terser@5.22.0)
|
||||
vite: 5.0.0(@types/node@20.10.3)(terser@5.22.0)
|
||||
vue: link:packages/vue
|
||||
dev: true
|
||||
|
||||
|
@ -1753,8 +1770,8 @@ packages:
|
|||
engines: {node: '>= 0.12.0'}
|
||||
dev: true
|
||||
|
||||
/@vue/repl@2.7.0:
|
||||
resolution: {integrity: sha512-zzyb+tVvzmOePv8Gp4sefP/7CKidx4WiJDfKPP698b9bN5jSFtmSOg4nvPoJEE1ICKeAEgdRKVneYJ8Mp7C/WA==}
|
||||
/@vue/repl@3.0.0:
|
||||
resolution: {integrity: sha512-tGYibiftMo5yEuIKPWVsNuuNDejjJk0JQmvKtTm12KNLFqtGD7fWoGv1qUzcN9EAxwVeDgnT9ljRgqGVgZkyEg==}
|
||||
dev: false
|
||||
|
||||
/@zeit/schemas@2.29.0:
|
||||
|
@ -1983,7 +2000,7 @@ packages:
|
|||
resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/balanced-match@1.0.2:
|
||||
|
@ -2304,8 +2321,8 @@ packages:
|
|||
/constantinople@4.0.1:
|
||||
resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==}
|
||||
dependencies:
|
||||
'@babel/parser': 7.23.4
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/parser': 7.23.5
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/content-disposition@0.5.2:
|
||||
|
@ -3520,13 +3537,13 @@ packages:
|
|||
safer-buffer: 2.1.2
|
||||
dev: true
|
||||
|
||||
/icss-utils@5.1.0(postcss@8.4.31):
|
||||
/icss-utils@5.1.0(postcss@8.4.32):
|
||||
resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
postcss: 8.4.31
|
||||
postcss: 8.4.32
|
||||
dev: true
|
||||
|
||||
/ieee754@1.2.1:
|
||||
|
@ -3823,8 +3840,8 @@ packages:
|
|||
resolution: {integrity: sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
'@babel/core': 7.23.3
|
||||
'@babel/parser': 7.23.4
|
||||
'@babel/core': 7.23.5
|
||||
'@babel/parser': 7.23.5
|
||||
'@istanbuljs/schema': 0.1.3
|
||||
istanbul-lib-coverage: 3.2.0
|
||||
semver: 7.5.4
|
||||
|
@ -4298,8 +4315,8 @@ packages:
|
|||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
dev: true
|
||||
|
||||
/nanoid@3.3.6:
|
||||
resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
|
||||
/nanoid@3.3.7:
|
||||
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
|
@ -4666,60 +4683,60 @@ packages:
|
|||
pathe: 1.1.1
|
||||
dev: true
|
||||
|
||||
/postcss-modules-extract-imports@3.0.0(postcss@8.4.31):
|
||||
/postcss-modules-extract-imports@3.0.0(postcss@8.4.32):
|
||||
resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
postcss: 8.4.31
|
||||
postcss: 8.4.32
|
||||
dev: true
|
||||
|
||||
/postcss-modules-local-by-default@4.0.3(postcss@8.4.31):
|
||||
/postcss-modules-local-by-default@4.0.3(postcss@8.4.32):
|
||||
resolution: {integrity: sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
icss-utils: 5.1.0(postcss@8.4.31)
|
||||
postcss: 8.4.31
|
||||
icss-utils: 5.1.0(postcss@8.4.32)
|
||||
postcss: 8.4.32
|
||||
postcss-selector-parser: 6.0.13
|
||||
postcss-value-parser: 4.2.0
|
||||
dev: true
|
||||
|
||||
/postcss-modules-scope@3.0.0(postcss@8.4.31):
|
||||
/postcss-modules-scope@3.0.0(postcss@8.4.32):
|
||||
resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
postcss: 8.4.31
|
||||
postcss: 8.4.32
|
||||
postcss-selector-parser: 6.0.13
|
||||
dev: true
|
||||
|
||||
/postcss-modules-values@4.0.0(postcss@8.4.31):
|
||||
/postcss-modules-values@4.0.0(postcss@8.4.32):
|
||||
resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
icss-utils: 5.1.0(postcss@8.4.31)
|
||||
postcss: 8.4.31
|
||||
icss-utils: 5.1.0(postcss@8.4.32)
|
||||
postcss: 8.4.32
|
||||
dev: true
|
||||
|
||||
/postcss-modules@6.0.0(postcss@8.4.31):
|
||||
/postcss-modules@6.0.0(postcss@8.4.32):
|
||||
resolution: {integrity: sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==}
|
||||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
dependencies:
|
||||
generic-names: 4.0.0
|
||||
icss-utils: 5.1.0(postcss@8.4.31)
|
||||
icss-utils: 5.1.0(postcss@8.4.32)
|
||||
lodash.camelcase: 4.3.0
|
||||
postcss: 8.4.31
|
||||
postcss-modules-extract-imports: 3.0.0(postcss@8.4.31)
|
||||
postcss-modules-local-by-default: 4.0.3(postcss@8.4.31)
|
||||
postcss-modules-scope: 3.0.0(postcss@8.4.31)
|
||||
postcss-modules-values: 4.0.0(postcss@8.4.31)
|
||||
postcss: 8.4.32
|
||||
postcss-modules-extract-imports: 3.0.0(postcss@8.4.32)
|
||||
postcss-modules-local-by-default: 4.0.3(postcss@8.4.32)
|
||||
postcss-modules-scope: 3.0.0(postcss@8.4.32)
|
||||
postcss-modules-values: 4.0.0(postcss@8.4.32)
|
||||
string-hash: 1.1.3
|
||||
dev: true
|
||||
|
||||
|
@ -4735,11 +4752,11 @@ packages:
|
|||
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
|
||||
dev: true
|
||||
|
||||
/postcss@8.4.31:
|
||||
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
|
||||
/postcss@8.4.32:
|
||||
resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
dependencies:
|
||||
nanoid: 3.3.6
|
||||
nanoid: 3.3.7
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
|
||||
|
@ -4914,9 +4931,9 @@ packages:
|
|||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/puppeteer-core@21.5.1:
|
||||
resolution: {integrity: sha512-u6c3SZKAOaOQogaTkQvllxT/o2PP16wkbrUWINtMhfvrB4ko+xwqC1pb+vyCPMmNUh3N/CX5YGqb3DWx2fUPSQ==}
|
||||
engines: {node: '>=16.3.0'}
|
||||
/puppeteer-core@21.5.2:
|
||||
resolution: {integrity: sha512-v4T0cWnujSKs+iEfmb8ccd7u4/x8oblEyKqplqKnJ582Kw8PewYAWvkH4qUWhitN3O2q9RF7dzkvjyK5HbzjLA==}
|
||||
engines: {node: '>=16.13.2'}
|
||||
dependencies:
|
||||
'@puppeteer/browsers': 1.8.0
|
||||
chromium-bidi: 0.4.33(devtools-protocol@0.0.1203626)
|
||||
|
@ -4931,14 +4948,14 @@ packages:
|
|||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/puppeteer@21.5.1(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-NkI06BXckVZeZUkODK+BbgGelQSu7uYEp9PaJDozxpwNRFDYoVfHQvd2G4dERoLdP6+qx4EBPwEhk4dEkQc2Kg==}
|
||||
engines: {node: '>=16.3.0'}
|
||||
/puppeteer@21.5.2(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-BaAGJOq8Fl6/cck6obmwaNLksuY0Bg/lIahCLhJPGXBFUD2mCffypa4A592MaWnDcye7eaHmSK9yot0pxctY8A==}
|
||||
engines: {node: '>=16.13.2'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@puppeteer/browsers': 1.8.0
|
||||
cosmiconfig: 8.3.6(typescript@5.2.2)
|
||||
puppeteer-core: 21.5.1
|
||||
puppeteer-core: 21.5.2
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- encoding
|
||||
|
@ -5129,7 +5146,7 @@ packages:
|
|||
rollup: 4.1.4
|
||||
typescript: 5.2.2
|
||||
optionalDependencies:
|
||||
'@babel/code-frame': 7.22.13
|
||||
'@babel/code-frame': 7.23.5
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-esbuild@6.1.0(esbuild@0.19.5)(rollup@4.1.4):
|
||||
|
@ -5771,8 +5788,8 @@ packages:
|
|||
typescript: 5.2.2
|
||||
dev: true
|
||||
|
||||
/tsx@4.5.0:
|
||||
resolution: {integrity: sha512-hgxdziy9KLaHh9KE+a6tIZFP6kb0MLq/1D0sJVifbGP4QVEYhy6+2FNn7MyCm1pMc63p9CW/L1OzdqTNPxs6rg==}
|
||||
/tsx@4.6.2:
|
||||
resolution: {integrity: sha512-QPpBdJo+ZDtqZgAnq86iY/PD2KYCUPSUGIunHdGwyII99GKH+f3z3FZ8XNFLSGQIA4I365ui8wnQpl8OKLqcsg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
|
@ -5954,7 +5971,7 @@ packages:
|
|||
engines: {node: '>= 0.8'}
|
||||
dev: true
|
||||
|
||||
/vite-node@0.34.6(@types/node@20.10.0)(terser@5.22.0):
|
||||
/vite-node@0.34.6(@types/node@20.10.3)(terser@5.22.0):
|
||||
resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==}
|
||||
engines: {node: '>=v14.18.0'}
|
||||
hasBin: true
|
||||
|
@ -5964,7 +5981,7 @@ packages:
|
|||
mlly: 1.4.2
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 5.0.0(@types/node@20.10.0)(terser@5.22.0)
|
||||
vite: 5.0.0(@types/node@20.10.3)(terser@5.22.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
|
@ -5976,7 +5993,7 @@ packages:
|
|||
- terser
|
||||
dev: true
|
||||
|
||||
/vite@5.0.0(@types/node@20.10.0)(terser@5.22.0):
|
||||
/vite@5.0.0(@types/node@20.10.3)(terser@5.22.0):
|
||||
resolution: {integrity: sha512-ESJVM59mdyGpsiNAeHQOR/0fqNoOyWPYesFto8FFZugfmhdHx8Fzd8sF3Q/xkVhZsyOxHfdM7ieiVAorI9RjFw==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
hasBin: true
|
||||
|
@ -6004,9 +6021,9 @@ packages:
|
|||
terser:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/node': 20.10.0
|
||||
'@types/node': 20.10.3
|
||||
esbuild: 0.19.5
|
||||
postcss: 8.4.31
|
||||
postcss: 8.4.32
|
||||
rollup: 4.4.1
|
||||
terser: 5.22.0
|
||||
optionalDependencies:
|
||||
|
@ -6046,7 +6063,7 @@ packages:
|
|||
dependencies:
|
||||
'@types/chai': 4.3.9
|
||||
'@types/chai-subset': 1.3.4
|
||||
'@types/node': 20.10.0
|
||||
'@types/node': 20.10.3
|
||||
'@vitest/expect': 0.34.6
|
||||
'@vitest/runner': 0.34.6
|
||||
'@vitest/snapshot': 0.34.6
|
||||
|
@ -6066,8 +6083,8 @@ packages:
|
|||
strip-literal: 1.3.0
|
||||
tinybench: 2.5.1
|
||||
tinypool: 0.7.0
|
||||
vite: 5.0.0(@types/node@20.10.0)(terser@5.22.0)
|
||||
vite-node: 0.34.6(@types/node@20.10.0)(terser@5.22.0)
|
||||
vite: 5.0.0(@types/node@20.10.3)(terser@5.22.0)
|
||||
vite-node: 0.34.6(@types/node@20.10.3)(terser@5.22.0)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
|
@ -6183,8 +6200,8 @@ packages:
|
|||
resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
dependencies:
|
||||
'@babel/parser': 7.23.4
|
||||
'@babel/types': 7.23.4
|
||||
'@babel/parser': 7.23.5
|
||||
'@babel/types': 7.23.5
|
||||
assert-never: 1.2.1
|
||||
babel-walk: 3.0.0-canary-5
|
||||
dev: true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// Using esbuild for faster dev builds.
|
||||
// We are still using Rollup for production builds because it generates
|
||||
// smaller files w/ better tree-shaking.
|
||||
// smaller files and provides better tree-shaking.
|
||||
|
||||
import esbuild from 'esbuild'
|
||||
import { resolve, relative, dirname } from 'node:path'
|
||||
|
|
Loading…
Reference in New Issue