diff --git a/CHANGELOG.md b/CHANGELOG.md index b289346e282..0385eed3b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,43 @@ +# [3.0.0-rc.13](https://github.com/vuejs/vue-next/compare/v3.0.0-rc.12...v3.0.0-rc.13) (2020-09-18) + + +### Bug Fixes + +* **hmr:** make hmr working with class components ([#2144](https://github.com/vuejs/vue-next/issues/2144)) ([422f05e](https://github.com/vuejs/vue-next/commit/422f05e085036e23ea3632c2ce75d86181a087b8)) +* **reactivity:** avoid length mutating array methods causing infinite updates ([#2138](https://github.com/vuejs/vue-next/issues/2138)) ([f316a33](https://github.com/vuejs/vue-next/commit/f316a332b055d3f448dc735365551d89041f1098)), closes [#2137](https://github.com/vuejs/vue-next/issues/2137) +* **suspense:** should discard unmount effects of invalidated pending branch ([5bfcad1](https://github.com/vuejs/vue-next/commit/5bfcad155b444b2f7ffaac171c1f61bc23909287)) +* **types:** component instance inference without props ([#2145](https://github.com/vuejs/vue-next/issues/2145)) ([57bdaa2](https://github.com/vuejs/vue-next/commit/57bdaa2220afefbde21118659c1ce2377d6b86d6)) + + +### Code Refactoring + +* watch APIs default to trigger pre-flush ([49bb447](https://github.com/vuejs/vue-next/commit/49bb44756fda0a7019c69f2fa6b880d9e41125aa)), closes [/github.com/vuejs/vue-next/issues/1706#issuecomment-666258948](https://github.com//github.com/vuejs/vue-next/issues/1706/issues/issuecomment-666258948) + + +### Features + +* **runtime-core:** support using inject() inside props default functions ([58c31e3](https://github.com/vuejs/vue-next/commit/58c31e36992d2647e5247de4904246fb2d6112ed)) +* **watch:** support dot-delimited path in watch option ([1c9a0b3](https://github.com/vuejs/vue-next/commit/1c9a0b3e195d144ac90d22d2cc2cef6a3fd8276d)) + + +### BREAKING CHANGES + +* watch APIs now default to use `flush: 'pre'` instead of +`flush: 'post'`. + + - This change affects `watch`, `watchEffect`, the `watch` component + option, and `this.$watch`. + + - As pointed out by @skirtles-code in + + + # [3.0.0-rc.12](https://github.com/vuejs/vue-next/compare/v3.0.0-rc.11...v3.0.0-rc.12) (2020-09-16) ### Bug Fixes -* **reactivity:** effect shoud only recursively self trigger with explicit options ([3810de7](https://github.com/vuejs/vue-next/commit/3810de7d6bd0044177f043285228c2e988093883)), closes [#2125](https://github.com/vuejs/vue-next/issues/2125) +* **reactivity:** effect should only recursively self trigger with explicit options ([3810de7](https://github.com/vuejs/vue-next/commit/3810de7d6bd0044177f043285228c2e988093883)), closes [#2125](https://github.com/vuejs/vue-next/issues/2125) * **runtime-core:** ensure root stable fragments inherit elements for moving ([bebd44f](https://github.com/vuejs/vue-next/commit/bebd44f793ccd13bfdf90c7e45eac320a340650c)), closes [#2134](https://github.com/vuejs/vue-next/issues/2134) * **runtime-core:** should still do full traverse of stable fragment children in dev + hmr ([dd40ad8](https://github.com/vuejs/vue-next/commit/dd40ad8fca47af0e1f0a963be2f48c23f7457952)) * **runtime-core/async-component:** fix error component when there are no error handlers ([c7b4a37](https://github.com/vuejs/vue-next/commit/c7b4a379cf8627c79a01d61039d3e3b283477dc1)), closes [#2129](https://github.com/vuejs/vue-next/issues/2129) diff --git a/README.md b/README.md index e2750cf8409..bc287c38d25 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,100 @@ # vue-next [![beta](https://img.shields.io/npm/v/vue/next.svg)](https://www.npmjs.com/package/vue/v/next) [![CircleCI](https://circleci.com/gh/vuejs/vue-next.svg?style=svg&circle-token=fb883a2d0a73df46e80b2e79fd430959d8f2b488)](https://circleci.com/gh/vuejs/vue-next) -## Status: Release Candidate +This is the repository for Vue 3.0. -- All planned RFCs have been merged. +## Quickstart -- All [merged RFCs](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3A3.x) have been implemented. +- Via CDN: `` +- In-browser playground on [Codepen](https://codepen.io/yyx990803/pen/OJNoaZL) +- Scaffold via [Vite](https://github.com/vitejs/vite): -- Vue CLI now has experimental support via [vue-cli-plugin-vue-next](https://github.com/vuejs/vue-cli-plugin-vue-next). + ```bash + npm init vite-app hello-vue3 # OR yarn create vite-app hello-vue3 + ``` -- There is also a simple plain webpack-based setup with Single-File Component support available [here](https://github.com/vuejs/vue-next-webpack-preview). +- Scaffold via [vue-cli](https://cli.vuejs.org/): -Please note that there could still be undocumented behavior inconsistencies with 2.x. When you run into such a case, please make sure to first check if the behavior difference has already been proposed in an existing RFC. If the inconsistency is not part of an RFC, then it's likely unintended, and an issue should be opened (please make sure to use the [issue helper](https://new-issue.vuejs.org/?repo=vuejs/vue-next) when opening new issues). + ```bash + npm install -g @vue/cli # OR yarn global add @vue/cli + vue create hello-vue3 + # select vue 3 preset + ``` -In addition, the current implementation requires native ES2015+ in the runtime environment and does not support IE11 (yet). The IE11 compatible build will be worked on after we have reached RC stage. +## Changes from Vue 2 -The documentation of Vue 3 can be found at https://v3.vuejs.org/ +Please consult the [Migration Guide](https://v3.vuejs.org/guide/migration/introduction.html). -## Status of the rest of the framework +- Note: IE11 support is still pending. + +## Supporting Libraries + +All of our official libraries and tools now support Vue 3, but most of them are still in beta status and distributed under the `next` dist tag on NPM. **We are planning to stabilize and switch all projects to use the `latest` dist tag by end of 2020.** + +### Vue CLI + +As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when creating a new project. You can upgrade `vue-cli` and run `vue create` to create a Vue 3 project today. ### Vue Router +Vue Router 4.0 provides Vue 3 support and has a number of breaking changes of its own. Check out its [Migration Guide](https://next.router.vuejs.org/guide/migration/) for full details. + - [![beta](https://img.shields.io/npm/v/vue-router/next.svg)](https://www.npmjs.com/package/vue-router/v/next) - [Github](https://github.com/vuejs/vue-router-next) - [RFCs](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3Arouter) ### Vuex +Vuex 4.0 provides Vue 3 support with largely the same API as 3.x. The only breaking change is [how the plugin is installed](https://github.com/vuejs/vuex/tree/4.0#breaking-changes). + - [![beta](https://img.shields.io/npm/v/vuex/next.svg)](https://www.npmjs.com/package/vuex/v/next) - [Github](https://github.com/vuejs/vuex/tree/4.0) -The only difference between Vuex 4.0 and 3.x is that it's Vue 3 compatible! It is ready to enter RC together with Vue 3 core. +### Devtools Extension -### Vue CLI +We are working on a new version of the Devtools with a new UI and refactored internals to support multiple Vue versions. The new version is currently in beta and only supports Vue 3 (for now). Vuex and Router integration is also work in progress. -As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when creating a new project. +- For Chrome: [Install from Chrome web store](https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg?hl=en) -### JSX Support + - Note: the beta channel may conflict with the stable version of devtools so you may need to temporarily disable the stable version for the beta channel to work properly. -There are currently two JSX transform implementations for Vue 3 with slightly differing syntax (for Vue specific features): +- For Firefox: [Download the signed extension](https://github.com/vuejs/vue-devtools/releases/tag/v6.0.0-beta.2) (`.xpi` file under Assets) -- [vuejs/jsx-next](https://github.com/vuejs/jsx-next) -- [HcySunYang/vue-next-jsx](https://github.com/HcySunYang/vue-next-jsx) +### IDE Support -We are using [this thread](https://github.com/vuejs/jsx/issues/141) to unify the design and land on an official specification of how Vue features should be handled in JSX. If you use Vue with JSX, please provide your feedback in that thread. +It is recommended to use [VSCode](https://code.visualstudio.com/) with our official extension [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur), which provides comprehensive IDE support for Vue 3. ### Other Projects -| Project | Status | -| ------------------- | ------ | -| vue-devtools | [![alpha][vd-badge]][vd-npm] [[Github][vd-code]] | -| eslint-plugin-vue | [![alpha][epv-badge]][epv-npm] [[Github][epv-code]] | -| @vue/test-utils | [![alpha][vtu-badge]][vtu-npm] [[Github][vtu-code]] | -| vue-class-component | [![alpha][vcc-badge]][vcc-npm] [[Github][vcc-code]] | -| vue-loader | [![alpha][vl-badge]][vl-npm] [[Github][vl-code]] | -| rollup-plugin-vue | [![alpha][rpv-badge]][rpv-npm] [[Github][rpv-code]] | - +| Project | NPM | Repo | +| --------------------- | ----------------------------- | -------------------- | +| @vue/babel-plugin-jsx | [![rc][jsx-badge]][jsx-npm] | [[Github][jsx-code]] | +| eslint-plugin-vue | [![beta][epv-badge]][epv-npm] | [[Github][epv-code]] | +| @vue/test-utils | [![beta][vtu-badge]][vtu-npm] | [[Github][vtu-code]] | +| vue-class-component | [![beta][vcc-badge]][vcc-npm] | [[Github][vcc-code]] | +| vue-loader | [![beta][vl-badge]][vl-npm] | [[Github][vl-code]] | +| rollup-plugin-vue | [![beta][rpv-badge]][rpv-npm] | [[Github][rpv-code]] | + +[jsx-badge]: https://img.shields.io/npm/v/@vue/babel-plugin-jsx.svg +[jsx-npm]: https://www.npmjs.com/package/@vue/babel-plugin-jsx +[jsx-code]: https://github.com/vuejs/jsx-next [vd-badge]: https://img.shields.io/npm/v/@vue/devtools/beta.svg [vd-npm]: https://www.npmjs.com/package/@vue/devtools/v/beta [vd-code]: https://github.com/vuejs/vue-devtools/tree/next - [epv-badge]: https://img.shields.io/npm/v/eslint-plugin-vue/next.svg [epv-npm]: https://www.npmjs.com/package/eslint-plugin-vue/v/next [epv-code]: https://github.com/vuejs/eslint-plugin-vue - [vtu-badge]: https://img.shields.io/npm/v/@vue/test-utils/next.svg [vtu-npm]: https://www.npmjs.com/package/@vue/test-utils/v/next [vtu-code]: https://github.com/vuejs/vue-test-utils-next - [jsx-badge]: https://img.shields.io/npm/v/@ant-design-vue/babel-plugin-jsx.svg [jsx-npm]: https://www.npmjs.com/package/@ant-design-vue/babel-plugin-jsx [jsx-code]: https://github.com/vueComponent/jsx - [vcc-badge]: https://img.shields.io/npm/v/vue-class-component/next.svg [vcc-npm]: https://www.npmjs.com/package/vue-class-component/v/next [vcc-code]: https://github.com/vuejs/vue-class-component/tree/next - [vl-badge]: https://img.shields.io/npm/v/vue-loader/next.svg [vl-npm]: https://www.npmjs.com/package/vue-loader/v/next [vl-code]: https://github.com/vuejs/vue-loader/tree/next - [rpv-badge]: https://img.shields.io/npm/v/rollup-plugin-vue/next.svg [rpv-npm]: https://www.npmjs.com/package/rollup-plugin-vue/v/next [rpv-code]: https://github.com/vuejs/rollup-plugin-vue/tree/next - -## Contribution - -See [Contributing Guide](https://github.com/vuejs/vue-next/blob/master/.github/contributing.md). diff --git a/package.json b/package.json index d4c700cc635..7a8fcaf6619 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "workspaces": [ "packages/*" ], diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json index f0928920831..8ded40ecf56 100644 --- a/packages/compiler-core/package.json +++ b/packages/compiler-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-core", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-core", "main": "index.js", "module": "dist/compiler-core.esm-bundler.js", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-core#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", + "@vue/shared": "3.0.0-rc.13", "@babel/parser": "^7.11.5", "@babel/types": "^7.11.5", "estree-walker": "^2.0.1", diff --git a/packages/compiler-dom/package.json b/packages/compiler-dom/package.json index 3c98116f0a3..91afba2aac0 100644 --- a/packages/compiler-dom/package.json +++ b/packages/compiler-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-dom", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-dom", "main": "index.js", "module": "dist/compiler-dom.esm-bundler.js", @@ -36,7 +36,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-dom#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-core": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-core": "3.0.0-rc.13" } } diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json index 9815e4fa716..ed4f90a629b 100644 --- a/packages/compiler-sfc/package.json +++ b/packages/compiler-sfc/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-sfc", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-sfc", "main": "dist/compiler-sfc.cjs.js", "types": "dist/compiler-sfc.d.ts", @@ -32,15 +32,15 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-sfc#readme", "peerDependencies": { - "vue": "3.0.0-rc.12" + "vue": "3.0.0-rc.13" }, "dependencies": { "@babel/parser": "^7.11.5", "@babel/types": "^7.11.5", - "@vue/compiler-core": "3.0.0-rc.12", - "@vue/compiler-dom": "3.0.0-rc.12", - "@vue/compiler-ssr": "3.0.0-rc.12", - "@vue/shared": "3.0.0-rc.12", + "@vue/compiler-core": "3.0.0-rc.13", + "@vue/compiler-dom": "3.0.0-rc.13", + "@vue/compiler-ssr": "3.0.0-rc.13", + "@vue/shared": "3.0.0-rc.13", "consolidate": "^0.16.0", "estree-walker": "^2.0.1", "hash-sum": "^2.0.0", diff --git a/packages/compiler-ssr/package.json b/packages/compiler-ssr/package.json index 887859e6dbc..194fcf8ba17 100644 --- a/packages/compiler-ssr/package.json +++ b/packages/compiler-ssr/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-ssr", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-ssr", "main": "dist/compiler-ssr.cjs.js", "types": "dist/compiler-ssr.d.ts", @@ -28,7 +28,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-ssr#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-dom": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-dom": "3.0.0-rc.13" } } diff --git a/packages/reactivity/__tests__/effect.spec.ts b/packages/reactivity/__tests__/effect.spec.ts index 63fea444202..6be4d8e25dd 100644 --- a/packages/reactivity/__tests__/effect.spec.ts +++ b/packages/reactivity/__tests__/effect.spec.ts @@ -358,6 +358,29 @@ describe('reactivity/effect', () => { expect(counterSpy).toHaveBeenCalledTimes(2) }) + it('should avoid infinite recursive loops when use Array.prototype.push/unshift/pop/shift', () => { + ;(['push', 'unshift'] as const).forEach(key => { + const arr = reactive([]) + const counterSpy1 = jest.fn(() => (arr[key] as any)(1)) + const counterSpy2 = jest.fn(() => (arr[key] as any)(2)) + effect(counterSpy1) + effect(counterSpy2) + expect(arr.length).toBe(2) + expect(counterSpy1).toHaveBeenCalledTimes(1) + expect(counterSpy2).toHaveBeenCalledTimes(1) + }) + ;(['pop', 'shift'] as const).forEach(key => { + const arr = reactive([1, 2, 3, 4]) + const counterSpy1 = jest.fn(() => (arr[key] as any)()) + const counterSpy2 = jest.fn(() => (arr[key] as any)()) + effect(counterSpy1) + effect(counterSpy2) + expect(arr.length).toBe(2) + expect(counterSpy1).toHaveBeenCalledTimes(1) + expect(counterSpy2).toHaveBeenCalledTimes(1) + }) + }) + it('should allow explicitly recursive raw function loops', () => { const counter = reactive({ num: 0 }) const numSpy = jest.fn(() => { diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index cc8983720a0..eb675381105 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@vue/reactivity", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/reactivity", "main": "index.js", "module": "dist/reactivity.esm-bundler.js", @@ -36,6 +36,6 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/reactivity#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13" } } diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index 2b7b29b03a8..f612043a339 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -8,7 +8,13 @@ import { reactiveMap } from './reactive' import { TrackOpTypes, TriggerOpTypes } from './operations' -import { track, trigger, ITERATE_KEY } from './effect' +import { + track, + trigger, + ITERATE_KEY, + pauseTracking, + enableTracking +} from './effect' import { isObject, hasOwn, @@ -32,22 +38,36 @@ const readonlyGet = /*#__PURE__*/ createGetter(true) const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true) const arrayInstrumentations: Record = {} +// instrument identity-sensitive Array methods to account for possible reactive +// values ;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => { + const method = Array.prototype[key] as any arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) { const arr = toRaw(this) for (let i = 0, l = this.length; i < l; i++) { track(arr, TrackOpTypes.GET, i + '') } // we run the method using the original args first (which may be reactive) - const res = (arr[key] as any)(...args) + const res = method.apply(arr, args) if (res === -1 || res === false) { // if that didn't work, run it again using raw values. - return (arr[key] as any)(...args.map(toRaw)) + return method.apply(arr, args.map(toRaw)) } else { return res } } }) +// instrument length-altering mutation methods to avoid length being tracked +// which leads to infinite loops in some cases (#2137) +;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => { + const method = Array.prototype[key] as any + arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) { + pauseTracking() + const res = method.apply(this, args) + enableTracking() + return res + } +}) function createGetter(isReadonly = false, shallow = false) { return function get(target: Target, key: string | symbol, receiver: object) { diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 00ecb6e4c4c..6b6014c05cc 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -113,6 +113,7 @@ describe('api: options', () => { const spyB = jest.fn(returnThis) const spyC = jest.fn(returnThis) const spyD = jest.fn(returnThis) + const spyE = jest.fn(returnThis) let ctx: any const Comp = { @@ -123,7 +124,10 @@ describe('api: options', () => { baz: { qux: 3 }, - qux: 4 + qux: 4, + dot: { + path: 5 + } } }, watch: { @@ -137,7 +141,8 @@ describe('api: options', () => { }, qux: { handler: 'onQuxChange' - } + }, + 'dot.path': spyE }, methods: { onFooChange: spyA, @@ -175,6 +180,11 @@ describe('api: options', () => { await nextTick() expect(spyD).toHaveBeenCalledTimes(1) assertCall(spyD, 0, [5, 4]) + + ctx.dot.path++ + await nextTick() + expect(spyE).toHaveBeenCalledTimes(1) + assertCall(spyE, 0, [6, 5]) }) test('watch array', async () => { diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 7b64e50bd5f..31bca6bed3f 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -280,22 +280,29 @@ describe('api: watch', () => { expect(cleanup).toHaveBeenCalledTimes(2) }) - it('flush timing: post (default)', async () => { + it('flush timing: pre (default)', async () => { const count = ref(0) + const count2 = ref(0) + let callCount = 0 - let result - const assertion = jest.fn(count => { + let result1 + let result2 + const assertion = jest.fn((count, count2Value) => { callCount++ // on mount, the watcher callback should be called before DOM render - // on update, should be called after the count is updated - const expectedDOM = callCount === 1 ? `` : `${count}` - result = serializeInner(root) === expectedDOM + // on update, should be called before the count is updated + const expectedDOM = callCount === 1 ? `` : `${count - 1}` + result1 = serializeInner(root) === expectedDOM + + // in a pre-flush callback, all state should have been updated + const expectedState = callCount - 1 + result2 = count === expectedState && count2Value === expectedState }) const Comp = { setup() { watchEffect(() => { - assertion(count.value) + assertion(count.value, count2.value) }) return () => count.value } @@ -303,42 +310,32 @@ describe('api: watch', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(assertion).toHaveBeenCalledTimes(1) - expect(result).toBe(true) + expect(result1).toBe(true) + expect(result2).toBe(true) count.value++ + count2.value++ await nextTick() + // two mutations should result in 1 callback execution expect(assertion).toHaveBeenCalledTimes(2) - expect(result).toBe(true) + expect(result1).toBe(true) + expect(result2).toBe(true) }) - it('flush timing: pre', async () => { + it('flush timing: post', async () => { const count = ref(0) - const count2 = ref(0) - - let callCount = 0 - let result1 - let result2 - const assertion = jest.fn((count, count2Value) => { - callCount++ - // on mount, the watcher callback should be called before DOM render - // on update, should be called before the count is updated - const expectedDOM = callCount === 1 ? `` : `${count - 1}` - result1 = serializeInner(root) === expectedDOM - - // in a pre-flush callback, all state should have been updated - const expectedState = callCount - 1 - result2 = count === expectedState && count2Value === expectedState + let result + const assertion = jest.fn(count => { + result = serializeInner(root) === `${count}` }) const Comp = { setup() { watchEffect( () => { - assertion(count.value, count2.value) + assertion(count.value) }, - { - flush: 'pre' - } + { flush: 'post' } ) return () => count.value } @@ -346,16 +343,12 @@ describe('api: watch', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(assertion).toHaveBeenCalledTimes(1) - expect(result1).toBe(true) - expect(result2).toBe(true) + expect(result).toBe(true) count.value++ - count2.value++ await nextTick() - // two mutations should result in 1 callback execution expect(assertion).toHaveBeenCalledTimes(2) - expect(result1).toBe(true) - expect(result2).toBe(true) + expect(result).toBe(true) }) it('flush timing: sync', async () => { @@ -410,7 +403,7 @@ describe('api: watch', () => { const cb = jest.fn() const Comp = { setup() { - watch(toggle, cb) + watch(toggle, cb, { flush: 'post' }) }, render() {} } diff --git a/packages/runtime-core/__tests__/componentProps.spec.ts b/packages/runtime-core/__tests__/componentProps.spec.ts index d0ddc5c1fdc..f75d3c2ebbd 100644 --- a/packages/runtime-core/__tests__/componentProps.spec.ts +++ b/packages/runtime-core/__tests__/componentProps.spec.ts @@ -8,7 +8,9 @@ import { defineComponent, ref, serializeInner, - createApp + createApp, + provide, + inject } from '@vue/runtime-test' import { render as domRender, nextTick } from 'vue' @@ -212,6 +214,32 @@ describe('component props', () => { expect(defaultFn).toHaveBeenCalledTimes(1) }) + test('using inject in default value factory', () => { + const Child = defineComponent({ + props: { + test: { + default: () => inject('test', 'default') + } + }, + setup(props) { + return () => { + return h('div', props.test) + } + } + }) + + const Comp = { + setup() { + provide('test', 'injected') + return () => h(Child) + } + } + + const root = nodeOps.createElement('div') + render(h(Comp), root) + expect(serializeInner(root)).toBe(`
injected
`) + }) + test('optimized props updates', async () => { const Child = defineComponent({ props: ['foo'], diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts index e4a57804314..c6ab0f3fa32 100644 --- a/packages/runtime-core/__tests__/components/Suspense.spec.ts +++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts @@ -154,7 +154,7 @@ describe('Suspense', () => { expect(onResolve).toHaveBeenCalled() }) - test('buffer mounted/updated hooks & watch callbacks', async () => { + test('buffer mounted/updated hooks & post flush watch callbacks', async () => { const deps: Promise[] = [] const calls: string[] = [] const toggle = ref(true) @@ -165,14 +165,21 @@ describe('Suspense', () => { // extra tick needed for Node 12+ deps.push(p.then(() => Promise.resolve())) - watchEffect(() => { - calls.push('immediate effect') - }) + watchEffect( + () => { + calls.push('watch effect') + }, + { flush: 'post' } + ) const count = ref(0) - watch(count, () => { - calls.push('watch callback') - }) + watch( + count, + () => { + calls.push('watch callback') + }, + { flush: 'post' } + ) count.value++ // trigger the watcher now onMounted(() => { @@ -201,12 +208,12 @@ describe('Suspense', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(serializeInner(root)).toBe(`
fallback
`) - expect(calls).toEqual([`immediate effect`]) + expect(calls).toEqual([]) await Promise.all(deps) await nextTick() expect(serializeInner(root)).toBe(`
async
`) - expect(calls).toEqual([`immediate effect`, `watch callback`, `mounted`]) + expect(calls).toEqual([`watch effect`, `watch callback`, `mounted`]) // effects inside an already resolved suspense should happen at normal timing toggle.value = false @@ -214,7 +221,7 @@ describe('Suspense', () => { await nextTick() expect(serializeInner(root)).toBe(``) expect(calls).toEqual([ - `immediate effect`, + `watch effect`, `watch callback`, `mounted`, 'unmounted' @@ -319,14 +326,21 @@ describe('Suspense', () => { const p = new Promise(r => setTimeout(r, 1)) deps.push(p) - watchEffect(() => { - calls.push('immediate effect') - }) + watchEffect( + () => { + calls.push('watch effect') + }, + { flush: 'post' } + ) const count = ref(0) - watch(count, () => { - calls.push('watch callback') - }) + watch( + count, + () => { + calls.push('watch callback') + }, + { flush: 'post' } + ) count.value++ // trigger the watcher now onMounted(() => { @@ -355,7 +369,7 @@ describe('Suspense', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(serializeInner(root)).toBe(`
fallback
`) - expect(calls).toEqual(['immediate effect']) + expect(calls).toEqual([]) // remove the async dep before it's resolved toggle.value = false @@ -366,8 +380,8 @@ describe('Suspense', () => { await Promise.all(deps) await nextTick() expect(serializeInner(root)).toBe(``) - // should discard effects (except for immediate ones) - expect(calls).toEqual(['immediate effect', 'unmounted']) + // should discard effects + expect(calls).toEqual([]) }) test('unmount suspense after resolve', async () => { diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index a53c7a3e258..31c910d17d4 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -148,6 +148,49 @@ describe('hot module replacement', () => { expect(mountSpy).toHaveBeenCalledTimes(1) }) + test('reload class component', async () => { + const root = nodeOps.createElement('div') + const childId = 'test4-child' + const unmountSpy = jest.fn() + const mountSpy = jest.fn() + + class Child { + static __vccOpts: ComponentOptions = { + __hmrId: childId, + data() { + return { count: 0 } + }, + unmounted: unmountSpy, + render: compileToFunction(`
{{ count }}
`) + } + } + createRecord(childId) + + const Parent: ComponentOptions = { + render: () => h(Child) + } + + render(h(Parent), root) + expect(serializeInner(root)).toBe(`
0
`) + + class UpdatedChild { + static __vccOpts: ComponentOptions = { + __hmrId: childId, + data() { + return { count: 1 } + }, + mounted: mountSpy, + render: compileToFunction(`
{{ count }}
`) + } + } + + reload(childId, UpdatedChild) + await nextTick() + expect(serializeInner(root)).toBe(`
1
`) + expect(unmountSpy).toHaveBeenCalledTimes(1) + expect(mountSpy).toHaveBeenCalledTimes(1) + }) + // #1156 - static nodes should retain DOM element reference across updates // when HMR is active test('static el reference', async () => { diff --git a/packages/runtime-core/package.json b/packages/runtime-core/package.json index 78226ccd5fc..5ed9cc653ae 100644 --- a/packages/runtime-core/package.json +++ b/packages/runtime-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-core", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/runtime-core", "main": "index.js", "module": "dist/runtime-core.esm-bundler.js", @@ -32,7 +32,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-core#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/reactivity": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/reactivity": "3.0.0-rc.13" } } diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index ef08d3c6533..9b85638c2dd 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -94,8 +94,8 @@ export function defineComponent< Props = {}, RawBindings = {}, D = {}, - C extends ComputedOptions = ComputedOptions, - M extends MethodOptions = MethodOptions, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = EmitsOptions, diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index ac1b1d16d7f..14253a2a403 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -268,9 +268,10 @@ function doWatch( let scheduler: (job: () => any) => void if (flush === 'sync') { scheduler = job - } else if (flush === 'pre') { - // ensure it's queued before component updates (which have positive ids) - job.id = -1 + } else if (flush === 'post') { + scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) + } else { + // default: 'pre' scheduler = () => { if (!instance || instance.isMounted) { queuePreFlushCb(job) @@ -280,8 +281,6 @@ function doWatch( job() } } - } else { - scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) } const runner = effect(getter, { @@ -300,6 +299,8 @@ function doWatch( } else { oldValue = runner() } + } else if (flush === 'post') { + queuePostRenderEffect(runner, instance && instance.suspense) } else { runner() } diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index ac482d6707a..78abad60a8a 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -800,3 +800,7 @@ export function formatComponentName( return name ? classify(name) : isRoot ? `App` : `Anonymous` } + +export function isClassComponent(value: unknown): value is ClassComponent { + return isFunction(value) && '__vccOpts' in value +} diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index ff499d36cdc..69f1f2afd1e 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -166,8 +166,7 @@ export type ComponentOptionsWithoutProps< Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = EmitsOptions, - EE extends string = string, - Defaults = {} + EE extends string = string > = ComponentOptionsBase< Props, RawBindings, @@ -178,23 +177,11 @@ export type ComponentOptionsWithoutProps< Extends, E, EE, - Defaults + {} > & { props?: undefined } & ThisType< - CreateComponentPublicInstance< - {}, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - Readonly, - Defaults, - false - > + CreateComponentPublicInstance<{}, RawBindings, D, C, M, Mixin, Extends, E> > export type ComponentOptionsWithArrayProps< @@ -816,7 +803,9 @@ function createWatcher( publicThis: ComponentPublicInstance, key: string ) { - const getter = () => (publicThis as any)[key] + const getter = key.includes('.') + ? createPathGetter(publicThis, key) + : () => (publicThis as any)[key] if (isString(raw)) { const handler = ctx[raw] if (isFunction(handler)) { @@ -840,7 +829,18 @@ function createWatcher( } } } else if (__DEV__) { - warn(`Invalid watch option: "${key}"`) + warn(`Invalid watch option: "${key}"`, raw) + } +} + +function createPathGetter(ctx: any, path: string) { + const segments = path.split('.') + return () => { + let cur = ctx + for (let i = 0; i < segments.length && cur; i++) { + cur = cur[segments[i]] + } + return cur } } diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 0fde127a28f..f977099d806 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -27,7 +27,8 @@ import { Data, ComponentInternalInstance, ComponentOptions, - ConcreteComponent + ConcreteComponent, + setCurrentInstance } from './component' import { isEmitListener } from './componentEmits' import { InternalObjectKey } from './vnode' @@ -179,7 +180,8 @@ export function updateProps( options, rawCurrentProps, camelizedKey, - value + value, + instance ) } } else { @@ -214,7 +216,8 @@ export function updateProps( options, rawProps || EMPTY_OBJ, key, - undefined + undefined, + instance ) } } else { @@ -277,7 +280,8 @@ function setFullProps( options!, rawCurrentProps, key, - rawCurrentProps[key] + rawCurrentProps[key], + instance ) } } @@ -287,7 +291,8 @@ function resolvePropValue( options: NormalizedProps, props: Data, key: string, - value: unknown + value: unknown, + instance: ComponentInternalInstance ) { const opt = options[key] if (opt != null) { @@ -295,10 +300,13 @@ function resolvePropValue( // default values if (hasDefault && value === undefined) { const defaultValue = opt.default - value = - opt.type !== Function && isFunction(defaultValue) - ? defaultValue(props) - : defaultValue + if (opt.type !== Function && isFunction(defaultValue)) { + setCurrentInstance(instance) + value = defaultValue(props) + setCurrentInstance(null) + } else { + value = defaultValue + } } // boolean casting if (opt[BooleanFlags.shouldCast]) { diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index 3259ca685c6..ac6eec56f2e 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -171,15 +171,18 @@ const KeepAliveImpl = { keys.delete(key) } + // prune cache on include/exclude prop change watch( () => [props.include, props.exclude], ([include, exclude]) => { include && pruneCache(name => matches(include, name)) exclude && pruneCache(name => !matches(exclude, name)) - } + }, + // prune post-render after `current` has been updated + { flush: 'post' } ) - // cache sub tree in beforeMount/Update (i.e. right after the render) + // cache sub tree after render let pendingCacheKey: CacheKey | null = null const cacheSubtree = () => { // fix #1621, the pendingCacheKey could be 0 diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts index 16204b6d0e0..288139609a9 100644 --- a/packages/runtime-core/src/components/Suspense.ts +++ b/packages/runtime-core/src/components/Suspense.ts @@ -201,11 +201,12 @@ function patchSuspense( suspense.isHydrating = false suspense.activeBranch = pendingBranch } else { - unmount(pendingBranch, parentComponent, null) + unmount(pendingBranch, parentComponent, suspense) } // increment pending ID. this is used to invalidate async callbacks // reset suspense state suspense.deps = 0 + // discard effects from pending branch suspense.effects.length = 0 // discard previous container suspense.hiddenContainer = createElement('div') diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index b831498baa4..df557313565 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -3,7 +3,9 @@ import { ConcreteComponent, ComponentInternalInstance, ComponentOptions, - InternalRenderFunction + InternalRenderFunction, + ClassComponent, + isClassComponent } from './component' import { queueJob, queuePostFlushCb } from './scheduler' import { extend } from '@vue/shared' @@ -83,7 +85,7 @@ function rerender(id: string, newRender?: Function) { }) } -function reload(id: string, newComp: ComponentOptions) { +function reload(id: string, newComp: ComponentOptions | ClassComponent) { const record = map.get(id) if (!record) return // Array.from creates a snapshot which avoids the set being mutated during @@ -92,6 +94,7 @@ function reload(id: string, newComp: ComponentOptions) { const comp = instance.type if (!hmrDirtyComponents.has(comp)) { // 1. Update existing comp definition to match new one + newComp = isClassComponent(newComp) ? newComp.__vccOpts : newComp extend(comp, newComp) for (const key in comp) { if (!(key in newComp)) { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 9a11090a37c..56ff85f5eea 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -17,7 +17,8 @@ import { Data, ConcreteComponent, ClassComponent, - Component + Component, + isClassComponent } from './component' import { RawSlots } from './componentSlots' import { isProxy, Ref, toRaw, ReactiveFlags } from '@vue/reactivity' @@ -340,7 +341,7 @@ function _createVNode( } // class component normalization. - if (isFunction(type) && '__vccOpts' in type) { + if (isClassComponent(type)) { type = type.__vccOpts } diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json index c7ce948ac84..cae5257fcad 100644 --- a/packages/runtime-dom/package.json +++ b/packages/runtime-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-dom", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/runtime-dom", "main": "index.js", "module": "dist/runtime-dom.esm-bundler.js", @@ -35,8 +35,8 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-dom#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/runtime-core": "3.0.0-rc.12", + "@vue/shared": "3.0.0-rc.13", + "@vue/runtime-core": "3.0.0-rc.13", "csstype": "^2.6.8" } } diff --git a/packages/runtime-test/package.json b/packages/runtime-test/package.json index ab5f885d5bb..f0aad177ade 100644 --- a/packages/runtime-test/package.json +++ b/packages/runtime-test/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-test", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/runtime-test", "private": true, "main": "index.js", @@ -25,7 +25,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-test#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/runtime-core": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/runtime-core": "3.0.0-rc.13" } } diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index 98a2979f388..a480e9a12be 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@vue/server-renderer", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/server-renderer", "main": "index.js", "types": "dist/server-renderer.d.ts", @@ -28,10 +28,10 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/server-renderer#readme", "peerDependencies": { - "vue": "3.0.0-rc.12" + "vue": "3.0.0-rc.13" }, "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-ssr": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-ssr": "3.0.0-rc.13" } } diff --git a/packages/shared/package.json b/packages/shared/package.json index 275d8c32780..cb67f854670 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@vue/shared", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "internal utils shared across @vue packages", "main": "index.js", "module": "dist/shared.esm-bundler.js", diff --git a/packages/size-check/package.json b/packages/size-check/package.json index f21de24e606..d2e8039d3c3 100644 --- a/packages/size-check/package.json +++ b/packages/size-check/package.json @@ -1,6 +1,6 @@ { "name": "@vue/size-check", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "private": true, "buildOptions": { "name": "Vue", diff --git a/packages/template-explorer/package.json b/packages/template-explorer/package.json index e6402f74141..e1afed4c27c 100644 --- a/packages/template-explorer/package.json +++ b/packages/template-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@vue/template-explorer", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "private": true, "buildOptions": { "formats": [ diff --git a/packages/vue/package.json b/packages/vue/package.json index 805318f3642..a940a4a4756 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "vue", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js", @@ -37,9 +37,9 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/vue#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-dom": "3.0.0-rc.12", - "@vue/runtime-dom": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-dom": "3.0.0-rc.13", + "@vue/runtime-dom": "3.0.0-rc.13" }, "devDependencies": { "lodash": "^4.17.15", diff --git a/test-dts/component.test-d.ts b/test-dts/component.test-d.ts index 990e370518b..30b3b8e5f53 100644 --- a/test-dts/component.test-d.ts +++ b/test-dts/component.test-d.ts @@ -190,6 +190,12 @@ describe('object props', () => { expectType(setup.setupProps.ggg) expectType(setup.setupProps.ffff) expectType(setup.setupProps.validated) + + // instance + const instance = new MyComponent() + expectType(instance.setupA) + // @ts-expect-error + instance.notExist }) describe('options', () => { @@ -356,6 +362,12 @@ describe('no props', () => { expectType(rawBindings.setupA) expectType(setup.setupA) + + // instance + const instance = new MyComponent() + expectType(instance.setupA) + // @ts-expect-error + instance.notExist }) describe('options', () => { diff --git a/yarn.lock b/yarn.lock index cd2df31c9e7..063307a72a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -864,9 +864,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@26.x", "@types/jest@^26.0.0": - version "26.0.13" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.13.tgz#5a7b9d5312f5dd521a38329c38ee9d3802a0b85e" - integrity sha512-sCzjKow4z9LILc6DhBvn5AkIfmQzDZkgtVVKmGwVrs5tuid38ws281D4l+7x1kP487+FlKDh5kfMZ8WSPAdmdA== + version "26.0.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.14.tgz#078695f8f65cb55c5a98450d65083b2b73e5a3f3" + integrity sha512-Hz5q8Vu0D288x3iWXePSn53W7hAjP0H7EQ6QvDO9c7t46mR0lNOLlfuwQ+JkVxuhygHzlzPX+0jKdA3ZgSh+Vg== dependencies: jest-diff "^25.2.1" pretty-format "^25.2.1" @@ -887,9 +887,9 @@ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= "@types/node@*", "@types/node@^14.10.1": - version "14.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.2.tgz#9b47a2c8e4dabd4db73b57e750b24af689600514" - integrity sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw== + version "14.11.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.1.tgz#56af902ad157e763f9ba63d671c39cda3193c835" + integrity sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw== "@types/node@10.17.13": version "10.17.13" @@ -4624,9 +4624,9 @@ lines-and-columns@^1.1.6: integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= lint-staged@^10.2.10: - version "10.3.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.3.0.tgz#388c3d440590c45c339e7163f669ea69ae90b1e0" - integrity sha512-an3VgjHqmJk0TORB/sdQl0CTkRg4E5ybYCXTTCSJ5h9jFwZbcgKIx5oVma5e7wp/uKt17s1QYFmYqT9MGVosGw== + version "10.4.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.4.0.tgz#d18628f737328e0bbbf87d183f4020930e9a984e" + integrity sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -5708,9 +5708,9 @@ postcss-value-parser@^4.0.0: integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + version "7.0.34" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20" + integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -6386,9 +6386,9 @@ rollup-pluginutils@^2.3.1: estree-walker "^0.6.1" rollup@^2.26.11: - version "2.26.11" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.11.tgz#4fc31de9c7b83d50916fc8395f8c3d24730cdaae" - integrity sha512-xyfxxhsE6hW57xhfL1I+ixH8l2bdoIMaAecdQiWF3N7IgJEMu99JG+daBiSZQjnBpzFxa0/xZm+3pbCdAQehHw== + version "2.27.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.1.tgz#372744e1d36eba0fd942d997600c2fc2ca266305" + integrity sha512-GiWHQvnmMgBktSpY/1+nrGpwPsTw4b9P28og2uedfeq4JZ16rzAmnQ5Pm/E0/BEmDNia1ZbY7+qu3nBgNa19Hg== optionalDependencies: fsevents "~2.1.2" @@ -6447,9 +6447,9 @@ sane@^4.0.3: walker "~1.0.5" sass@^1.26.9: - version "1.26.10" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.10.tgz#851d126021cdc93decbf201d1eca2a20ee434760" - integrity sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw== + version "1.26.11" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.11.tgz#0f22cc4ab2ba27dad1d4ca30837beb350b709847" + integrity sha512-W1l/+vjGjIamsJ6OnTe0K37U2DBO/dgsv2Z4c89XQ8ZOO6l/VwkqwLSqoYzJeJs6CLuGSTRWc91GbQFL3lvrvw== dependencies: chokidar ">=2.0.0 <4.0.0"