mirror of https://github.com/vuejs/core.git
chore: Merge branch 'main' into minor
This commit is contained in:
commit
58d827cb71
|
@ -50,5 +50,9 @@
|
||||||
// pinned
|
// pinned
|
||||||
// https://github.com/vuejs/core/issues/10300#issuecomment-1940855364
|
// https://github.com/vuejs/core/issues/10300#issuecomment-1940855364
|
||||||
'lru-cache',
|
'lru-cache',
|
||||||
|
|
||||||
|
// pinned
|
||||||
|
// https://github.com/vuejs/core/commit/a012e39b373f1b6918e5c89856e8f902e1bfa14d
|
||||||
|
'@rollup/plugin-replace',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,3 +1,17 @@
|
||||||
|
## [3.4.20](https://github.com/vuejs/core/compare/v3.4.19...v3.4.20) (2024-02-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **parser:** should not treat uppercase components as special tags ([e0e0253](https://github.com/vuejs/core/commit/e0e02535cdea1aeb1cfaff0d61d4b2555e555c36)), closes [#10395](https://github.com/vuejs/core/issues/10395)
|
||||||
|
* **runtime-dom:** avoid always resetting nullish option value ([ff130c4](https://github.com/vuejs/core/commit/ff130c470204086edaa093fb8fdc1247c69cba69)), closes [#10396](https://github.com/vuejs/core/issues/10396)
|
||||||
|
* **runtime-dom:** fix nested v-show priority regression ([364f890](https://github.com/vuejs/core/commit/364f8902c8657faec7c3a4d70a5b2c856567e92d)), closes [#10338](https://github.com/vuejs/core/issues/10338)
|
||||||
|
* **runtime-dom:** v-bind style should clear previous css string value ([#10373](https://github.com/vuejs/core/issues/10373)) ([e2d3235](https://github.com/vuejs/core/commit/e2d323538e71d404e729148fd19a08bbc2e3da9b)), closes [#10352](https://github.com/vuejs/core/issues/10352)
|
||||||
|
* **suspense:** handle suspense switching with nested suspense ([#10184](https://github.com/vuejs/core/issues/10184)) ([0f3da05](https://github.com/vuejs/core/commit/0f3da05ea201761529bb95594df1e2cee20b7107)), closes [#10098](https://github.com/vuejs/core/issues/10098)
|
||||||
|
* **types:** better typing for direct setup signature of defineComponent ([#10357](https://github.com/vuejs/core/issues/10357)) ([eadce5b](https://github.com/vuejs/core/commit/eadce5b75356656fd2209ebdb406d34823c961b7)), closes [#8604](https://github.com/vuejs/core/issues/8604) [#8855](https://github.com/vuejs/core/issues/8855)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [3.4.19](https://github.com/vuejs/core/compare/v3.4.18...v3.4.19) (2024-02-13)
|
## [3.4.19](https://github.com/vuejs/core/compare/v3.4.18...v3.4.19) (2024-02-13)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -773,7 +773,7 @@ may cause build issues in projects still using TS 3.x.
|
||||||
- **types:** adjust type exports for manual render function and tooling usage ([e4dc03a](https://github.com/vuejs/core/commit/e4dc03a8b17d5e9f167de6a62a645878ac7ef3e2)), closes [#1329](https://github.com/vuejs/core/issues/1329)
|
- **types:** adjust type exports for manual render function and tooling usage ([e4dc03a](https://github.com/vuejs/core/commit/e4dc03a8b17d5e9f167de6a62a645878ac7ef3e2)), closes [#1329](https://github.com/vuejs/core/issues/1329)
|
||||||
- **types:** mixins/extends support in TypeScript ([#626](https://github.com/vuejs/core/issues/626)) ([d3c436a](https://github.com/vuejs/core/commit/d3c436ae2e66b75b7f2ed574dadda3f0e1fdce73))
|
- **types:** mixins/extends support in TypeScript ([#626](https://github.com/vuejs/core/issues/626)) ([d3c436a](https://github.com/vuejs/core/commit/d3c436ae2e66b75b7f2ed574dadda3f0e1fdce73))
|
||||||
- **types:** support typing directive value via generic argument ([#1007](https://github.com/vuejs/core/issues/1007)) ([419b86d](https://github.com/vuejs/core/commit/419b86d1908f2a0521e6a7eafcbee764e9ee59a0)), closes [#998](https://github.com/vuejs/core/issues/998)
|
- **types:** support typing directive value via generic argument ([#1007](https://github.com/vuejs/core/issues/1007)) ([419b86d](https://github.com/vuejs/core/commit/419b86d1908f2a0521e6a7eafcbee764e9ee59a0)), closes [#998](https://github.com/vuejs/core/issues/998)
|
||||||
- **types:** update to Typescript 3.9 ([#1106](https://github.com/vuejs/core/issues/1106)) ([97dedeb](https://github.com/vuejs/core/commit/97dedebd8097116a16209664a1ca38392b964da3))
|
- **types:** update to TypeScript 3.9 ([#1106](https://github.com/vuejs/core/issues/1106)) ([97dedeb](https://github.com/vuejs/core/commit/97dedebd8097116a16209664a1ca38392b964da3))
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|
||||||
|
|
48
package.json
48
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"packageManager": "pnpm@8.15.1",
|
"packageManager": "pnpm@8.15.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/dev.js",
|
"dev": "node scripts/dev.js",
|
||||||
|
@ -70,49 +70,49 @@
|
||||||
"@rollup/plugin-terser": "^0.4.4",
|
"@rollup/plugin-terser": "^0.4.4",
|
||||||
"@types/hash-sum": "^1.0.2",
|
"@types/hash-sum": "^1.0.2",
|
||||||
"@types/minimist": "^1.2.5",
|
"@types/minimist": "^1.2.5",
|
||||||
"@types/node": "^20.11.16",
|
"@types/node": "^20.11.20",
|
||||||
"@types/semver": "^7.5.6",
|
"@types/semver": "^7.5.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
||||||
"@typescript-eslint/parser": "^6.18.1",
|
"@typescript-eslint/parser": "^7.0.2",
|
||||||
"@vitest/coverage-istanbul": "^1.2.2",
|
"@vitest/coverage-istanbul": "^1.3.1",
|
||||||
"@vue/consolidate": "0.17.3",
|
"@vue/consolidate": "1.0.0",
|
||||||
"conventional-changelog-cli": "^4.1.0",
|
"conventional-changelog-cli": "^4.1.0",
|
||||||
"enquirer": "^2.4.1",
|
"enquirer": "^2.4.1",
|
||||||
"esbuild": "^0.20.0",
|
"esbuild": "^0.20.1",
|
||||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-define-config": "^1.24.1",
|
"eslint-define-config": "^2.1.0",
|
||||||
"eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
|
"eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
|
||||||
"eslint-plugin-jest": "^27.6.3",
|
"eslint-plugin-jest": "^27.9.0",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"jsdom": "^23.2.0",
|
"jsdom": "^24.0.0",
|
||||||
"lint-staged": "^15.2.0",
|
"lint-staged": "^15.2.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"magic-string": "^0.30.6",
|
"magic-string": "^0.30.7",
|
||||||
"markdown-table": "^3.0.3",
|
"markdown-table": "^3.0.3",
|
||||||
"marked": "^11.2.0",
|
"marked": "^12.0.0",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"npm-run-all2": "^6.1.2",
|
"npm-run-all2": "^6.1.2",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"prettier": "^3.2.2",
|
"prettier": "^3.2.5",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^6.1.1",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
"puppeteer": "~21.11.0",
|
"puppeteer": "~22.2.0",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"rollup": "4.9.2",
|
"rollup": "^4.12.0",
|
||||||
"rollup-plugin-dts": "^6.1.0",
|
"rollup-plugin-dts": "^6.1.0",
|
||||||
"rollup-plugin-esbuild": "^6.1.1",
|
"rollup-plugin-esbuild": "^6.1.1",
|
||||||
"rollup-plugin-polyfill-node": "^0.13.0",
|
"rollup-plugin-polyfill-node": "^0.13.0",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.6.0",
|
||||||
"serve": "^14.2.1",
|
"serve": "^14.2.1",
|
||||||
"simple-git-hooks": "^2.9.0",
|
"simple-git-hooks": "^2.9.0",
|
||||||
"terser": "^5.27.0",
|
"terser": "^5.28.1",
|
||||||
"todomvc-app-css": "^2.4.3",
|
"todomvc-app-css": "^2.4.3",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"tsx": "^4.7.0",
|
"tsx": "^4.7.1",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"vite": "^5.0.12",
|
"vite": "^5.1.4",
|
||||||
"vitest": "^1.2.2"
|
"vitest": "^1.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,7 @@ describe('compiler: transform v-on', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should NOT wrap as function if expression is already function expression (with Typescript)', () => {
|
test('should NOT wrap as function if expression is already function expression (with TypeScript)', () => {
|
||||||
const { node } = parseWithVOn(`<div @click="(e: any): any => foo(e)"/>`)
|
const { node } = parseWithVOn(`<div @click="(e: any): any => foo(e)"/>`)
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-core",
|
"name": "@vue/compiler-core",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/compiler-core",
|
"description": "@vue/compiler-core",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/compiler-core.esm-bundler.js",
|
"module": "dist/compiler-core.esm-bundler.js",
|
||||||
|
|
|
@ -553,12 +553,11 @@ export default class Tokenizer {
|
||||||
// HTML mode
|
// HTML mode
|
||||||
// - <script>, <style> RAWTEXT
|
// - <script>, <style> RAWTEXT
|
||||||
// - <title>, <textarea> RCDATA
|
// - <title>, <textarea> RCDATA
|
||||||
const lower = c | 0x20
|
if (c === 116 /* t */) {
|
||||||
if (lower === 116 /* t */) {
|
|
||||||
this.state = State.BeforeSpecialT
|
this.state = State.BeforeSpecialT
|
||||||
} else {
|
} else {
|
||||||
this.state =
|
this.state =
|
||||||
lower === 115 /* s */ ? State.BeforeSpecialS : State.InTagName
|
c === 115 /* s */ ? State.BeforeSpecialS : State.InTagName
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.state = State.InTagName
|
this.state = State.InTagName
|
||||||
|
@ -862,10 +861,9 @@ export default class Tokenizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private stateBeforeSpecialS(c: number): void {
|
private stateBeforeSpecialS(c: number): void {
|
||||||
const lower = c | 0x20
|
if (c === Sequences.ScriptEnd[3]) {
|
||||||
if (lower === Sequences.ScriptEnd[3]) {
|
|
||||||
this.startSpecial(Sequences.ScriptEnd, 4)
|
this.startSpecial(Sequences.ScriptEnd, 4)
|
||||||
} else if (lower === Sequences.StyleEnd[3]) {
|
} else if (c === Sequences.StyleEnd[3]) {
|
||||||
this.startSpecial(Sequences.StyleEnd, 4)
|
this.startSpecial(Sequences.StyleEnd, 4)
|
||||||
} else {
|
} else {
|
||||||
this.state = State.InTagName
|
this.state = State.InTagName
|
||||||
|
@ -873,10 +871,9 @@ export default class Tokenizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private stateBeforeSpecialT(c: number): void {
|
private stateBeforeSpecialT(c: number): void {
|
||||||
const lower = c | 0x20
|
if (c === Sequences.TitleEnd[3]) {
|
||||||
if (lower === Sequences.TitleEnd[3]) {
|
|
||||||
this.startSpecial(Sequences.TitleEnd, 4)
|
this.startSpecial(Sequences.TitleEnd, 4)
|
||||||
} else if (lower === Sequences.TextareaEnd[3]) {
|
} else if (c === Sequences.TextareaEnd[3]) {
|
||||||
this.startSpecial(Sequences.TextareaEnd, 4)
|
this.startSpecial(Sequences.TextareaEnd, 4)
|
||||||
} else {
|
} else {
|
||||||
this.state = State.InTagName
|
this.state = State.InTagName
|
||||||
|
|
|
@ -20,7 +20,7 @@ describe('DOM parser', () => {
|
||||||
)
|
)
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
const text = element.children[0] as TextNode
|
const text = element.children[0] as TextNode
|
||||||
|
expect(element.children.length).toBe(1)
|
||||||
expect(text).toStrictEqual({
|
expect(text).toStrictEqual({
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: 'some<div>text</div>and<!--comment-->',
|
content: 'some<div>text</div>and<!--comment-->',
|
||||||
|
@ -32,6 +32,20 @@ describe('DOM parser', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should not treat Uppercase component as special tag', () => {
|
||||||
|
const ast = parse(
|
||||||
|
'<TextArea>some<div>text</div>and<!--comment--></TextArea>',
|
||||||
|
parserOptions,
|
||||||
|
)
|
||||||
|
const element = ast.children[0] as ElementNode
|
||||||
|
expect(element.children.map(n => n.type)).toMatchObject([
|
||||||
|
NodeTypes.TEXT,
|
||||||
|
NodeTypes.ELEMENT,
|
||||||
|
NodeTypes.TEXT,
|
||||||
|
NodeTypes.COMMENT,
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('textarea handles entities', () => {
|
test('textarea handles entities', () => {
|
||||||
const ast = parse('<textarea>&</textarea>', parserOptions)
|
const ast = parse('<textarea>&</textarea>', parserOptions)
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-dom",
|
"name": "@vue/compiler-dom",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/compiler-dom",
|
"description": "@vue/compiler-dom",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/compiler-dom.esm-bundler.js",
|
"module": "dist/compiler-dom.esm-bundler.js",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-sfc",
|
"name": "@vue/compiler-sfc",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/compiler-sfc",
|
"description": "@vue/compiler-sfc",
|
||||||
"main": "dist/compiler-sfc.cjs.js",
|
"main": "dist/compiler-sfc.cjs.js",
|
||||||
"module": "dist/compiler-sfc.esm-browser.js",
|
"module": "dist/compiler-sfc.esm-browser.js",
|
||||||
|
@ -48,8 +48,8 @@
|
||||||
"@vue/compiler-ssr": "workspace:*",
|
"@vue/compiler-ssr": "workspace:*",
|
||||||
"@vue/shared": "workspace:*",
|
"@vue/shared": "workspace:*",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"magic-string": "^0.30.6",
|
"magic-string": "^0.30.7",
|
||||||
"postcss": "^8.4.33",
|
"postcss": "^8.4.35",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -62,6 +62,6 @@
|
||||||
"postcss-modules": "^6.0.0",
|
"postcss-modules": "^6.0.0",
|
||||||
"postcss-selector-parser": "^6.0.15",
|
"postcss-selector-parser": "^6.0.15",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
"sass": "^1.70.0"
|
"sass": "^1.71.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-ssr",
|
"name": "@vue/compiler-ssr",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/compiler-ssr",
|
"description": "@vue/compiler-ssr",
|
||||||
"main": "dist/compiler-ssr.cjs.js",
|
"main": "dist/compiler-ssr.cjs.js",
|
||||||
"types": "dist/compiler-ssr.d.ts",
|
"types": "dist/compiler-ssr.d.ts",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# dts-test
|
# dts-test
|
||||||
|
|
||||||
Tests Typescript types to ensure the types remain as expected.
|
Tests TypeScript types to ensure the types remain as expected.
|
||||||
|
|
||||||
- This directory is included in the root `tsconfig.json`, where package imports are aliased to `src` directories, so in IDEs and the `pnpm check` script the types are validated against source code.
|
- This directory is included in the root `tsconfig.json`, where package imports are aliased to `src` directories, so in IDEs and the `pnpm check` script the types are validated against source code.
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ describe.skipIf(!global.gc)('reactivity/gc', () => {
|
||||||
// #9233
|
// #9233
|
||||||
it('should release computed cache', async () => {
|
it('should release computed cache', async () => {
|
||||||
const src = ref<{} | undefined>({})
|
const src = ref<{} | undefined>({})
|
||||||
|
// @ts-expect-error ES2021 API
|
||||||
const srcRef = new WeakRef(src.value!)
|
const srcRef = new WeakRef(src.value!)
|
||||||
|
|
||||||
let c: ComputedRef | undefined = computed(() => src.value)
|
let c: ComputedRef | undefined = computed(() => src.value)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/reactivity",
|
"name": "@vue/reactivity",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/reactivity",
|
"description": "@vue/reactivity",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/reactivity.esm-bundler.js",
|
"module": "dist/reactivity.esm-bundler.js",
|
||||||
|
|
|
@ -84,26 +84,26 @@ function hasOwnProperty(this: object, key: string) {
|
||||||
class BaseReactiveHandler implements ProxyHandler<Target> {
|
class BaseReactiveHandler implements ProxyHandler<Target> {
|
||||||
constructor(
|
constructor(
|
||||||
protected readonly _isReadonly = false,
|
protected readonly _isReadonly = false,
|
||||||
protected readonly _shallow = false,
|
protected readonly _isShallow = false,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get(target: Target, key: string | symbol, receiver: object) {
|
get(target: Target, key: string | symbol, receiver: object) {
|
||||||
const isReadonly = this._isReadonly,
|
const isReadonly = this._isReadonly,
|
||||||
shallow = this._shallow
|
isShallow = this._isShallow
|
||||||
if (key === ReactiveFlags.IS_REACTIVE) {
|
if (key === ReactiveFlags.IS_REACTIVE) {
|
||||||
return !isReadonly
|
return !isReadonly
|
||||||
} else if (key === ReactiveFlags.IS_READONLY) {
|
} else if (key === ReactiveFlags.IS_READONLY) {
|
||||||
return isReadonly
|
return isReadonly
|
||||||
} else if (key === ReactiveFlags.IS_SHALLOW) {
|
} else if (key === ReactiveFlags.IS_SHALLOW) {
|
||||||
return shallow
|
return isShallow
|
||||||
} else if (key === ReactiveFlags.RAW) {
|
} else if (key === ReactiveFlags.RAW) {
|
||||||
if (
|
if (
|
||||||
receiver ===
|
receiver ===
|
||||||
(isReadonly
|
(isReadonly
|
||||||
? shallow
|
? isShallow
|
||||||
? shallowReadonlyMap
|
? shallowReadonlyMap
|
||||||
: readonlyMap
|
: readonlyMap
|
||||||
: shallow
|
: isShallow
|
||||||
? shallowReactiveMap
|
? shallowReactiveMap
|
||||||
: reactiveMap
|
: reactiveMap
|
||||||
).get(target) ||
|
).get(target) ||
|
||||||
|
@ -145,7 +145,7 @@ class BaseReactiveHandler implements ProxyHandler<Target> {
|
||||||
track(target, TrackOpTypes.GET, key)
|
track(target, TrackOpTypes.GET, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shallow) {
|
if (isShallow) {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,8 +166,8 @@ class BaseReactiveHandler implements ProxyHandler<Target> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MutableReactiveHandler extends BaseReactiveHandler {
|
class MutableReactiveHandler extends BaseReactiveHandler {
|
||||||
constructor(shallow = false) {
|
constructor(isShallow = false) {
|
||||||
super(false, shallow)
|
super(false, isShallow)
|
||||||
}
|
}
|
||||||
|
|
||||||
set(
|
set(
|
||||||
|
@ -177,7 +177,7 @@ class MutableReactiveHandler extends BaseReactiveHandler {
|
||||||
receiver: object,
|
receiver: object,
|
||||||
): boolean {
|
): boolean {
|
||||||
let oldValue = (target as any)[key]
|
let oldValue = (target as any)[key]
|
||||||
if (!this._shallow) {
|
if (!this._isShallow) {
|
||||||
const isOldValueReadonly = isReadonly(oldValue)
|
const isOldValueReadonly = isReadonly(oldValue)
|
||||||
if (!isShallow(value) && !isReadonly(value)) {
|
if (!isShallow(value) && !isReadonly(value)) {
|
||||||
oldValue = toRaw(oldValue)
|
oldValue = toRaw(oldValue)
|
||||||
|
@ -239,8 +239,8 @@ class MutableReactiveHandler extends BaseReactiveHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReadonlyReactiveHandler extends BaseReactiveHandler {
|
class ReadonlyReactiveHandler extends BaseReactiveHandler {
|
||||||
constructor(shallow = false) {
|
constructor(isShallow = false) {
|
||||||
super(true, shallow)
|
super(true, isShallow)
|
||||||
}
|
}
|
||||||
|
|
||||||
set(target: object, key: string | symbol) {
|
set(target: object, key: string | symbol) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { toRaw, toReactive, toReadonly } from './reactive'
|
||||||
import { ITERATE_KEY, MAP_KEY_ITERATE_KEY, track, trigger } from './dep'
|
import { ITERATE_KEY, MAP_KEY_ITERATE_KEY, track, trigger } from './dep'
|
||||||
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
|
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
|
||||||
import { capitalize, hasChanged, hasOwn, isMap, toRawType } from '@vue/shared'
|
import { capitalize, hasChanged, hasOwn, isMap, toRawType } from '@vue/shared'
|
||||||
|
import { warn } from './warning'
|
||||||
|
|
||||||
type CollectionTypes = IterableCollections | WeakCollections
|
type CollectionTypes = IterableCollections | WeakCollections
|
||||||
|
|
||||||
|
@ -218,7 +219,7 @@ function createReadonlyMethod(type: TriggerOpTypes): Function {
|
||||||
return function (this: CollectionTypes, ...args: unknown[]) {
|
return function (this: CollectionTypes, ...args: unknown[]) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
const key = args[0] ? `on key "${args[0]}" ` : ``
|
const key = args[0] ? `on key "${args[0]}" ` : ``
|
||||||
console.warn(
|
warn(
|
||||||
`${capitalize(type)} operation ${key}failed: target is readonly.`,
|
`${capitalize(type)} operation ${key}failed: target is readonly.`,
|
||||||
toRaw(this),
|
toRaw(this),
|
||||||
)
|
)
|
||||||
|
@ -392,7 +393,7 @@ function checkIdentityKeys(
|
||||||
const rawKey = toRaw(key)
|
const rawKey = toRaw(key)
|
||||||
if (rawKey !== key && has.call(target, rawKey)) {
|
if (rawKey !== key && has.call(target, rawKey)) {
|
||||||
const type = toRawType(target)
|
const type = toRawType(target)
|
||||||
console.warn(
|
warn(
|
||||||
`Reactive ${type} contains both the raw and reactive ` +
|
`Reactive ${type} contains both the raw and reactive ` +
|
||||||
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
|
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
|
||||||
`which can lead to inconsistencies. ` +
|
`which can lead to inconsistencies. ` +
|
||||||
|
|
|
@ -60,6 +60,11 @@ export class ComputedRefImpl<T = any> implements Subscriber {
|
||||||
// dev only
|
// dev only
|
||||||
onTrigger?: (event: DebuggerEvent) => void
|
onTrigger?: (event: DebuggerEvent) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dev only
|
||||||
|
*/
|
||||||
|
_warnRecursive?: boolean
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public fn: ComputedGetter<T>,
|
public fn: ComputedGetter<T>,
|
||||||
private readonly setter: ComputedSetter<T> | undefined,
|
private readonly setter: ComputedSetter<T> | undefined,
|
||||||
|
|
|
@ -43,6 +43,7 @@ export {
|
||||||
type WritableComputedOptions,
|
type WritableComputedOptions,
|
||||||
type ComputedGetter,
|
type ComputedGetter,
|
||||||
type ComputedSetter,
|
type ComputedSetter,
|
||||||
|
type ComputedRefImpl,
|
||||||
} from './computed'
|
} from './computed'
|
||||||
export {
|
export {
|
||||||
effect,
|
effect,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
} from './collectionHandlers'
|
} from './collectionHandlers'
|
||||||
import type { RawSymbol, Ref, UnwrapRefSimple } from './ref'
|
import type { RawSymbol, Ref, UnwrapRefSimple } from './ref'
|
||||||
import { ReactiveFlags } from './constants'
|
import { ReactiveFlags } from './constants'
|
||||||
|
import { warn } from './warning'
|
||||||
|
|
||||||
export interface Target {
|
export interface Target {
|
||||||
[ReactiveFlags.SKIP]?: boolean
|
[ReactiveFlags.SKIP]?: boolean
|
||||||
|
@ -247,7 +248,7 @@ function createReactiveObject(
|
||||||
) {
|
) {
|
||||||
if (!isObject(target)) {
|
if (!isObject(target)) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.warn(`value cannot be made reactive: ${String(target)}`)
|
warn(`value cannot be made reactive: ${String(target)}`)
|
||||||
}
|
}
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
} from './reactive'
|
} from './reactive'
|
||||||
import type { ComputedRef } from './computed'
|
import type { ComputedRef } from './computed'
|
||||||
import { TrackOpTypes, TriggerOpTypes } from './constants'
|
import { TrackOpTypes, TriggerOpTypes } from './constants'
|
||||||
|
import { warn } from './warning'
|
||||||
|
|
||||||
declare const RefSymbol: unique symbol
|
declare const RefSymbol: unique symbol
|
||||||
export declare const RawSymbol: unique symbol
|
export declare const RawSymbol: unique symbol
|
||||||
|
@ -319,7 +320,7 @@ export type ToRefs<T = any> = {
|
||||||
*/
|
*/
|
||||||
export function toRefs<T extends object>(object: T): ToRefs<T> {
|
export function toRefs<T extends object>(object: T): ToRefs<T> {
|
||||||
if (__DEV__ && !isProxy(object)) {
|
if (__DEV__ && !isProxy(object)) {
|
||||||
console.warn(`toRefs() expects a reactive object but received a plain one.`)
|
warn(`toRefs() expects a reactive object but received a plain one.`)
|
||||||
}
|
}
|
||||||
const ret: any = isArray(object) ? new Array(object.length) : {}
|
const ret: any = isArray(object) ? new Array(object.length) : {}
|
||||||
for (const key in object) {
|
for (const key in object) {
|
||||||
|
|
|
@ -143,10 +143,10 @@ describe('api: createApp', () => {
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
// resolve in setup
|
// resolve in setup
|
||||||
const FooBar = resolveComponent('foo-bar') as any
|
const FooBar = resolveComponent('foo-bar')
|
||||||
return () => {
|
return () => {
|
||||||
// resolve in render
|
// resolve in render
|
||||||
const BarBaz = resolveComponent('bar-baz') as any
|
const BarBaz = resolveComponent('bar-baz')
|
||||||
return h('div', [h(FooBar), h(BarBaz)])
|
return h('div', [h(FooBar), h(BarBaz)])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -182,10 +182,10 @@ describe('api: createApp', () => {
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
// resolve in setup
|
// resolve in setup
|
||||||
const FooBar = resolveDirective('foo-bar')!
|
const FooBar = resolveDirective('foo-bar')
|
||||||
return () => {
|
return () => {
|
||||||
// resolve in render
|
// resolve in render
|
||||||
const BarBaz = resolveDirective('bar-baz')!
|
const BarBaz = resolveDirective('bar-baz')
|
||||||
return withDirectives(h('div'), [[FooBar], [BarBaz]])
|
return withDirectives(h('div'), [[FooBar], [BarBaz]])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -350,7 +350,7 @@ describe('api: createApp', () => {
|
||||||
|
|
||||||
const handler = vi.fn((err, instance, info) => {
|
const handler = vi.fn((err, instance, info) => {
|
||||||
expect(err).toBe(error)
|
expect(err).toBe(error)
|
||||||
expect((instance as any).count).toBe(count.value)
|
expect(instance.count).toBe(count.value)
|
||||||
expect(info).toBe(`render function`)
|
expect(info).toBe(`render function`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -450,11 +450,6 @@ describe('api: createApp', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = createApp(Root)
|
const app = createApp(Root)
|
||||||
Object.defineProperty(app.config, 'isNativeTag', {
|
|
||||||
value: isNativeTag,
|
|
||||||
writable: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
app.mount(nodeOps.createElement('div'))
|
app.mount(nodeOps.createElement('div'))
|
||||||
expect(
|
expect(
|
||||||
`Do not use built-in directive ids as custom directive id: bind`,
|
`Do not use built-in directive ids as custom directive id: bind`,
|
||||||
|
|
|
@ -790,10 +790,8 @@ describe('api: options', () => {
|
||||||
data() {},
|
data() {},
|
||||||
}
|
}
|
||||||
defineComponent({
|
defineComponent({
|
||||||
// @ts-expect-error edge case after #7963, unlikely to happen in practice
|
|
||||||
// since the user will want to type the mixins themselves.
|
// since the user will want to type the mixins themselves.
|
||||||
mixins: [defineComponent(MixinA), defineComponent(MixinB)],
|
mixins: [defineComponent(MixinA), defineComponent(MixinB)],
|
||||||
// @ts-expect-error
|
|
||||||
data() {},
|
data() {},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {
|
||||||
watch,
|
watch,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { createApp, defineComponent } from 'vue'
|
import { computed, createApp, defineComponent, inject, provide } from 'vue'
|
||||||
import type { RawSlots } from 'packages/runtime-core/src/componentSlots'
|
import type { RawSlots } from 'packages/runtime-core/src/componentSlots'
|
||||||
import { resetSuspenseId } from '../../src/components/Suspense'
|
import { resetSuspenseId } from '../../src/components/Suspense'
|
||||||
|
|
||||||
|
@ -1039,6 +1039,99 @@ describe('Suspense', () => {
|
||||||
expect(serializeInner(root)).toBe(`<div>foo<div>foo nested</div></div>`)
|
expect(serializeInner(root)).toBe(`<div>foo<div>foo nested</div></div>`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #10098
|
||||||
|
test('switching branches w/ nested suspense', async () => {
|
||||||
|
const RouterView = {
|
||||||
|
setup(_: any, { slots }: any) {
|
||||||
|
const route = inject('route') as any
|
||||||
|
const depth = inject('depth', 0)
|
||||||
|
provide('depth', depth + 1)
|
||||||
|
return () => {
|
||||||
|
const current = route.value[depth]
|
||||||
|
return slots.default({ Component: current })[0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const OuterB = defineAsyncComponent({
|
||||||
|
setup: () => {
|
||||||
|
return () =>
|
||||||
|
h(RouterView, null, {
|
||||||
|
default: ({ Component }: any) => [
|
||||||
|
h(Suspense, null, {
|
||||||
|
default: () => h(Component),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const InnerB = defineAsyncComponent({
|
||||||
|
setup: () => {
|
||||||
|
return () => h('div', 'innerB')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const OuterA = defineAsyncComponent({
|
||||||
|
setup: () => {
|
||||||
|
return () =>
|
||||||
|
h(RouterView, null, {
|
||||||
|
default: ({ Component }: any) => [
|
||||||
|
h(Suspense, null, {
|
||||||
|
default: () => h(Component),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const InnerA = defineAsyncComponent({
|
||||||
|
setup: () => {
|
||||||
|
return () => h('div', 'innerA')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const toggle = ref(true)
|
||||||
|
const route = computed(() => {
|
||||||
|
return toggle.value ? [OuterA, InnerA] : [OuterB, InnerB]
|
||||||
|
})
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
provide('route', route)
|
||||||
|
return () =>
|
||||||
|
h(RouterView, null, {
|
||||||
|
default: ({ Component }: any) => [
|
||||||
|
h(Suspense, null, {
|
||||||
|
default: () => h(Component),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(h(Comp), root)
|
||||||
|
await Promise.all(deps)
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(`<!---->`)
|
||||||
|
|
||||||
|
await Promise.all(deps)
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(`<div>innerA</div>`)
|
||||||
|
|
||||||
|
deps.length = 0
|
||||||
|
|
||||||
|
toggle.value = false
|
||||||
|
await nextTick()
|
||||||
|
// toggle again
|
||||||
|
toggle.value = true
|
||||||
|
|
||||||
|
await Promise.all(deps)
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(`<div>innerA</div>`)
|
||||||
|
})
|
||||||
|
|
||||||
test('branch switch to 3rd branch before resolve', async () => {
|
test('branch switch to 3rd branch before resolve', async () => {
|
||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import {
|
||||||
} from '@vue/runtime-dom'
|
} from '@vue/runtime-dom'
|
||||||
import { type SSRContext, renderToString } from '@vue/server-renderer'
|
import { type SSRContext, renderToString } from '@vue/server-renderer'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
import { vShowOldKey } from '../../runtime-dom/src/directives/vShow'
|
import { vShowOriginalDisplay } from '../../runtime-dom/src/directives/vShow'
|
||||||
|
|
||||||
function mountWithHydration(html: string, render: () => any) {
|
function mountWithHydration(html: string, render: () => any) {
|
||||||
const container = document.createElement('div')
|
const container = document.createElement('div')
|
||||||
|
@ -1252,7 +1252,7 @@ describe('SSR hydration', () => {
|
||||||
foo
|
foo
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
expect((container.firstChild as any)[vShowOldKey]).toBe('')
|
expect((container.firstChild as any)[vShowOriginalDisplay]).toBe('')
|
||||||
expect(vnode.el).toBe(container.firstChild)
|
expect(vnode.el).toBe(container.firstChild)
|
||||||
expect(`mismatch`).not.toHaveBeenWarned()
|
expect(`mismatch`).not.toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/runtime-core",
|
"name": "@vue/runtime-core",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/runtime-core",
|
"description": "@vue/runtime-core",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/runtime-core.esm-bundler.js",
|
"module": "dist/runtime-core.esm-bundler.js",
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import { computed as _computed } from '@vue/reactivity'
|
import { type ComputedRefImpl, computed as _computed } from '@vue/reactivity'
|
||||||
import { isInSSRComponentSetup } from './component'
|
import { getCurrentInstance, isInSSRComponentSetup } from './component'
|
||||||
|
|
||||||
export const computed: typeof _computed = (
|
export const computed: typeof _computed = (
|
||||||
getterOrOptions: any,
|
getterOrOptions: any,
|
||||||
debugOptions?: any,
|
debugOptions?: any,
|
||||||
) => {
|
) => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
return _computed(getterOrOptions, debugOptions, isInSSRComponentSetup)
|
const c = _computed(getterOrOptions, debugOptions, isInSSRComponentSetup)
|
||||||
|
if (__DEV__) {
|
||||||
|
const i = getCurrentInstance()
|
||||||
|
if (i && i.appContext.config.warnRecursiveComputed) {
|
||||||
|
;(c as unknown as ComputedRefImpl<any>)._warnRecursive = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ export type OptionMergeFunction = (to: unknown, from: unknown) => any
|
||||||
|
|
||||||
export interface AppConfig {
|
export interface AppConfig {
|
||||||
// @private
|
// @private
|
||||||
readonly isNativeTag?: (tag: string) => boolean
|
readonly isNativeTag: (tag: string) => boolean
|
||||||
|
|
||||||
performance: boolean
|
performance: boolean
|
||||||
optionMergeStrategies: Record<string, OptionMergeFunction>
|
optionMergeStrategies: Record<string, OptionMergeFunction>
|
||||||
|
@ -110,6 +110,12 @@ export interface AppConfig {
|
||||||
* @deprecated use config.compilerOptions.isCustomElement
|
* @deprecated use config.compilerOptions.isCustomElement
|
||||||
*/
|
*/
|
||||||
isCustomElement?: (tag: string) => boolean
|
isCustomElement?: (tag: string) => boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO document for 3.5
|
||||||
|
* Enable warnings for computed getters that recursively trigger itself.
|
||||||
|
*/
|
||||||
|
warnRecursiveComputed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AppContext {
|
export interface AppContext {
|
||||||
|
|
|
@ -89,6 +89,30 @@ export type DefineComponent<
|
||||||
> &
|
> &
|
||||||
PP
|
PP
|
||||||
|
|
||||||
|
export type DefineSetupFnComponent<
|
||||||
|
P extends Record<string, any>,
|
||||||
|
E extends EmitsOptions = {},
|
||||||
|
S extends SlotsType = SlotsType,
|
||||||
|
Props = P & EmitsToProps<E>,
|
||||||
|
PP = PublicProps,
|
||||||
|
> = new (
|
||||||
|
props: Props & PP,
|
||||||
|
) => CreateComponentPublicInstance<
|
||||||
|
Props,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
ComponentOptionsMixin,
|
||||||
|
ComponentOptionsMixin,
|
||||||
|
E,
|
||||||
|
PP,
|
||||||
|
{},
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
S
|
||||||
|
>
|
||||||
|
|
||||||
// defineComponent is a utility that is primarily used for type inference
|
// defineComponent is a utility that is primarily used for type inference
|
||||||
// when declaring components. Type inference is provided in the component
|
// when declaring components. Type inference is provided in the component
|
||||||
// options (provided as the argument). The returned value has artificial types
|
// options (provided as the argument). The returned value has artificial types
|
||||||
|
@ -111,7 +135,7 @@ export function defineComponent<
|
||||||
emits?: E | EE[]
|
emits?: E | EE[]
|
||||||
slots?: S
|
slots?: S
|
||||||
},
|
},
|
||||||
): (props: Props & EmitsToProps<E>) => any
|
): DefineSetupFnComponent<Props, E, S>
|
||||||
export function defineComponent<
|
export function defineComponent<
|
||||||
Props extends Record<string, any>,
|
Props extends Record<string, any>,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
|
@ -127,7 +151,7 @@ export function defineComponent<
|
||||||
emits?: E | EE[]
|
emits?: E | EE[]
|
||||||
slots?: S
|
slots?: S
|
||||||
},
|
},
|
||||||
): (props: Props & EmitsToProps<E>) => any
|
): DefineSetupFnComponent<Props, E, S>
|
||||||
|
|
||||||
// overload 2: object format with no props
|
// overload 2: object format with no props
|
||||||
// (uses user defined props interface)
|
// (uses user defined props interface)
|
||||||
|
|
|
@ -61,7 +61,6 @@ import {
|
||||||
import {
|
import {
|
||||||
EMPTY_OBJ,
|
EMPTY_OBJ,
|
||||||
type IfAny,
|
type IfAny,
|
||||||
NO,
|
|
||||||
NOOP,
|
NOOP,
|
||||||
ShapeFlags,
|
ShapeFlags,
|
||||||
extend,
|
extend,
|
||||||
|
@ -712,9 +711,11 @@ export const unsetCurrentInstance = () => {
|
||||||
|
|
||||||
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
|
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
|
||||||
|
|
||||||
export function validateComponentName(name: string, config: AppConfig) {
|
export function validateComponentName(
|
||||||
const appIsNativeTag = config.isNativeTag || NO
|
name: string,
|
||||||
if (isBuiltInTag(name) || appIsNativeTag(name)) {
|
{ isNativeTag }: AppConfig,
|
||||||
|
) {
|
||||||
|
if (isBuiltInTag(name) || isNativeTag(name)) {
|
||||||
warn(
|
warn(
|
||||||
'Do not use built-in or reserved HTML elements as component id: ' + name,
|
'Do not use built-in or reserved HTML elements as component id: ' + name,
|
||||||
)
|
)
|
||||||
|
|
|
@ -144,8 +144,6 @@ const BaseTransitionImpl: ComponentOptions = {
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
const state = useTransitionState()
|
const state = useTransitionState()
|
||||||
|
|
||||||
let prevTransitionKey: any
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const children =
|
const children =
|
||||||
slots.default && getTransitionRawChildren(slots.default(), true)
|
slots.default && getTransitionRawChildren(slots.default(), true)
|
||||||
|
@ -211,23 +209,11 @@ const BaseTransitionImpl: ComponentOptions = {
|
||||||
const oldChild = instance.subTree
|
const oldChild = instance.subTree
|
||||||
const oldInnerChild = oldChild && getKeepAliveChild(oldChild)
|
const oldInnerChild = oldChild && getKeepAliveChild(oldChild)
|
||||||
|
|
||||||
let transitionKeyChanged = false
|
|
||||||
const { getTransitionKey } = innerChild.type as any
|
|
||||||
if (getTransitionKey) {
|
|
||||||
const key = getTransitionKey()
|
|
||||||
if (prevTransitionKey === undefined) {
|
|
||||||
prevTransitionKey = key
|
|
||||||
} else if (key !== prevTransitionKey) {
|
|
||||||
prevTransitionKey = key
|
|
||||||
transitionKeyChanged = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mode
|
// handle mode
|
||||||
if (
|
if (
|
||||||
oldInnerChild &&
|
oldInnerChild &&
|
||||||
oldInnerChild.type !== Comment &&
|
oldInnerChild.type !== Comment &&
|
||||||
(!isSameVNodeType(innerChild, oldInnerChild) || transitionKeyChanged)
|
!isSameVNodeType(innerChild, oldInnerChild)
|
||||||
) {
|
) {
|
||||||
const leavingHooks = resolveTransitionHooks(
|
const leavingHooks = resolveTransitionHooks(
|
||||||
oldInnerChild,
|
oldInnerChild,
|
||||||
|
|
|
@ -100,7 +100,9 @@ export const SuspenseImpl = {
|
||||||
// it is necessary to skip the current patch to avoid multiple mounts
|
// it is necessary to skip the current patch to avoid multiple mounts
|
||||||
// of inner components.
|
// of inner components.
|
||||||
if (parentSuspense && parentSuspense.deps > 0) {
|
if (parentSuspense && parentSuspense.deps > 0) {
|
||||||
n2.suspense = n1.suspense
|
n2.suspense = n1.suspense!
|
||||||
|
n2.suspense.vnode = n2
|
||||||
|
n2.el = n1.el
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
patchSuspense(
|
patchSuspense(
|
||||||
|
|
|
@ -250,7 +250,11 @@ export type {
|
||||||
AllowedComponentProps,
|
AllowedComponentProps,
|
||||||
ComponentInstance,
|
ComponentInstance,
|
||||||
} from './component'
|
} from './component'
|
||||||
export type { DefineComponent, PublicProps } from './apiDefineComponent'
|
export type {
|
||||||
|
DefineComponent,
|
||||||
|
DefineSetupFnComponent,
|
||||||
|
PublicProps,
|
||||||
|
} from './apiDefineComponent'
|
||||||
export type {
|
export type {
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
|
|
|
@ -158,4 +158,13 @@ describe(`runtime-dom: style patching`, () => {
|
||||||
)
|
)
|
||||||
expect(el.style.display).toBe('flex')
|
expect(el.style.display).toBe('flex')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should clear previous css string value', () => {
|
||||||
|
const el = document.createElement('div')
|
||||||
|
patchProp(el, 'style', {}, 'color:red')
|
||||||
|
expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
|
||||||
|
|
||||||
|
patchProp(el, 'style', 'color:red', { fontSize: '12px' })
|
||||||
|
expect(el.style.cssText.replace(/\s/g, '')).toBe('font-size:12px;')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/runtime-dom",
|
"name": "@vue/runtime-dom",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/runtime-dom",
|
"description": "@vue/runtime-dom",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/runtime-dom.esm-bundler.js",
|
"module": "dist/runtime-dom.esm-bundler.js",
|
||||||
|
|
|
@ -209,25 +209,20 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
||||||
},
|
},
|
||||||
// set value in mounted & updated because <select> relies on its children
|
// set value in mounted & updated because <select> relies on its children
|
||||||
// <option>s.
|
// <option>s.
|
||||||
mounted(el, { value, oldValue, modifiers: { number } }) {
|
mounted(el, { value, modifiers: { number } }) {
|
||||||
setSelected(el, value, oldValue, number)
|
setSelected(el, value, number)
|
||||||
},
|
},
|
||||||
beforeUpdate(el, _binding, vnode) {
|
beforeUpdate(el, _binding, vnode) {
|
||||||
el[assignKey] = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
},
|
},
|
||||||
updated(el, { value, oldValue, modifiers: { number } }) {
|
updated(el, { value, modifiers: { number } }) {
|
||||||
if (!el._assigning) {
|
if (!el._assigning) {
|
||||||
setSelected(el, value, oldValue, number)
|
setSelected(el, value, number)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSelected(
|
function setSelected(el: HTMLSelectElement, value: any, number: boolean) {
|
||||||
el: HTMLSelectElement,
|
|
||||||
value: any,
|
|
||||||
oldValue: any,
|
|
||||||
number: boolean,
|
|
||||||
) {
|
|
||||||
const isMultiple = el.multiple
|
const isMultiple = el.multiple
|
||||||
const isArrayValue = isArray(value)
|
const isArrayValue = isArray(value)
|
||||||
if (isMultiple && !isArrayValue && !isSet(value)) {
|
if (isMultiple && !isArrayValue && !isSet(value)) {
|
||||||
|
@ -256,11 +251,9 @@ function setSelected(
|
||||||
} else {
|
} else {
|
||||||
option.selected = value.has(optionValue)
|
option.selected = value.has(optionValue)
|
||||||
}
|
}
|
||||||
} else {
|
} else if (looseEqual(getValue(option), value)) {
|
||||||
if (looseEqual(getValue(option), value)) {
|
if (el.selectedIndex !== i) el.selectedIndex = i
|
||||||
if (el.selectedIndex !== i) el.selectedIndex = i
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isMultiple && el.selectedIndex !== -1) {
|
if (!isMultiple && el.selectedIndex !== -1) {
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import type { ObjectDirective } from '@vue/runtime-core'
|
import type { ObjectDirective } from '@vue/runtime-core'
|
||||||
|
|
||||||
export const vShowOldKey = Symbol('_vod')
|
export const vShowOriginalDisplay = Symbol('_vod')
|
||||||
|
export const vShowHidden = Symbol('_vsh')
|
||||||
|
|
||||||
interface VShowElement extends HTMLElement {
|
export interface VShowElement extends HTMLElement {
|
||||||
// _vod = vue original display
|
// _vod = vue original display
|
||||||
[vShowOldKey]: string
|
[vShowOriginalDisplay]: string
|
||||||
|
[vShowHidden]: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const vShow: ObjectDirective<VShowElement> & { name?: 'show' } = {
|
export const vShow: ObjectDirective<VShowElement> & { name?: 'show' } = {
|
||||||
beforeMount(el, { value }, { transition }) {
|
beforeMount(el, { value }, { transition }) {
|
||||||
el[vShowOldKey] = el.style.display === 'none' ? '' : el.style.display
|
el[vShowOriginalDisplay] =
|
||||||
|
el.style.display === 'none' ? '' : el.style.display
|
||||||
if (transition && value) {
|
if (transition && value) {
|
||||||
transition.beforeEnter(el)
|
transition.beforeEnter(el)
|
||||||
} else {
|
} else {
|
||||||
|
@ -22,11 +25,7 @@ export const vShow: ObjectDirective<VShowElement> & { name?: 'show' } = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updated(el, { value, oldValue }, { transition }) {
|
updated(el, { value, oldValue }, { transition }) {
|
||||||
if (
|
if (!value === !oldValue) return
|
||||||
!value === !oldValue &&
|
|
||||||
(el.style.display === el[vShowOldKey] || !value)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
if (transition) {
|
if (transition) {
|
||||||
if (value) {
|
if (value) {
|
||||||
transition.beforeEnter(el)
|
transition.beforeEnter(el)
|
||||||
|
@ -51,7 +50,8 @@ if (__DEV__) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDisplay(el: VShowElement, value: unknown): void {
|
function setDisplay(el: VShowElement, value: unknown): void {
|
||||||
el.style.display = value ? el[vShowOldKey] : 'none'
|
el.style.display = value ? el[vShowOriginalDisplay] : 'none'
|
||||||
|
el[vShowHidden] = !value
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSR vnode transforms, only used when user includes client-oriented render
|
// SSR vnode transforms, only used when user includes client-oriented render
|
||||||
|
|
|
@ -39,7 +39,8 @@ export function patchDOMProp(
|
||||||
el._value = value
|
el._value = value
|
||||||
// #4956: <option> value will fallback to its text content so we need to
|
// #4956: <option> value will fallback to its text content so we need to
|
||||||
// compare against its attribute value instead.
|
// compare against its attribute value instead.
|
||||||
const oldValue = tag === 'OPTION' ? el.getAttribute('value') : el.value
|
const oldValue =
|
||||||
|
tag === 'OPTION' ? el.getAttribute('value') || '' : el.value
|
||||||
const newValue = value == null ? '' : value
|
const newValue = value == null ? '' : value
|
||||||
if (oldValue !== newValue) {
|
if (oldValue !== newValue) {
|
||||||
el.value = newValue
|
el.value = newValue
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import { capitalize, hyphenate, isArray, isString } from '@vue/shared'
|
import { capitalize, hyphenate, isArray, isString } from '@vue/shared'
|
||||||
import { camelize, warn } from '@vue/runtime-core'
|
import { camelize, warn } from '@vue/runtime-core'
|
||||||
import { vShowOldKey } from '../directives/vShow'
|
import {
|
||||||
|
type VShowElement,
|
||||||
|
vShowHidden,
|
||||||
|
vShowOriginalDisplay,
|
||||||
|
} from '../directives/vShow'
|
||||||
import { CSS_VAR_TEXT } from '../helpers/useCssVars'
|
import { CSS_VAR_TEXT } from '../helpers/useCssVars'
|
||||||
|
|
||||||
type Style = string | Record<string, string | string[]> | null
|
type Style = string | Record<string, string | string[]> | null
|
||||||
|
@ -10,13 +14,21 @@ const displayRE = /(^|;)\s*display\s*:/
|
||||||
export function patchStyle(el: Element, prev: Style, next: Style) {
|
export function patchStyle(el: Element, prev: Style, next: Style) {
|
||||||
const style = (el as HTMLElement).style
|
const style = (el as HTMLElement).style
|
||||||
const isCssString = isString(next)
|
const isCssString = isString(next)
|
||||||
const currentDisplay = style.display
|
|
||||||
let hasControlledDisplay = false
|
let hasControlledDisplay = false
|
||||||
if (next && !isCssString) {
|
if (next && !isCssString) {
|
||||||
if (prev && !isString(prev)) {
|
if (prev) {
|
||||||
for (const key in prev) {
|
if (!isString(prev)) {
|
||||||
if (next[key] == null) {
|
for (const key in prev) {
|
||||||
setStyle(style, key, '')
|
if (next[key] == null) {
|
||||||
|
setStyle(style, key, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const prevStyle of prev.split(';')) {
|
||||||
|
const key = prevStyle.slice(0, prevStyle.indexOf(':')).trim()
|
||||||
|
if (next[key] == null) {
|
||||||
|
setStyle(style, key, '')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,12 +53,14 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
|
||||||
el.removeAttribute('style')
|
el.removeAttribute('style')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// indicates that the `display` of the element is controlled by `v-show`,
|
// indicates the element also has `v-show`.
|
||||||
// so we always keep the current `display` value regardless of the `style`
|
if (vShowOriginalDisplay in el) {
|
||||||
// value, thus handing over control to `v-show`.
|
// make v-show respect the current v-bind style display when shown
|
||||||
if (vShowOldKey in el) {
|
el[vShowOriginalDisplay] = hasControlledDisplay ? style.display : ''
|
||||||
el[vShowOldKey] = hasControlledDisplay ? style.display : ''
|
// if v-show is in hidden state, v-show has higher priority
|
||||||
style.display = currentDisplay
|
if ((el as VShowElement)[vShowHidden]) {
|
||||||
|
style.display = 'none'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/server-renderer",
|
"name": "@vue/server-renderer",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "@vue/server-renderer",
|
"description": "@vue/server-renderer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/server-renderer.esm-bundler.js",
|
"module": "dist/server-renderer.esm-bundler.js",
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
<link rel="icon" type="image/svg" href="/logo.svg" />
|
<link rel="icon" type="image/svg" href="/logo.svg" />
|
||||||
<title>Vue SFC Playground</title>
|
<title>Vue SFC Playground</title>
|
||||||
<script>
|
<script>
|
||||||
// process shim for old versions of @vue/compiler-sfc dependency
|
|
||||||
window.process = { env: {} }
|
|
||||||
const savedPreferDark = localStorage.getItem('vue-sfc-playground-prefer-dark')
|
const savedPreferDark = localStorage.getItem('vue-sfc-playground-prefer-dark')
|
||||||
if (
|
if (
|
||||||
savedPreferDark === 'true' ||
|
savedPreferDark === 'true' ||
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
"serve": "vite preview"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"vite": "^5.0.12"
|
"vite": "^5.1.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/repl": "^3.1.1",
|
"@vue/repl": "^4.1.1",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"vue": "workspace:*"
|
"vue": "workspace:*"
|
||||||
|
|
|
@ -1,22 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Header from './Header.vue'
|
import Header from './Header.vue'
|
||||||
import { Repl, ReplStore, SFCOptions } from '@vue/repl'
|
import { Repl, useStore, SFCOptions, useVueImportMap } from '@vue/repl'
|
||||||
import type Monaco from '@vue/repl/monaco-editor'
|
import Monaco from '@vue/repl/monaco-editor'
|
||||||
import type CodeMirror from '@vue/repl/codemirror-editor'
|
import { ref, watchEffect, onMounted, computed } from 'vue'
|
||||||
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 replRef = ref<InstanceType<typeof Repl>>()
|
const replRef = ref<InstanceType<typeof Repl>>()
|
||||||
|
|
||||||
|
@ -26,78 +12,80 @@ const setVH = () => {
|
||||||
window.addEventListener('resize', setVH)
|
window.addEventListener('resize', setVH)
|
||||||
setVH()
|
setVH()
|
||||||
|
|
||||||
const useProdMode = ref(false)
|
|
||||||
const useSSRMode = ref(false)
|
const useSSRMode = ref(false)
|
||||||
|
|
||||||
|
const { productionMode, vueVersion, importMap } = useVueImportMap({
|
||||||
|
runtimeDev: import.meta.env.PROD
|
||||||
|
? `${location.origin}/vue.runtime.esm-browser.js`
|
||||||
|
: `${location.origin}/src/vue-dev-proxy`,
|
||||||
|
runtimeProd: import.meta.env.PROD
|
||||||
|
? `${location.origin}/vue.runtime.esm-browser.prod.js`
|
||||||
|
: `${location.origin}/src/vue-dev-proxy-prod`,
|
||||||
|
serverRenderer: import.meta.env.PROD
|
||||||
|
? `${location.origin}/server-renderer.esm-browser.js`
|
||||||
|
: `${location.origin}/src/vue-server-renderer-dev-proxy`,
|
||||||
|
})
|
||||||
|
|
||||||
let hash = location.hash.slice(1)
|
let hash = location.hash.slice(1)
|
||||||
if (hash.startsWith('__DEV__')) {
|
if (hash.startsWith('__DEV__')) {
|
||||||
hash = hash.slice(7)
|
hash = hash.slice(7)
|
||||||
useProdMode.value = false
|
productionMode.value = false
|
||||||
}
|
}
|
||||||
if (hash.startsWith('__PROD__')) {
|
if (hash.startsWith('__PROD__')) {
|
||||||
hash = hash.slice(8)
|
hash = hash.slice(8)
|
||||||
useProdMode.value = true
|
productionMode.value = true
|
||||||
}
|
}
|
||||||
if (hash.startsWith('__SSR__')) {
|
if (hash.startsWith('__SSR__')) {
|
||||||
hash = hash.slice(7)
|
hash = hash.slice(7)
|
||||||
useSSRMode.value = true
|
useSSRMode.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = new ReplStore({
|
|
||||||
serializedState: hash,
|
|
||||||
productionMode: useProdMode.value,
|
|
||||||
defaultVueRuntimeURL: import.meta.env.PROD
|
|
||||||
? `${location.origin}/vue.runtime.esm-browser.js`
|
|
||||||
: `${location.origin}/src/vue-dev-proxy`,
|
|
||||||
defaultVueRuntimeProdURL: import.meta.env.PROD
|
|
||||||
? `${location.origin}/vue.runtime.esm-browser.prod.js`
|
|
||||||
: `${location.origin}/src/vue-dev-proxy-prod`,
|
|
||||||
defaultVueServerRendererURL: import.meta.env.PROD
|
|
||||||
? `${location.origin}/server-renderer.esm-browser.js`
|
|
||||||
: `${location.origin}/src/vue-server-renderer-dev-proxy`,
|
|
||||||
})
|
|
||||||
|
|
||||||
// enable experimental features
|
// enable experimental features
|
||||||
const sfcOptions: SFCOptions = {
|
const sfcOptions = computed(
|
||||||
script: {
|
(): SFCOptions => ({
|
||||||
inlineTemplate: useProdMode.value,
|
script: {
|
||||||
isProd: useProdMode.value,
|
inlineTemplate: productionMode.value,
|
||||||
propsDestructure: true,
|
isProd: productionMode.value,
|
||||||
},
|
propsDestructure: true,
|
||||||
style: {
|
|
||||||
isProd: useProdMode.value,
|
|
||||||
},
|
|
||||||
template: {
|
|
||||||
isProd: useProdMode.value,
|
|
||||||
compilerOptions: {
|
|
||||||
isCustomElement: (tag: string) => tag === 'mjx-container',
|
|
||||||
},
|
},
|
||||||
|
style: {
|
||||||
|
isProd: productionMode.value,
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
isProd: productionMode.value,
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag: string) => tag === 'mjx-container',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
const store = useStore(
|
||||||
|
{
|
||||||
|
builtinImportMap: importMap,
|
||||||
|
vueVersion,
|
||||||
|
sfcOptions,
|
||||||
},
|
},
|
||||||
}
|
hash,
|
||||||
|
)
|
||||||
|
// @ts-expect-error
|
||||||
|
globalThis.store = store
|
||||||
|
|
||||||
// persist state
|
// persist state
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const newHash = store
|
const newHash = store
|
||||||
.serialize()
|
.serialize()
|
||||||
.replace(/^#/, useSSRMode.value ? `#__SSR__` : `#`)
|
.replace(/^#/, useSSRMode.value ? `#__SSR__` : `#`)
|
||||||
.replace(/^#/, useProdMode.value ? `#__PROD__` : `#`)
|
.replace(/^#/, productionMode.value ? `#__PROD__` : `#`)
|
||||||
history.replaceState({}, '', newHash)
|
history.replaceState({}, '', newHash)
|
||||||
})
|
})
|
||||||
|
|
||||||
function toggleProdMode() {
|
function toggleProdMode() {
|
||||||
const isProd = (useProdMode.value = !useProdMode.value)
|
productionMode.value = !productionMode.value
|
||||||
sfcOptions.script!.inlineTemplate =
|
|
||||||
sfcOptions.script!.isProd =
|
|
||||||
sfcOptions.template!.isProd =
|
|
||||||
sfcOptions.style!.isProd =
|
|
||||||
isProd
|
|
||||||
store.toggleProduction()
|
|
||||||
store.setFiles(store.getFiles())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSSR() {
|
function toggleSSR() {
|
||||||
useSSRMode.value = !useSSRMode.value
|
useSSRMode.value = !useSSRMode.value
|
||||||
store.setFiles(store.getFiles())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadPage() {
|
function reloadPage() {
|
||||||
|
@ -111,13 +99,16 @@ function toggleTheme(isDark: boolean) {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const cls = document.documentElement.classList
|
const cls = document.documentElement.classList
|
||||||
toggleTheme(cls.contains('dark'))
|
toggleTheme(cls.contains('dark'))
|
||||||
|
|
||||||
|
// @ts-expect-error process shim for old versions of @vue/compiler-sfc dependency
|
||||||
|
window.process = { env: {} }
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Header
|
<Header
|
||||||
:store="store"
|
:store="store"
|
||||||
:prod="useProdMode"
|
:prod="productionMode"
|
||||||
:ssr="useSSRMode"
|
:ssr="useSSRMode"
|
||||||
@toggle-theme="toggleTheme"
|
@toggle-theme="toggleTheme"
|
||||||
@toggle-prod="toggleProdMode"
|
@toggle-prod="toggleProdMode"
|
||||||
|
@ -125,17 +116,15 @@ onMounted(() => {
|
||||||
@reload-page="reloadPage"
|
@reload-page="reloadPage"
|
||||||
/>
|
/>
|
||||||
<Repl
|
<Repl
|
||||||
v-if="EditorComponent"
|
|
||||||
ref="replRef"
|
ref="replRef"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
:editor="EditorComponent"
|
:editor="Monaco"
|
||||||
@keydown.ctrl.s.prevent
|
@keydown.ctrl.s.prevent
|
||||||
@keydown.meta.s.prevent
|
@keydown.meta.s.prevent
|
||||||
:ssr="useSSRMode"
|
:ssr="useSSRMode"
|
||||||
:store="store"
|
:store="store"
|
||||||
:showCompileOutput="true"
|
:showCompileOutput="true"
|
||||||
:autoResize="true"
|
:autoResize="true"
|
||||||
:sfcOptions="sfcOptions"
|
|
||||||
:clearConsole="false"
|
:clearConsole="false"
|
||||||
:preview-options="{
|
:preview-options="{
|
||||||
customCode: {
|
customCode: {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import type { ReplStore } from '@vue/repl'
|
||||||
import { downloadProject } from './download/download'
|
import { downloadProject } from './download/download'
|
||||||
import { ref } from 'vue'
|
|
||||||
import Sun from './icons/Sun.vue'
|
import Sun from './icons/Sun.vue'
|
||||||
import Moon from './icons/Moon.vue'
|
import Moon from './icons/Moon.vue'
|
||||||
import Share from './icons/Share.vue'
|
import Share from './icons/Share.vue'
|
||||||
import Download from './icons/Download.vue'
|
import Download from './icons/Download.vue'
|
||||||
import GitHub from './icons/GitHub.vue'
|
import GitHub from './icons/GitHub.vue'
|
||||||
import Reload from './icons/Reload.vue'
|
import Reload from './icons/Reload.vue'
|
||||||
import type { ReplStore } from '@vue/repl'
|
|
||||||
import VersionSelect from './VersionSelect.vue'
|
import VersionSelect from './VersionSelect.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -25,23 +25,20 @@ const emit = defineEmits([
|
||||||
const { store } = props
|
const { store } = props
|
||||||
|
|
||||||
const currentCommit = __COMMIT__
|
const currentCommit = __COMMIT__
|
||||||
const vueVersion = ref(`@${currentCommit}`)
|
|
||||||
|
|
||||||
const vueURL = store.getImportMap().imports.vue
|
const vueVersion = computed(() => {
|
||||||
if (vueURL && !vueURL.startsWith(location.origin)) {
|
if (store.loading) {
|
||||||
const versionMatch = vueURL.match(/runtime-dom@([^/]+)/)
|
return 'loading...'
|
||||||
if (versionMatch) vueVersion.value = versionMatch[1]
|
}
|
||||||
}
|
return store.vueVersion || `@${__COMMIT__}`
|
||||||
|
})
|
||||||
|
|
||||||
async function setVueVersion(v: string) {
|
async function setVueVersion(v: string) {
|
||||||
vueVersion.value = `loading...`
|
store.vueVersion = v
|
||||||
await store.setVueVersion(v)
|
|
||||||
vueVersion.value = v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetVueVersion() {
|
function resetVueVersion() {
|
||||||
store.resetVueVersion()
|
store.vueVersion = null
|
||||||
vueVersion.value = `@${currentCommit}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyLink(e: MouseEvent) {
|
async function copyLink(e: MouseEvent) {
|
||||||
|
@ -73,7 +70,7 @@ function toggleDark() {
|
||||||
</h1>
|
</h1>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<VersionSelect
|
<VersionSelect
|
||||||
v-model="store.state.typescriptVersion"
|
v-model="store.typescriptVersion"
|
||||||
pkg="typescript"
|
pkg="typescript"
|
||||||
label="TypeScript Version"
|
label="TypeScript Version"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"vue": "^3.4.0"
|
"vue": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"vite": "^5.0.12"
|
"vite": "^5.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/shared",
|
"name": "@vue/shared",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "internal utils shared across @vue packages",
|
"description": "internal utils shared across @vue packages",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/shared.esm-bundler.js",
|
"module": "dist/shared.esm-bundler.js",
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"enableNonBrowserBranches": true
|
"enableNonBrowserBranches": true
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"monaco-editor": "^0.45.0",
|
"monaco-editor": "^0.46.0",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compat",
|
"name": "@vue/compat",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "Vue 3 compatibility build for Vue 2",
|
"description": "Vue 3 compatibility build for Vue 2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/vue.runtime.esm-bundler.js",
|
"module": "dist/vue.runtime.esm-bundler.js",
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const E2E_TIMEOUT = 30 * 1000
|
||||||
|
|
||||||
const puppeteerOptions: PuppeteerLaunchOptions = {
|
const puppeteerOptions: PuppeteerLaunchOptions = {
|
||||||
args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [],
|
args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [],
|
||||||
headless: 'new',
|
headless: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxTries = 30
|
const maxTries = 30
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vue",
|
"name": "vue",
|
||||||
"version": "3.4.19",
|
"version": "3.4.20",
|
||||||
"description": "The progressive JavaScript framework for building modern web UI.",
|
"description": "The progressive JavaScript framework for building modern web UI.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/vue.runtime.esm-bundler.js",
|
"module": "dist/vue.runtime.esm-bundler.js",
|
||||||
|
|
993
pnpm-lock.yaml
993
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -143,6 +143,8 @@ function createConfig(format, output, plugins = []) {
|
||||||
}
|
}
|
||||||
output.sourcemap = !!process.env.SOURCE_MAP
|
output.sourcemap = !!process.env.SOURCE_MAP
|
||||||
output.externalLiveBindings = false
|
output.externalLiveBindings = false
|
||||||
|
// https://github.com/rollup/rollup/pull/5380
|
||||||
|
output.reexportProtoFromExternal = false
|
||||||
|
|
||||||
if (isGlobalBuild) {
|
if (isGlobalBuild) {
|
||||||
output.name = packageOptions.name
|
output.name = packageOptions.name
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"lib": ["esnext", "dom"],
|
"lib": ["es2016", "dom"],
|
||||||
"types": ["vitest/globals", "puppeteer", "node"],
|
"types": ["vitest/globals", "puppeteer", "node"],
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|
Loading…
Reference in New Issue