mirror of https://github.com/vuejs/core.git
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
98b701c82c
|
@ -1,4 +0,0 @@
|
|||
node_modules
|
||||
dist
|
||||
temp
|
||||
coverage
|
144
.eslintrc.cjs
144
.eslintrc.cjs
|
@ -1,144 +0,0 @@
|
|||
const { builtinModules } = require('node:module')
|
||||
const DOMGlobals = ['window', 'document']
|
||||
const NodeGlobals = ['module', 'require']
|
||||
|
||||
const banConstEnum = {
|
||||
selector: 'TSEnumDeclaration[const=true]',
|
||||
message:
|
||||
'Please use non-const enums. This project automatically inlines enums.',
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import('eslint-define-config').ESLintConfig}
|
||||
*/
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['jest', 'import', '@typescript-eslint'],
|
||||
rules: {
|
||||
'no-debugger': 'error',
|
||||
'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
|
||||
// most of the codebase are expected to be env agnostic
|
||||
'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],
|
||||
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
banConstEnum,
|
||||
{
|
||||
selector: 'ObjectPattern > RestElement',
|
||||
message:
|
||||
'Our output target is ES2016, and object rest spread results in ' +
|
||||
'verbose helpers and should be avoided.',
|
||||
},
|
||||
{
|
||||
selector: 'ObjectExpression > SpreadElement',
|
||||
message:
|
||||
'esbuild transpiles object spread into very verbose inline helpers.\n' +
|
||||
'Please use the `extend` helper from @vue/shared instead.',
|
||||
},
|
||||
{
|
||||
selector: 'AwaitExpression',
|
||||
message:
|
||||
'Our output target is ES2016, so async/await syntax should be avoided.',
|
||||
},
|
||||
],
|
||||
'sort-imports': ['error', { ignoreDeclarationSort: true }],
|
||||
|
||||
'import/no-nodejs-modules': [
|
||||
'error',
|
||||
{ allow: builtinModules.map(mod => `node:${mod}`) },
|
||||
],
|
||||
// This rule enforces the preference for using '@ts-expect-error' comments in TypeScript
|
||||
// code to indicate intentional type errors, improving code clarity and maintainability.
|
||||
'@typescript-eslint/prefer-ts-expect-error': 'error',
|
||||
// Enforce the use of 'import type' for importing types
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{
|
||||
fixStyle: 'inline-type-imports',
|
||||
disallowTypeAnnotations: false,
|
||||
},
|
||||
],
|
||||
// Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers
|
||||
'@typescript-eslint/no-import-type-side-effects': 'error',
|
||||
},
|
||||
overrides: [
|
||||
// tests, no restrictions (runs in Node / jest with jsdom)
|
||||
{
|
||||
files: ['**/__tests__/**', 'packages/dts-test/**'],
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'jest/no-disabled-tests': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
},
|
||||
},
|
||||
// shared, may be used in any env
|
||||
{
|
||||
files: ['packages/shared/**', '.eslintrc.cjs'],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
},
|
||||
},
|
||||
// Packages targeting DOM
|
||||
{
|
||||
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
},
|
||||
},
|
||||
// Packages targeting Node
|
||||
{
|
||||
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...DOMGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
},
|
||||
},
|
||||
// Private package, browser only + no syntax restrictions
|
||||
{
|
||||
files: [
|
||||
'packages/template-explorer/**',
|
||||
'packages/sfc-playground/**',
|
||||
'playground/**',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
// JavaScript files
|
||||
{
|
||||
files: ['*.js', '*.cjs'],
|
||||
rules: {
|
||||
// We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.
|
||||
'no-unused-vars': ['error', { vars: 'all', args: 'none' }],
|
||||
},
|
||||
},
|
||||
// Node scripts
|
||||
{
|
||||
files: [
|
||||
'scripts/**',
|
||||
'./*.{js,ts}',
|
||||
'packages/*/*.js',
|
||||
'packages/vue/*/*.js',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
// Import nodejs modules in compiler-sfc
|
||||
{
|
||||
files: ['packages/compiler-sfc/src/**'],
|
||||
rules: {
|
||||
'import/no-nodejs-modules': ['error', { allow: builtinModules }],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
|
@ -34,7 +34,7 @@
|
|||
{
|
||||
groupName: 'lint',
|
||||
matchPackageNames: ['simple-git-hooks', 'lint-staged'],
|
||||
matchPackagePrefixes: ['@typescript-eslint', 'eslint', 'prettier'],
|
||||
matchPackagePrefixes: ['typescript-eslint', 'eslint', 'prettier'],
|
||||
},
|
||||
],
|
||||
ignoreDeps: [
|
||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
|||
## [3.4.23](https://github.com/vuejs/core/compare/v3.4.22...v3.4.23) (2024-04-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **runtime-core:** fix regression for $attrs tracking in slots ([6930e60](https://github.com/vuejs/core/commit/6930e60787e4905a50417190263ae7dd46cf5409)), closes [#10710](https://github.com/vuejs/core/issues/10710)
|
||||
* **runtime-core:** use same internal object mechanism for slots ([6df53d8](https://github.com/vuejs/core/commit/6df53d85a207986128159d88565e6e7045db2add)), closes [#10709](https://github.com/vuejs/core/issues/10709)
|
||||
|
||||
|
||||
|
||||
## [3.4.22](https://github.com/vuejs/core/compare/v3.4.21...v3.4.22) (2024-04-15)
|
||||
|
||||
|
||||
|
|
|
@ -5,3 +5,9 @@ To report a vulnerability, please email security@vuejs.org.
|
|||
While the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Vue and its official companion libraries to ensure your application remains as secure as possible.
|
||||
|
||||
Please note that we do not consider XSS via template expressions a valid attack vector, because it can only happen if the user intentionally uses untrusted content as template compilation source. This is similar to knowingly pasting untrusted scripts into a browser console. We explicitly warn users against using untrusted content as template compilation source in our documentation.
|
||||
|
||||
## Security Hall of Fame
|
||||
|
||||
We would like to thank the following security researchers for responsibly disclosing security issues to us.
|
||||
|
||||
- Jeet Pal - [GitHub](https://github.com/jeetpal2007) | [Email](jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290 )
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
import importX from 'eslint-plugin-import-x'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import vitest from 'eslint-plugin-vitest'
|
||||
import { builtinModules } from 'node:module'
|
||||
|
||||
const DOMGlobals = ['window', 'document']
|
||||
const NodeGlobals = ['module', 'require']
|
||||
|
||||
const banConstEnum = {
|
||||
selector: 'TSEnumDeclaration[const=true]',
|
||||
message:
|
||||
'Please use non-const enums. This project automatically inlines enums.',
|
||||
}
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
|
||||
extends: [tseslint.configs.base],
|
||||
plugins: {
|
||||
'import-x': importX,
|
||||
},
|
||||
rules: {
|
||||
'no-debugger': 'error',
|
||||
'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
|
||||
// most of the codebase are expected to be env agnostic
|
||||
'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],
|
||||
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
banConstEnum,
|
||||
{
|
||||
selector: 'ObjectPattern > RestElement',
|
||||
message:
|
||||
'Our output target is ES2016, and object rest spread results in ' +
|
||||
'verbose helpers and should be avoided.',
|
||||
},
|
||||
{
|
||||
selector: 'ObjectExpression > SpreadElement',
|
||||
message:
|
||||
'esbuild transpiles object spread into very verbose inline helpers.\n' +
|
||||
'Please use the `extend` helper from @vue/shared instead.',
|
||||
},
|
||||
{
|
||||
selector: 'AwaitExpression',
|
||||
message:
|
||||
'Our output target is ES2016, so async/await syntax should be avoided.',
|
||||
},
|
||||
],
|
||||
'sort-imports': ['error', { ignoreDeclarationSort: true }],
|
||||
|
||||
'import-x/no-nodejs-modules': [
|
||||
'error',
|
||||
{ allow: builtinModules.map(mod => `node:${mod}`) },
|
||||
],
|
||||
// This rule enforces the preference for using '@ts-expect-error' comments in TypeScript
|
||||
// code to indicate intentional type errors, improving code clarity and maintainability.
|
||||
'@typescript-eslint/prefer-ts-expect-error': 'error',
|
||||
// Enforce the use of 'import type' for importing types
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{
|
||||
fixStyle: 'inline-type-imports',
|
||||
disallowTypeAnnotations: false,
|
||||
},
|
||||
],
|
||||
// Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers
|
||||
'@typescript-eslint/no-import-type-side-effects': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// tests, no restrictions (runs in Node / Vitest with jsdom)
|
||||
{
|
||||
files: ['**/__tests__/**', 'packages/dts-test/**'],
|
||||
plugins: { vitest },
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...vitest.environments.env.globals,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'vitest/no-disabled-tests': 'error',
|
||||
'vitest/no-focused-tests': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// shared, may be used in any env
|
||||
{
|
||||
files: ['packages/shared/**', 'eslint.config.js'],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Packages targeting DOM
|
||||
{
|
||||
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
},
|
||||
},
|
||||
|
||||
// Packages targeting Node
|
||||
{
|
||||
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...DOMGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
},
|
||||
},
|
||||
|
||||
// Private package, browser only + no syntax restrictions
|
||||
{
|
||||
files: [
|
||||
'packages/template-explorer/**',
|
||||
'packages/sfc-playground/**',
|
||||
'playground/**',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// JavaScript files
|
||||
{
|
||||
files: ['*.js'],
|
||||
rules: {
|
||||
// We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.
|
||||
'no-unused-vars': ['error', { vars: 'all', args: 'none' }],
|
||||
},
|
||||
},
|
||||
|
||||
// Node scripts
|
||||
{
|
||||
files: [
|
||||
'eslint.config.js',
|
||||
'rollup.config.js',
|
||||
'scripts/**',
|
||||
'./*.{js,ts}',
|
||||
'packages/*/*.js',
|
||||
'packages/vue/*/*.js',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Import nodejs modules in compiler-sfc
|
||||
{
|
||||
files: ['packages/compiler-sfc/src/**'],
|
||||
rules: {
|
||||
'import-x/no-nodejs-modules': ['error', { allow: builtinModules }],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
ignores: [
|
||||
'**/dist/',
|
||||
'**/temp/',
|
||||
'**/coverage/',
|
||||
'.idea/',
|
||||
'explorations/',
|
||||
'dts-build/packages',
|
||||
],
|
||||
},
|
||||
)
|
25
package.json
25
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"private": true,
|
||||
"version": "3.0.0-vapor",
|
||||
"packageManager": "pnpm@8.15.4",
|
||||
"packageManager": "pnpm@9.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "node scripts/dev.js vue vue-vapor",
|
||||
|
@ -13,7 +13,7 @@
|
|||
"size-esm-runtime": "node scripts/build.js vue vue-vapor -f esm-bundler-runtime",
|
||||
"size-esm": "node scripts/build.js runtime-dom runtime-vapor runtime-core reactivity shared -f esm-bundler",
|
||||
"check": "tsc --incremental --noEmit",
|
||||
"lint": "eslint --cache --ext .js,.ts,.tsx . --ignore-path .gitignore",
|
||||
"lint": "eslint --cache .",
|
||||
"format": "prettier --write --cache .",
|
||||
"format-check": "prettier --check --cache .",
|
||||
"test": "vitest",
|
||||
|
@ -72,8 +72,6 @@
|
|||
"@types/minimist": "^1.2.5",
|
||||
"@types/node": "^20.12.5",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
||||
"@typescript-eslint/parser": "^7.4.0",
|
||||
"@vitest/coverage-istanbul": "^1.4.0",
|
||||
"@vitest/ui": "^1.4.0",
|
||||
"@vue/consolidate": "1.0.0",
|
||||
|
@ -81,10 +79,9 @@
|
|||
"enquirer": "^2.4.1",
|
||||
"esbuild": "^0.20.2",
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-define-config": "^2.1.0",
|
||||
"eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
"eslint": "^9.0.0",
|
||||
"eslint-plugin-import-x": "^0.5.0",
|
||||
"eslint-plugin-vitest": "^0.5.3",
|
||||
"estree-walker": "^2.0.2",
|
||||
"execa": "^8.0.1",
|
||||
"jsdom": "^24.0.0",
|
||||
|
@ -113,7 +110,19 @@
|
|||
"tslib": "^2.6.2",
|
||||
"tsx": "^4.7.2",
|
||||
"typescript": "~5.4.5",
|
||||
"typescript-eslint": "^7.6.0",
|
||||
"vite": "^5.2.7",
|
||||
"vitest": "^1.4.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
"allowedVersions": {
|
||||
"typescript-eslint>eslint": "^9.0.0",
|
||||
"@typescript-eslint/eslint-plugin>eslint": "^9.0.0",
|
||||
"@typescript-eslint/parser>eslint": "^9.0.0",
|
||||
"@typescript-eslint/type-utils>eslint": "^9.0.0",
|
||||
"@typescript-eslint/utils>eslint": "^9.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ import {
|
|||
import { baseParse } from '../src/parser'
|
||||
import type { Program } from '@babel/types'
|
||||
|
||||
/* eslint jest/no-disabled-tests: "off" */
|
||||
|
||||
describe('compiler: parse', () => {
|
||||
describe('Text', () => {
|
||||
test('simple text', () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/compiler-core",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/compiler-core",
|
||||
"main": "index.js",
|
||||
"module": "dist/compiler-core.esm-bundler.js",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/compiler-dom",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/compiler-dom",
|
||||
"main": "index.js",
|
||||
"module": "dist/compiler-dom.esm-bundler.js",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/compiler-sfc",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/compiler-sfc",
|
||||
"main": "dist/compiler-sfc.cjs.js",
|
||||
"module": "dist/compiler-sfc.esm-browser.js",
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('ssr: element', () => {
|
|||
test('v-html', () => {
|
||||
expect(getCompiledString(`<div v-html="foo"/>`)).toMatchInlineSnapshot(`
|
||||
"\`<div>\${
|
||||
_ctx.foo
|
||||
(_ctx.foo) ?? ''
|
||||
}</div>\`"
|
||||
`)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/compiler-ssr",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/compiler-ssr",
|
||||
"main": "dist/compiler-ssr.cjs.js",
|
||||
"types": "dist/compiler-ssr.d.ts",
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
createAssignmentExpression,
|
||||
createCallExpression,
|
||||
createCompilerError,
|
||||
createCompoundExpression,
|
||||
createConditionalExpression,
|
||||
createInterpolation,
|
||||
createSequenceExpression,
|
||||
|
@ -188,7 +189,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
|||
// special cases with children override
|
||||
if (prop.type === NodeTypes.DIRECTIVE) {
|
||||
if (prop.name === 'html' && prop.exp) {
|
||||
rawChildrenMap.set(node, prop.exp)
|
||||
rawChildrenMap.set(
|
||||
node,
|
||||
createCompoundExpression([`(`, prop.exp, `) ?? ''`]),
|
||||
)
|
||||
} else if (prop.name === 'text' && prop.exp) {
|
||||
node.children = [createInterpolation(prop.exp, prop.loc)]
|
||||
} else if (prop.name === 'slot') {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/reactivity",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/reactivity",
|
||||
"main": "index.js",
|
||||
"module": "dist/reactivity.esm-bundler.js",
|
||||
|
|
|
@ -1230,4 +1230,9 @@ describe('BaseTransition', () => {
|
|||
await runTestWithKeepAlive(testInOutBeforeFinish)
|
||||
})
|
||||
})
|
||||
|
||||
// #10719
|
||||
test('should not error on KeepAlive w/ function children', () => {
|
||||
expect(() => mount({}, () => () => h('div'), true)).not.toThrow()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
render,
|
||||
withModifiers,
|
||||
} from '@vue/runtime-dom'
|
||||
import { createApp } from 'vue'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
|
||||
describe('attribute fallthrough', () => {
|
||||
|
@ -783,4 +784,31 @@ describe('attribute fallthrough', () => {
|
|||
expect(textBar).toBe('from GrandChild')
|
||||
expect(textFoo).toBe('from Child')
|
||||
})
|
||||
|
||||
// covers uncaught regression #10710
|
||||
it('should track this.$attrs access in slots', async () => {
|
||||
const GrandChild = {
|
||||
template: `<slot/>`,
|
||||
}
|
||||
const Child = {
|
||||
components: { GrandChild },
|
||||
template: `<div><GrandChild>{{ $attrs.foo }}</GrandChild></div>`,
|
||||
}
|
||||
|
||||
const obj = ref(1)
|
||||
const App = {
|
||||
render() {
|
||||
return h(Child, { foo: obj.value })
|
||||
},
|
||||
}
|
||||
|
||||
const root = document.createElement('div')
|
||||
createApp(App).mount(root)
|
||||
|
||||
expect(root.innerHTML).toBe('<div foo="1">1</div>')
|
||||
|
||||
obj.value = 2
|
||||
await nextTick()
|
||||
expect(root.innerHTML).toBe('<div foo="2">2</div>')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/runtime-core",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/runtime-core",
|
||||
"main": "index.js",
|
||||
"module": "dist/runtime-core.esm-bundler.js",
|
||||
|
|
|
@ -38,6 +38,7 @@ import { createPropsDefaultThis } from './compat/props'
|
|||
import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'
|
||||
import { DeprecationTypes } from './compat/compatConfig'
|
||||
import { shouldSkipAttr } from './compat/attrsFallthrough'
|
||||
import { createInternalObject } from './internalObject'
|
||||
|
||||
export type ComponentPropsOptions<P = Data> =
|
||||
| ComponentObjectPropsOptions<P>
|
||||
|
@ -185,13 +186,6 @@ type NormalizedProp =
|
|||
export type NormalizedProps = Record<string, NormalizedProp>
|
||||
export type NormalizedPropsOptions = [NormalizedProps, string[]] | []
|
||||
|
||||
/**
|
||||
* Used during vnode props normalization to check if the vnode props is the
|
||||
* attrs object of a component via `Object.getPrototypeOf`. This is more
|
||||
* performant than defining a non-enumerable property.
|
||||
*/
|
||||
export const attrsProto = {}
|
||||
|
||||
export function initProps(
|
||||
instance: ComponentInternalInstance,
|
||||
rawProps: Data | null,
|
||||
|
@ -199,7 +193,7 @@ export function initProps(
|
|||
isSSR = false,
|
||||
) {
|
||||
const props: Data = {}
|
||||
const attrs: Data = Object.create(attrsProto)
|
||||
const attrs: Data = createInternalObject()
|
||||
|
||||
instance.propsDefaults = Object.create(null)
|
||||
|
||||
|
|
|
@ -367,9 +367,10 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||
// public $xxx properties
|
||||
if (publicGetter) {
|
||||
if (key === '$attrs') {
|
||||
track(instance, TrackOpTypes.GET, key)
|
||||
track(instance.attrs, TrackOpTypes.GET, '')
|
||||
__DEV__ && markAttrsAccessed()
|
||||
} else if (__DEV__ && key === '$slots') {
|
||||
// for HMR only
|
||||
track(instance, TrackOpTypes.GET, key)
|
||||
}
|
||||
return publicGetter(instance)
|
||||
|
|
|
@ -21,9 +21,8 @@ import { isKeepAlive } from './components/KeepAlive'
|
|||
import { type ContextualRenderFn, withCtx } from './componentRenderContext'
|
||||
import { isHmrUpdating } from './hmr'
|
||||
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
|
||||
import { toRaw } from '@vue/reactivity'
|
||||
import { trigger } from '@vue/reactivity'
|
||||
import { TriggerOpTypes } from '@vue/reactivity'
|
||||
import { TriggerOpTypes, trigger } from '@vue/reactivity'
|
||||
import { createInternalObject } from './internalObject'
|
||||
|
||||
export type Slot<T extends any = any> = (
|
||||
...args: IfAny<T, any[], [T] | (T extends undefined ? [] : never)>
|
||||
|
@ -166,26 +165,18 @@ export const initSlots = (
|
|||
instance: ComponentInternalInstance,
|
||||
children: VNodeNormalizedChildren,
|
||||
) => {
|
||||
const slots = (instance.slots = createInternalObject())
|
||||
if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
|
||||
const type = (children as RawSlots)._
|
||||
if (type) {
|
||||
// users can get the shallow readonly version of the slots object through `this.$slots`,
|
||||
// we should avoid the proxy object polluting the slots of the internal instance
|
||||
instance.slots = toRaw(children as InternalSlots)
|
||||
extend(slots, children as InternalSlots)
|
||||
// make compiler marker non-enumerable
|
||||
def(instance.slots, '_', type)
|
||||
def(slots, '_', type)
|
||||
} else {
|
||||
normalizeObjectSlots(
|
||||
children as RawSlots,
|
||||
(instance.slots = {}),
|
||||
instance,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
instance.slots = {}
|
||||
if (children) {
|
||||
normalizeVNodeSlots(instance, children)
|
||||
normalizeObjectSlots(children as RawSlots, slots, instance)
|
||||
}
|
||||
} else if (children) {
|
||||
normalizeVNodeSlots(instance, children)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import { warn } from '../warning'
|
|||
import { isKeepAlive } from './KeepAlive'
|
||||
import { SchedulerJobFlags, toRaw } from '@vue/reactivity'
|
||||
import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling'
|
||||
import { PatchFlags, ShapeFlags, isArray } from '@vue/shared'
|
||||
import { PatchFlags, ShapeFlags, isArray, isFunction } from '@vue/shared'
|
||||
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
|
||||
import type { RendererElement } from '../renderer'
|
||||
|
||||
|
@ -458,15 +458,27 @@ function emptyPlaceholder(vnode: VNode): VNode | undefined {
|
|||
}
|
||||
|
||||
function getKeepAliveChild(vnode: VNode): VNode | undefined {
|
||||
return isKeepAlive(vnode)
|
||||
? // #7121 ensure get the child component subtree in case
|
||||
// it's been replaced during HMR
|
||||
__DEV__ && vnode.component
|
||||
? vnode.component.subTree
|
||||
: vnode.children
|
||||
? ((vnode.children as VNodeArrayChildren)[0] as VNode)
|
||||
: undefined
|
||||
: vnode
|
||||
if (!isKeepAlive(vnode)) {
|
||||
return vnode
|
||||
}
|
||||
// #7121 ensure get the child component subtree in case
|
||||
// it's been replaced during HMR
|
||||
if (__DEV__ && vnode.component) {
|
||||
return vnode.component.subTree
|
||||
}
|
||||
|
||||
const { shapeFlag, children } = vnode
|
||||
|
||||
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||
return (children as VNodeArrayChildren)[0] as VNode
|
||||
}
|
||||
|
||||
if (
|
||||
shapeFlag & ShapeFlags.SLOTS_CHILDREN &&
|
||||
isFunction((children as any).default)
|
||||
) {
|
||||
return (children as any).default()
|
||||
}
|
||||
}
|
||||
|
||||
export function setTransitionHooks(vnode: VNode, hooks: TransitionHooks) {
|
||||
|
|
|
@ -814,7 +814,6 @@ function hydrateSuspense(
|
|||
suspense.resolve(false, true)
|
||||
}
|
||||
return result
|
||||
/* eslint-enable no-restricted-globals */
|
||||
}
|
||||
|
||||
function normalizeSuspenseChildren(vnode: VNode) {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Used during vnode props/slots normalization to check if the vnode props/slots
|
||||
* are the internal attrs / slots object of a component via
|
||||
* `Object.getPrototypeOf`. This is more performant than defining a
|
||||
* non-enumerable property. (one of the optimizations done for ssr-benchmark)
|
||||
*/
|
||||
const internalObjectProto = Object.create(null)
|
||||
|
||||
export const createInternalObject = () => Object.create(internalObjectProto)
|
||||
|
||||
export const isInternalObject = (obj: object) =>
|
||||
Object.getPrototypeOf(obj) === internalObjectProto
|
|
@ -55,7 +55,7 @@ import { convertLegacyVModelProps } from './compat/componentVModel'
|
|||
import { defineLegacyVNodeProperties } from './compat/renderFn'
|
||||
import { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'
|
||||
import type { ComponentPublicInstance } from './componentPublicInstance'
|
||||
import { attrsProto } from './componentProps'
|
||||
import { isInternalObject } from './internalObject'
|
||||
|
||||
export const Fragment = Symbol.for('v-fgt') as any as {
|
||||
__isFragment: true
|
||||
|
@ -617,9 +617,7 @@ function _createVNode(
|
|||
|
||||
export function guardReactiveProps(props: (Data & VNodeProps) | null) {
|
||||
if (!props) return null
|
||||
return isProxy(props) || Object.getPrototypeOf(props) === attrsProto
|
||||
? extend({}, props)
|
||||
: props
|
||||
return isProxy(props) || isInternalObject(props) ? extend({}, props) : props
|
||||
}
|
||||
|
||||
export function cloneVNode<T, U>(
|
||||
|
@ -791,7 +789,7 @@ export function normalizeChildren(vnode: VNode, children: unknown) {
|
|||
} else {
|
||||
type = ShapeFlags.SLOTS_CHILDREN
|
||||
const slotFlag = (children as RawSlots)._
|
||||
if (!slotFlag) {
|
||||
if (!slotFlag && !isInternalObject(children)) {
|
||||
// if slots are not normalized, attach context instance
|
||||
// (compiled / normalized slots already have context)
|
||||
;(children as RawSlots)._ctx = currentRenderingInstance
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/runtime-dom",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/runtime-dom",
|
||||
"main": "index.js",
|
||||
"module": "dist/runtime-dom.esm-bundler.js",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/server-renderer",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "@vue/server-renderer",
|
||||
"main": "index.js",
|
||||
"module": "dist/server-renderer.esm-bundler.js",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/shared",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "internal utils shared across @vue packages",
|
||||
"main": "index.js",
|
||||
"module": "dist/shared.esm-bundler.js",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vue/compat",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "Vue 3 compatibility build for Vue 2",
|
||||
"main": "index.js",
|
||||
"module": "dist/vue.runtime.esm-bundler.js",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "vue",
|
||||
"version": "3.4.22",
|
||||
"version": "3.4.23",
|
||||
"description": "The progressive JavaScript framework for building modern web UI.",
|
||||
"main": "index.js",
|
||||
"module": "dist/vue.runtime.esm-bundler.js",
|
||||
|
|
7983
pnpm-lock.yaml
7983
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -383,7 +383,7 @@ async function getCIResult() {
|
|||
)
|
||||
const data = await res.json()
|
||||
return data.workflow_runs.length > 0
|
||||
} catch (e) {
|
||||
} catch {
|
||||
console.error('Failed to get CI status for current commit.')
|
||||
return false
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ async function isInSyncWithRemote() {
|
|||
})
|
||||
return yes
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
console.error(
|
||||
pico.red('Failed to check whether local HEAD is up-to-date with remote.'),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue