From cb7de6a921e1b07ada76c3e171be3d7a543af5d3 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 01:32:14 +0000 Subject: [PATCH 01/51] build(deps-dev): bump eslint from 7.7.0 to 7.8.1 (#2032) --- yarn.lock | 58 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4b98f6dd900..7286b064ebd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -369,6 +369,22 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@eslint/eslintrc@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" + integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" @@ -1016,11 +1032,16 @@ acorn@^5.7.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== -acorn@^7.1.1, acorn@^7.3.1: +acorn@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +acorn@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -1049,10 +1070,10 @@ ajv@6.5.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.5.5: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -2592,11 +2613,12 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint@^7.7.0: - version "7.7.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073" - integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg== + version "7.8.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.8.1.tgz#e59de3573fb6a5be8ff526c791571646d124a8fa" + integrity sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w== dependencies: "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.1.3" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -2606,7 +2628,7 @@ eslint@^7.7.0: eslint-scope "^5.1.0" eslint-utils "^2.1.0" eslint-visitor-keys "^1.3.0" - espree "^7.2.0" + espree "^7.3.0" esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -2633,12 +2655,12 @@ eslint@^7.7.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69" - integrity sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g== +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== dependencies: - acorn "^7.3.1" + acorn "^7.4.0" acorn-jsx "^5.2.0" eslint-visitor-keys "^1.3.0" @@ -6867,10 +6889,10 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" - integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== strip-json-comments@~2.0.1: version "2.0.1" From ef0aa7c99da3459d22191c2803e2fdef4ad8a482 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 09:20:38 -0400 Subject: [PATCH 02/51] build(deps): bump @babel/parser from 7.11.4 to 7.11.5 (#2028) Bumps [@babel/parser](https://github.com/babel/babel/tree/HEAD/packages/babel-parser) from 7.11.4 to 7.11.5. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.11.5/packages/babel-parser) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7286b064ebd..d70e48fabe5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -218,9 +218,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5", "@babel/parser@^7.7.5", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.4.tgz#6fa1a118b8b0d80d0267b719213dc947e88cc0ca" - integrity sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA== + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" From 71b6fedcdb56ce876b668165f0d4c8098027d305 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 09:20:45 -0400 Subject: [PATCH 03/51] build(deps): bump @babel/types from 7.11.0 to 7.11.5 (#2030) Bumps [@babel/types](https://github.com/babel/babel/tree/HEAD/packages/babel-types) from 7.11.0 to 7.11.5. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.11.5/packages/babel-types) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d70e48fabe5..1c14b26490c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -348,9 +348,9 @@ lodash "^4.17.13" "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" From 95c07d8c36a69bfc29e661fbbfb92735c4fe5d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=9C=C9=B4=D0=B2=CA=8F=D1=82=E1=B4=87?= Date: Thu, 3 Sep 2020 09:35:43 -0500 Subject: [PATCH 04/51] fix(runtime-core): fix priority of option merging (#2041) --- .../runtime-core/__tests__/apiCreateApp.spec.ts | 2 +- packages/runtime-core/src/componentOptions.ts | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/runtime-core/__tests__/apiCreateApp.spec.ts b/packages/runtime-core/__tests__/apiCreateApp.spec.ts index 0c7faf711aa..c3be3476c2c 100644 --- a/packages/runtime-core/__tests__/apiCreateApp.spec.ts +++ b/packages/runtime-core/__tests__/apiCreateApp.spec.ts @@ -457,7 +457,7 @@ describe('api: createApp', () => { app.config.optionMergeStrategies.foo = (a, b) => (a ? `${a},` : ``) + b app.mount(nodeOps.createElement('div')) - expect(merged!).toBe('local,extends,mixin,global') + expect(merged!).toBe('global,extends,mixin,local') }) test('config.globalProperties', () => { diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 5af8c410dd6..fd473714771 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -768,23 +768,24 @@ export function resolveMergedOptions( const globalMixins = instance.appContext.mixins if (!globalMixins.length && !mixins && !extendsOptions) return raw const options = {} - mergeOptions(options, raw, instance) globalMixins.forEach(m => mergeOptions(options, m, instance)) + mergeOptions(options, raw, instance) return (raw.__merged = options) } function mergeOptions(to: any, from: any, instance: ComponentInternalInstance) { const strats = instance.appContext.config.optionMergeStrategies + const { mixins, extends: extendsOptions } = from + + extendsOptions && mergeOptions(to, extendsOptions, instance) + mixins && + mixins.forEach((m: ComponentOptionsMixin) => mergeOptions(to, m, instance)) + for (const key in from) { if (strats && hasOwn(strats, key)) { to[key] = strats[key](to[key], from[key], instance.proxy, key) - } else if (!hasOwn(to, key)) { + } else { to[key] = from[key] } } - const { mixins, extends: extendsOptions } = from - - extendsOptions && mergeOptions(to, extendsOptions, instance) - mixins && - mixins.forEach((m: ComponentOptionsMixin) => mergeOptions(to, m, instance)) } From fa7ab0a7f7a939dc7724930a548805219e6a86c5 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 3 Sep 2020 11:21:14 -0400 Subject: [PATCH 05/51] fix(runtime-core): warn reserved prefix for setup return properties and ensure consistent dev/prod behavior close #2042 --- .../runtime-core/src/componentPublicInstance.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index c47941fc568..695e5ace3c9 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -299,12 +299,16 @@ export const PublicInstanceProxyHandlers: ProxyHandler = { // to infinite warning loop key.indexOf('__v') !== 0) ) { - if (data !== EMPTY_OBJ && key[0] === '$' && hasOwn(data, key)) { + if ( + data !== EMPTY_OBJ && + (key[0] === '$' || key[0] === '_') && + hasOwn(data, key) + ) { warn( `Property ${JSON.stringify( key )} must be accessed via $data because it starts with a reserved ` + - `character and is not proxied on the render context.` + `character ("$" or "_") and is not proxied on the render context.` ) } else { warn( @@ -474,6 +478,15 @@ export function exposeSetupStateOnRenderContext( ) { const { ctx, setupState } = instance Object.keys(toRaw(setupState)).forEach(key => { + if (key[0] === '$' || key[0] === '_') { + warn( + `setup() return property ${JSON.stringify( + key + )} should not start with "$" or "_" ` + + `which are reserved prefixes for Vue internals.` + ) + return + } Object.defineProperty(ctx, key, { enumerable: true, configurable: true, From 5f4053967cb61620d3dd27518f571166d7b5ec8f Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 4 Sep 2020 11:08:53 -0400 Subject: [PATCH 06/51] fix(reactivity): revert ac81dcf fix #2043 --- packages/reactivity/src/effect.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index fb17e575e1f..a4d087beade 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -178,11 +178,7 @@ export function trigger( const effects = new Set() const add = (effectsToAdd: Set | undefined) => { if (effectsToAdd) { - effectsToAdd.forEach(effect => { - if (effect !== activeEffect) { - effects.add(effect) - } - }) + effectsToAdd.forEach(effect => effects.add(effect)) } } From 6dbc6c4cd0d298d3c6faa6d6aeb318be7a963700 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 4 Sep 2020 11:36:55 -0400 Subject: [PATCH 07/51] fix(sfc): fix scoped style regression for child component with single root + comment fix #2046 --- .../runtime-core/src/componentRenderUtils.ts | 28 ++++++++++------ packages/runtime-core/src/renderer.ts | 32 ++++--------------- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 9fa72c9dd51..fe1a73fb21e 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -214,6 +214,9 @@ export function renderComponentRoot( /** * dev only + * In dev mode, template root level comments are rendered, which turns the + * template into a fragment root, but we need to locate the single element + * root for attrs and scope id processing. */ const getChildRoot = ( vnode: VNode @@ -223,17 +226,10 @@ const getChildRoot = ( } const rawChildren = vnode.children as VNodeArrayChildren const dynamicChildren = vnode.dynamicChildren as VNodeArrayChildren - const children = rawChildren.filter(child => { - return !( - isVNode(child) && - child.type === Comment && - child.children !== 'v-if' - ) - }) - if (children.length !== 1) { + const childRoot = filterSingleRoot(rawChildren) + if (!childRoot) { return [vnode, undefined] } - const childRoot = children[0] const index = rawChildren.indexOf(childRoot) const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1 const setRoot = (updatedRoot: VNode) => { @@ -247,6 +243,20 @@ const getChildRoot = ( return [normalizeVNode(childRoot), setRoot] } +/** + * dev only + */ +export function filterSingleRoot(children: VNodeArrayChildren): VNode | null { + const filtered = children.filter(child => { + return !( + isVNode(child) && + child.type === Comment && + child.children !== 'v-if' + ) + }) + return filtered.length === 1 && isVNode(filtered[0]) ? filtered[0] : null +} + const getFunctionalFallthrough = (attrs: Data): Data | undefined => { let res: Data | undefined for (const key in attrs) { diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index ee020298423..a4cf97dc807 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -19,6 +19,7 @@ import { setupComponent } from './component' import { + filterSingleRoot, renderComponentRoot, shouldUpdateComponent, updateHOCHostEl @@ -746,30 +747,6 @@ function baseCreateRenderer( } // scopeId setScopeId(el, scopeId, vnode, parentComponent) - // if (scopeId) { - // hostSetScopeId(el, scopeId) - // } - // if (parentComponent) { - // const treeOwnerId = parentComponent.type.__scopeId - // // vnode's own scopeId and the current patched component's scopeId is - // // different - this is a slot content node. - // if (treeOwnerId && treeOwnerId !== scopeId) { - // hostSetScopeId(el, treeOwnerId + '-s') - // } - // const parentScopeId = - // vnode === parentComponent.subTree && parentComponent.vnode.scopeId - // if (parentScopeId) { - // hostSetScopeId(el, parentScopeId) - // if (parentComponent.parent) { - // const treeOwnerId = parentComponent.parent.type.__scopeId - // // vnode's own scopeId and the current patched component's scopeId is - // // different - this is a slot content node. - // if (treeOwnerId && treeOwnerId !== parentScopeId) { - // hostSetScopeId(el, treeOwnerId + '-s') - // } - // } - // } - // } } if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { Object.defineProperty(el, '__vnode', { @@ -823,7 +800,12 @@ function baseCreateRenderer( if (treeOwnerId && treeOwnerId !== scopeId) { hostSetScopeId(el, treeOwnerId + '-s') } - if (vnode === parentComponent.subTree) { + let subTree = parentComponent.subTree + if (__DEV__ && subTree.type === Fragment) { + subTree = + filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree + } + if (vnode === subTree) { setScopeId( el, parentComponent.vnode.scopeId, From d4724619fc3d005311f27c1ac7cab0a0e735c4d2 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 4 Sep 2020 12:00:37 -0400 Subject: [PATCH 08/51] fix(inject): fix support for inject option default function fix #2050 --- .../runtime-core/__tests__/apiOptions.spec.ts | 65 +++++++++---------- packages/runtime-core/src/apiInject.ts | 14 +++- packages/runtime-core/src/componentOptions.ts | 6 +- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 4504649bc5e..4dd1910bfa1 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -241,7 +241,7 @@ describe('api: options', () => { }) test('provide/inject', () => { - const Root = { + const Root = defineComponent({ data() { return { a: 1 @@ -253,45 +253,38 @@ describe('api: options', () => { } }, render() { - return [h(ChildA), h(ChildB), h(ChildC), h(ChildD)] - } - } as any - const ChildA = { - inject: ['a'], - render() { - return this.a - } - } as any - const ChildB = { - // object alias - inject: { b: 'a' }, - render() { - return this.b + return [h(ChildA), h(ChildB), h(ChildC), h(ChildD), h(ChildE)] } - } as any - const ChildC = { - inject: { - b: { - from: 'a' + }) + + const defineChild = (injectOptions: any, injectedKey = 'b') => + ({ + inject: injectOptions, + render() { + return this[injectedKey] } - }, - render() { - return this.b + } as any) + + const ChildA = defineChild(['a'], 'a') + const ChildB = defineChild({ b: 'a' }) + const ChildC = defineChild({ + b: { + from: 'a' } - } as any - const ChildD = { - inject: { - b: { - from: 'c', - default: 2 - } - }, - render() { - return this.b + }) + const ChildD = defineChild({ + b: { + from: 'c', + default: 2 } - } as any - - expect(renderToString(h(Root))).toBe(`1112`) + }) + const ChildE = defineChild({ + b: { + from: 'c', + default: () => 3 + } + }) + expect(renderToString(h(Root))).toBe(`11123`) }) test('lifecycle', async () => { diff --git a/packages/runtime-core/src/apiInject.ts b/packages/runtime-core/src/apiInject.ts index 2e1d428d1b9..02dc69e9d29 100644 --- a/packages/runtime-core/src/apiInject.ts +++ b/packages/runtime-core/src/apiInject.ts @@ -1,3 +1,4 @@ +import { isFunction } from '@vue/shared' import { currentInstance } from './component' import { currentRenderingInstance } from './componentRenderUtils' import { warn } from './warning' @@ -27,10 +28,15 @@ export function provide(key: InjectionKey | string, value: T) { } export function inject(key: InjectionKey | string): T | undefined -export function inject(key: InjectionKey | string, defaultValue: T): T +export function inject( + key: InjectionKey | string, + defaultValue: T, + treatDefaultAsFactory?: boolean +): T export function inject( key: InjectionKey | string, - defaultValue?: unknown + defaultValue?: unknown, + treatDefaultAsFactory = false ) { // fallback to `currentRenderingInstance` so that this can be called in // a functional component @@ -41,7 +47,9 @@ export function inject( // TS doesn't allow symbol as index type return provides[key as string] } else if (arguments.length > 1) { - return defaultValue + return treatDefaultAsFactory && isFunction(defaultValue) + ? defaultValue() + : defaultValue } else if (__DEV__) { warn(`injection "${String(key)}" not found.`) } diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index fd473714771..0eb24a6c2a1 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -457,7 +457,11 @@ export function applyOptions( for (const key in injectOptions) { const opt = injectOptions[key] if (isObject(opt)) { - ctx[key] = inject(opt.from, opt.default) + ctx[key] = inject( + opt.from, + opt.default, + true /* treat default function as factory */ + ) } else { ctx[key] = inject(opt) } From b19488e5d0adfa2bf74fe9f5a3f68d55d61caaf0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 12:23:20 +0000 Subject: [PATCH 09/51] build(deps-dev): bump @microsoft/api-extractor from 7.9.11 to 7.9.13 (#2068) --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1c14b26490c..39ee4f2bd01 100644 --- a/yarn.lock +++ b/yarn.lock @@ -586,22 +586,22 @@ resolved "https://registry.yarnpkg.com/@ls-lint/ls-lint/-/ls-lint-1.9.2.tgz#689f1f4c06072823a726802ba167340efcefe19c" integrity sha512-sugEjWjSSy9OHF6t1ZBLZCAROj52cZthB9dIePmzZzzMwmWwy3qAEMSdJheHeS1FOwDZI7Ipm1H/bWgzJNnSAw== -"@microsoft/api-extractor-model@7.8.19": - version "7.8.19" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.19.tgz#a49fb1b3f454966c4f60e8d63ffae2599eeaace3" - integrity sha512-tEEPuww0Gbyw9LuTcJ7nDCTjb+aLSAox8Xl9/iSxNTv5yHJN1QX3cqajlC3ibDHlRz7oMpQfHZX7YpAygbgIvg== +"@microsoft/api-extractor-model@7.8.21": + version "7.8.21" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.21.tgz#0d394a3414ff7222fc51ed7e00f9b732bd6a1fd2" + integrity sha512-gpg92BaN1mlxvSvyFMTPkcIZOqC9Q5pX/cKqkF+rtH0RXVQXL7ck9LWyM6gSrd/ricz/ARlsyTlLPNq2vJZg7A== dependencies: "@microsoft/tsdoc" "0.12.19" - "@rushstack/node-core-library" "3.30.0" + "@rushstack/node-core-library" "3.31.0" "@microsoft/api-extractor@^7.9.7": - version "7.9.11" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.11.tgz#ba4276bf1343f6e9df2560e77e7861af4e8740dd" - integrity sha512-t+LwGAuTjr+odFEl5xV3vl7qOWf84CM8BWKgb93kEnVd8uha3KfuWtDfnstxG4oC/TL6tu5+9rOwKJiNIidf2A== + version "7.9.13" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.13.tgz#33d1cafe4e821096e83f8856da62d2388d025956" + integrity sha512-hWpNLeHv4zwEn0UBhgSDN3Fn8YVVU8Ti8IMTy6Ik/AC7AEwU6QzGRnH5GSxbkfig+K22dmnwxljyxy6FAkam+g== dependencies: - "@microsoft/api-extractor-model" "7.8.19" + "@microsoft/api-extractor-model" "7.8.21" "@microsoft/tsdoc" "0.12.19" - "@rushstack/node-core-library" "3.30.0" + "@rushstack/node-core-library" "3.31.0" "@rushstack/ts-command-line" "4.6.4" colors "~1.2.1" lodash "~4.17.15" @@ -665,10 +665,10 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rushstack/node-core-library@3.30.0": - version "3.30.0" - resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.30.0.tgz#a2b814a611a040ac69d6c31ffc92bf9155c983fb" - integrity sha512-vZo1fi/ObL3CmRXlQUX/E1xL9KL9arBfCJ7pYf3O/vFrD8ffSfpQ6+6lhgAsKrCIM5Epddsgeb2REPxMwYZX1g== +"@rushstack/node-core-library@3.31.0": + version "3.31.0" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.31.0.tgz#80e8f50e5b438e68627a928ab8f45661860dc04f" + integrity sha512-GN/nKEszlKvW4Efhmicbk/s+mY6cshXexINl+W1OBtq2AaTae1QI0XjGjCp6cCygW7PltilJ5EOKGEtTQg2mew== dependencies: "@types/node" "10.17.13" colors "~1.2.1" From 02e95fc977188321371571cc414832c0be47f105 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 12:26:35 +0000 Subject: [PATCH 10/51] build(deps-dev): bump @types/jest from 26.0.12 to 26.0.13 (#2069) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 39ee4f2bd01..8997bf0410f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -828,9 +828,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@26.x", "@types/jest@^26.0.0": - version "26.0.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.12.tgz#0f20fef9e74f55a312530284e6178f3b3254f501" - integrity sha512-vZOFjm562IPb1EmaKxMjdcouxVb1l3NqoUH4XC4tDQ2R/AWde+0HXBUhyfc6L+7vc3mJ393U+5vr3nH2CLSVVg== + version "26.0.13" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.13.tgz#5a7b9d5312f5dd521a38329c38ee9d3802a0b85e" + integrity sha512-sCzjKow4z9LILc6DhBvn5AkIfmQzDZkgtVVKmGwVrs5tuid38ws281D4l+7x1kP487+FlKDh5kfMZ8WSPAdmdA== dependencies: jest-diff "^25.2.1" pretty-format "^25.2.1" From e474754c7687e2815e303a9b43d47868d27ad318 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 12:27:49 +0000 Subject: [PATCH 11/51] build(deps-dev): bump lint-staged from 10.2.13 to 10.3.0 (#2070) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8997bf0410f..94061dead2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4551,9 +4551,9 @@ lines-and-columns@^1.1.6: integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= lint-staged@^10.2.10: - version "10.2.13" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.2.13.tgz#b9c504683470edfc464b7d3fe3845a5a1efcd814" - integrity sha512-conwlukNV6aL9SiMWjFtDp5exeDnTMekdNPDZsKGnpfQuHcO0E3L3Bbf58lcR+M7vk6LpCilxDAVks/DDVBYlA== + version "10.3.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.3.0.tgz#388c3d440590c45c339e7163f669ea69ae90b1e0" + integrity sha512-an3VgjHqmJk0TORB/sdQl0CTkRg4E5ybYCXTTCSJ5h9jFwZbcgKIx5oVma5e7wp/uKt17s1QYFmYqT9MGVosGw== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" From b53d45de65239fa4acd9c6bc41ed58fc9b823729 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 21:25:00 +0000 Subject: [PATCH 12/51] build(deps-dev): bump rollup from 2.26.9 to 2.26.10 (#2067) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 94061dead2e..cbef9c34538 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6303,9 +6303,9 @@ rollup-pluginutils@^2.3.1: estree-walker "^0.6.1" rollup@^2.16.1: - version "2.26.9" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.9.tgz#4b6ce4e9044dd257d7314d8ed9b4d4d8a7d166c9" - integrity sha512-XIiWYLayLqV+oY4S2Lub/shJq4uk/QQLwWToYCL4LjZbYHbFK3czea4UDVRUJu+zNmKmxq5Zb/OG7c5HSvH2TQ== + version "2.26.10" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.10.tgz#0ffe0390d35f07af850382f22f1b8525c7f57f07" + integrity sha512-dUnjCWOA0h9qNX6qtcHidyatz8FAFZxVxt1dbcGtKdlJkpSxGK3G9+DLCYvtZr9v94D129ij9zUhG+xbRoqepw== optionalDependencies: fsevents "~2.1.2" From 629439039168ab7b768922aab6b26e6e4d52a762 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 00:01:55 +0000 Subject: [PATCH 13/51] build(deps-dev): bump @types/puppeteer from 2.1.2 to 2.1.3 (#2074) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cbef9c34538..5f0ddd9929c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -881,9 +881,9 @@ integrity sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ== "@types/puppeteer@^2.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-2.1.2.tgz#75b870c7f8fe4bdf76c3bb30c997c3904611d839" - integrity sha512-rNPCKZ+PuHR11au5Qu36TK63i9ppcdvREyEUd45jGc9Yj4AsoLpiCm22ebwDDRSzNc1N2+XOmaa5i6ZSW8FOMQ== + version "2.1.3" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-2.1.3.tgz#6f9963ad4f70b717f2cd399cb738149db6f70b21" + integrity sha512-ZYRfnd4oj2fxdGA+uNn1cBQYfBJK4xQLIKmG7ONoCoyOhksk68e5mzFI/zgvFHSxX0Qf6MITb+IZlHFGS6ipLw== dependencies: "@types/node" "*" From 110e96d1524fa9ff6d2b1fb0f26af0c4d0cb6ff7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 00:05:06 +0000 Subject: [PATCH 14/51] build(deps-dev): bump rollup from 2.26.10 to 2.26.11 (#2075) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5f0ddd9929c..12e2d77ab47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6303,9 +6303,9 @@ rollup-pluginutils@^2.3.1: estree-walker "^0.6.1" rollup@^2.16.1: - version "2.26.10" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.10.tgz#0ffe0390d35f07af850382f22f1b8525c7f57f07" - integrity sha512-dUnjCWOA0h9qNX6qtcHidyatz8FAFZxVxt1dbcGtKdlJkpSxGK3G9+DLCYvtZr9v94D129ij9zUhG+xbRoqepw== + version "2.26.11" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.11.tgz#4fc31de9c7b83d50916fc8395f8c3d24730cdaae" + integrity sha512-xyfxxhsE6hW57xhfL1I+ixH8l2bdoIMaAecdQiWF3N7IgJEMu99JG+daBiSZQjnBpzFxa0/xZm+3pbCdAQehHw== optionalDependencies: fsevents "~2.1.2" From 7417bac08bcc7d5e240c33434aae589d0054a519 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 11 Sep 2020 05:12:43 +0000 Subject: [PATCH 15/51] build(deps-dev): bump @microsoft/api-extractor from 7.9.13 to 7.9.14 (#2098) --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index 12e2d77ab47..b1d07230988 100644 --- a/yarn.lock +++ b/yarn.lock @@ -586,22 +586,22 @@ resolved "https://registry.yarnpkg.com/@ls-lint/ls-lint/-/ls-lint-1.9.2.tgz#689f1f4c06072823a726802ba167340efcefe19c" integrity sha512-sugEjWjSSy9OHF6t1ZBLZCAROj52cZthB9dIePmzZzzMwmWwy3qAEMSdJheHeS1FOwDZI7Ipm1H/bWgzJNnSAw== -"@microsoft/api-extractor-model@7.8.21": - version "7.8.21" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.21.tgz#0d394a3414ff7222fc51ed7e00f9b732bd6a1fd2" - integrity sha512-gpg92BaN1mlxvSvyFMTPkcIZOqC9Q5pX/cKqkF+rtH0RXVQXL7ck9LWyM6gSrd/ricz/ARlsyTlLPNq2vJZg7A== +"@microsoft/api-extractor-model@7.8.22": + version "7.8.22" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.22.tgz#cec02dc6663208c14c4a1ecfb36acaf106414f6a" + integrity sha512-wca7qUwcA5wD2qVoCRLiWHl2XPspjJQHmEWSOTnyoYXmLMxgKsAxz1jN5rlAcLIm2U8DLX8DSzvSWBXnLH7OPg== dependencies: "@microsoft/tsdoc" "0.12.19" - "@rushstack/node-core-library" "3.31.0" + "@rushstack/node-core-library" "3.32.0" "@microsoft/api-extractor@^7.9.7": - version "7.9.13" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.13.tgz#33d1cafe4e821096e83f8856da62d2388d025956" - integrity sha512-hWpNLeHv4zwEn0UBhgSDN3Fn8YVVU8Ti8IMTy6Ik/AC7AEwU6QzGRnH5GSxbkfig+K22dmnwxljyxy6FAkam+g== + version "7.9.14" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.14.tgz#d9ea209a8218040c3c02322a1ad99167fc0e33e0" + integrity sha512-B6pcw/CuvC8oxaLjTkVwHl4FLDbNx/8ezuR4RW+qfzT+yCwvyy0XCrnT025EqBha1bPKjNEjEmUgsNZKwhcDqw== dependencies: - "@microsoft/api-extractor-model" "7.8.21" + "@microsoft/api-extractor-model" "7.8.22" "@microsoft/tsdoc" "0.12.19" - "@rushstack/node-core-library" "3.31.0" + "@rushstack/node-core-library" "3.32.0" "@rushstack/ts-command-line" "4.6.4" colors "~1.2.1" lodash "~4.17.15" @@ -665,10 +665,10 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rushstack/node-core-library@3.31.0": - version "3.31.0" - resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.31.0.tgz#80e8f50e5b438e68627a928ab8f45661860dc04f" - integrity sha512-GN/nKEszlKvW4Efhmicbk/s+mY6cshXexINl+W1OBtq2AaTae1QI0XjGjCp6cCygW7PltilJ5EOKGEtTQg2mew== +"@rushstack/node-core-library@3.32.0": + version "3.32.0" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.32.0.tgz#b40de3a23c3106b94265344a2362195f418fabb2" + integrity sha512-7xM++fJNvCKjbnB4k6y52uCOOu1s7PNbcSup18yfml9q2e2c1qKULy/A41SFgdD2J0L6UP2SD9K5lbQt+OoWjQ== dependencies: "@types/node" "10.17.13" colors "~1.2.1" From d0b56d2fcc393a5e5b4b26f49830bf3b7f638b35 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2020 12:02:45 +0000 Subject: [PATCH 16/51] build(deps-dev): bump eslint from 7.8.1 to 7.9.0 (#2114) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b1d07230988..960a8ca60e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2613,9 +2613,9 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint@^7.7.0: - version "7.8.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.8.1.tgz#e59de3573fb6a5be8ff526c791571646d124a8fa" - integrity sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w== + version "7.9.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.9.0.tgz#522aeccc5c3a19017cf0cb46ebfd660a79acf337" + integrity sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA== dependencies: "@babel/code-frame" "^7.0.0" "@eslint/eslintrc" "^0.1.3" From 2f7924d53090b2e51be881739416dc324cc7b1da Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2020 12:03:04 +0000 Subject: [PATCH 17/51] build(deps-dev): bump @microsoft/api-extractor from 7.9.14 to 7.9.15 (#2113) --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 960a8ca60e0..a3170a3a9a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -586,20 +586,20 @@ resolved "https://registry.yarnpkg.com/@ls-lint/ls-lint/-/ls-lint-1.9.2.tgz#689f1f4c06072823a726802ba167340efcefe19c" integrity sha512-sugEjWjSSy9OHF6t1ZBLZCAROj52cZthB9dIePmzZzzMwmWwy3qAEMSdJheHeS1FOwDZI7Ipm1H/bWgzJNnSAw== -"@microsoft/api-extractor-model@7.8.22": - version "7.8.22" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.22.tgz#cec02dc6663208c14c4a1ecfb36acaf106414f6a" - integrity sha512-wca7qUwcA5wD2qVoCRLiWHl2XPspjJQHmEWSOTnyoYXmLMxgKsAxz1jN5rlAcLIm2U8DLX8DSzvSWBXnLH7OPg== +"@microsoft/api-extractor-model@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.9.0.tgz#9b0c0db3821937454bbd5d1441c0634801dacd31" + integrity sha512-zXBA4D/gE7BkNU5jjiKSoXGK+h6N+TQHa47ut/a5CYcVzjxXWVdLpew+tGnyRW/7eRhbS6qzzdQ/dAgraDfReA== dependencies: "@microsoft/tsdoc" "0.12.19" "@rushstack/node-core-library" "3.32.0" "@microsoft/api-extractor@^7.9.7": - version "7.9.14" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.14.tgz#d9ea209a8218040c3c02322a1ad99167fc0e33e0" - integrity sha512-B6pcw/CuvC8oxaLjTkVwHl4FLDbNx/8ezuR4RW+qfzT+yCwvyy0XCrnT025EqBha1bPKjNEjEmUgsNZKwhcDqw== + version "7.9.15" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.15.tgz#72fe4ccc2fe40c5114546b11d2aa3e8eb2bd6c19" + integrity sha512-j3BrAXTc3M51vUe32hC47i4JoJBqbR2iJaV6Vhew1+BzBkg4bJJziT6V3EbCdKt60rbEWSV/30EMwwdXVyqL5A== dependencies: - "@microsoft/api-extractor-model" "7.8.22" + "@microsoft/api-extractor-model" "7.9.0" "@microsoft/tsdoc" "0.12.19" "@rushstack/node-core-library" "3.32.0" "@rushstack/ts-command-line" "4.6.4" From 542680e4786892b7d8f149389e2402ab0a0cda21 Mon Sep 17 00:00:00 2001 From: Wuzado <23276409+Wuzado@users.noreply.github.com> Date: Mon, 14 Sep 2020 16:45:32 +0200 Subject: [PATCH 18/51] chore(readme): update link to the JSX babel plugin (#2104) [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e34cf0b6d45..e2750cf8409 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when There are currently two JSX transform implementations for Vue 3 with slightly differing syntax (for Vue specific features): -- [vueComponent/jsx](https://github.com/vueComponent/jsx) +- [vuejs/jsx-next](https://github.com/vuejs/jsx-next) - [HcySunYang/vue-next-jsx](https://github.com/HcySunYang/vue-next-jsx) 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. From cf1b6c666f45a284494f80981522a3dc4804a683 Mon Sep 17 00:00:00 2001 From: Pick Date: Mon, 14 Sep 2020 23:16:50 +0800 Subject: [PATCH 19/51] feat(runtime-dom): allow native Set as v-model checkbox source (#1957) --- .../__tests__/directives/vModel.spec.ts | 70 +++++++++++++++++++ packages/runtime-dom/src/directives/vModel.ts | 28 ++++++-- packages/shared/src/index.ts | 3 + packages/shared/src/looseEqual.ts | 7 ++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/packages/runtime-dom/__tests__/directives/vModel.spec.ts b/packages/runtime-dom/__tests__/directives/vModel.spec.ts index c8b3531ffb9..33d48e5fc6c 100644 --- a/packages/runtime-dom/__tests__/directives/vModel.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vModel.spec.ts @@ -433,6 +433,76 @@ describe('vModel', () => { expect(bar.checked).toEqual(false) }) + it(`should support Set as a checkbox model`, async () => { + const component = defineComponent({ + data() { + return { value: new Set() } + }, + render() { + return [ + withVModel( + h('input', { + type: 'checkbox', + class: 'foo', + value: 'foo', + 'onUpdate:modelValue': setValue.bind(this) + }), + this.value + ), + withVModel( + h('input', { + type: 'checkbox', + class: 'bar', + value: 'bar', + 'onUpdate:modelValue': setValue.bind(this) + }), + this.value + ) + ] + } + }) + render(h(component), root) + + const foo = root.querySelector('.foo') + const bar = root.querySelector('.bar') + const data = root._vnode.component.data + + foo.checked = true + triggerEvent('change', foo) + await nextTick() + expect(data.value).toMatchObject(new Set(['foo'])) + + bar.checked = true + triggerEvent('change', bar) + await nextTick() + expect(data.value).toMatchObject(new Set(['foo', 'bar'])) + + bar.checked = false + triggerEvent('change', bar) + await nextTick() + expect(data.value).toMatchObject(new Set(['foo'])) + + foo.checked = false + triggerEvent('change', foo) + await nextTick() + expect(data.value).toMatchObject(new Set()) + + data.value = new Set(['foo']) + await nextTick() + expect(bar.checked).toEqual(false) + expect(foo.checked).toEqual(true) + + data.value = new Set(['bar']) + await nextTick() + expect(foo.checked).toEqual(false) + expect(bar.checked).toEqual(true) + + data.value = new Set() + await nextTick() + expect(foo.checked).toEqual(false) + expect(bar.checked).toEqual(false) + }) + it('should work with radio', async () => { const component = defineComponent({ data() { diff --git a/packages/runtime-dom/src/directives/vModel.ts b/packages/runtime-dom/src/directives/vModel.ts index 23ebb07b359..ea1098dd19b 100644 --- a/packages/runtime-dom/src/directives/vModel.ts +++ b/packages/runtime-dom/src/directives/vModel.ts @@ -11,7 +11,9 @@ import { looseEqual, looseIndexOf, invokeArrayFns, - toNumber + toNumber, + isSet, + looseHas } from '@vue/shared' type AssignerFn = (value: any) => void @@ -111,6 +113,14 @@ export const vModelCheckbox: ModelDirective = { filtered.splice(index, 1) assign(filtered) } + } else if (isSet(modelValue)) { + const found = modelValue.has(elementValue) + if (checked && !found) { + assign(modelValue.add(elementValue)) + } else if (!checked && found) { + modelValue.delete(elementValue) + assign(modelValue) + } } else { assign(getCheckboxValue(el, checked)) } @@ -132,6 +142,8 @@ function setChecked( ;(el as any)._modelValue = value if (isArray(value)) { el.checked = looseIndexOf(value, vnode.props!.value) > -1 + } else if (isSet(value)) { + el.checked = looseHas(value, vnode.props!.value) } else if (value !== oldValue) { el.checked = looseEqual(value, getCheckboxValue(el, true)) } @@ -178,10 +190,10 @@ export const vModelSelect: ModelDirective = { function setSelected(el: HTMLSelectElement, value: any) { const isMultiple = el.multiple - if (isMultiple && !isArray(value)) { + if (isMultiple && !isArray(value) && !isSet(value)) { __DEV__ && warn( - ` expects an Array or Set value for its binding, ` + `but got ${Object.prototype.toString.call(value).slice(8, -1)}.` ) return @@ -190,7 +202,11 @@ function setSelected(el: HTMLSelectElement, value: any) { const option = el.options[i] const optionValue = getValue(option) if (isMultiple) { - option.selected = looseIndexOf(value, optionValue) > -1 + if (isArray(value)) { + option.selected = looseIndexOf(value, optionValue) > -1 + } else { + option.selected = looseHas(value, optionValue) + } } else { if (looseEqual(getValue(option), value)) { el.selectedIndex = i @@ -280,6 +296,10 @@ if (__NODE_JS__) { if (vnode.props && looseIndexOf(value, vnode.props.value) > -1) { return { checked: true } } + } else if (isSet(value)) { + if (vnode.props && looseHas(value, vnode.props.value)) { + return { checked: true } + } } else if (value) { return { checked: true } } diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 69739cae251..2178c5f1ee7 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -58,6 +58,9 @@ export const hasOwn = ( ): key is keyof typeof val => hasOwnProperty.call(val, key) export const isArray = Array.isArray +export const isSet = (val: any): boolean => { + return toRawType(val) === 'Set' +} export const isDate = (val: unknown): val is Date => val instanceof Date export const isFunction = (val: unknown): val is Function => typeof val === 'function' diff --git a/packages/shared/src/looseEqual.ts b/packages/shared/src/looseEqual.ts index 030f0338b30..076ea7b5569 100644 --- a/packages/shared/src/looseEqual.ts +++ b/packages/shared/src/looseEqual.ts @@ -51,3 +51,10 @@ export function looseEqual(a: any, b: any): boolean { export function looseIndexOf(arr: any[], val: any): number { return arr.findIndex(item => looseEqual(item, val)) } + +export function looseHas(set: Set, val: any): boolean { + for (let item of set) { + if (looseEqual(item, val)) return true + } + return false +} From 0124eacc91bc03a9bcf135f09258c2448452423e Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 14 Sep 2020 11:26:34 -0400 Subject: [PATCH 20/51] refactor(reactivity): refactor iteration key trigger logic + use more robust Map/Set check --- packages/reactivity/src/collectionHandlers.ts | 12 +++--- packages/reactivity/src/effect.ts | 40 +++++++++++++------ packages/runtime-core/src/apiWatch.ts | 10 +++-- packages/shared/src/index.ts | 8 ++-- packages/shared/src/toDisplayString.ts | 6 +-- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/packages/reactivity/src/collectionHandlers.ts b/packages/reactivity/src/collectionHandlers.ts index 24ae1515610..6ff76c671b3 100644 --- a/packages/reactivity/src/collectionHandlers.ts +++ b/packages/reactivity/src/collectionHandlers.ts @@ -6,7 +6,8 @@ import { capitalize, hasOwn, hasChanged, - toRawType + toRawType, + isMap } from '@vue/shared' export type CollectionTypes = IterableCollections | WeakCollections @@ -129,7 +130,7 @@ function clear(this: IterableCollections) { const target = toRaw(this) const hadItems = target.size !== 0 const oldTarget = __DEV__ - ? target instanceof Map + ? isMap(target) ? new Map(target) : new Set(target) : undefined @@ -185,9 +186,10 @@ function createIterableMethod( ): Iterable & Iterator { const target = (this as any)[ReactiveFlags.RAW] const rawTarget = toRaw(target) - const isMap = rawTarget instanceof Map - const isPair = method === 'entries' || (method === Symbol.iterator && isMap) - const isKeyOnly = method === 'keys' && isMap + const targetIsMap = isMap(rawTarget) + const isPair = + method === 'entries' || (method === Symbol.iterator && targetIsMap) + const isKeyOnly = method === 'keys' && targetIsMap const innerIterator = target[method](...args) const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive !isReadonly && diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index a4d087beade..495d6714939 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -1,5 +1,5 @@ import { TrackOpTypes, TriggerOpTypes } from './operations' -import { EMPTY_OBJ, isArray, isIntegerKey } from '@vue/shared' +import { EMPTY_OBJ, isArray, isIntegerKey, isMap } from '@vue/shared' // The main WeakMap that stores {target -> key -> dep} connections. // Conceptually, it's easier to think of a dependency as a Dep class @@ -197,19 +197,33 @@ export function trigger( if (key !== void 0) { add(depsMap.get(key)) } + // also run for iteration key on ADD | DELETE | Map.SET - const shouldTriggerIteration = - (type === TriggerOpTypes.ADD && - (!isArray(target) || isIntegerKey(key))) || - (type === TriggerOpTypes.DELETE && !isArray(target)) - if ( - shouldTriggerIteration || - (type === TriggerOpTypes.SET && target instanceof Map) - ) { - add(depsMap.get(isArray(target) ? 'length' : ITERATE_KEY)) - } - if (shouldTriggerIteration && target instanceof Map) { - add(depsMap.get(MAP_KEY_ITERATE_KEY)) + switch (type) { + case TriggerOpTypes.ADD: + if (!isArray(target)) { + add(depsMap.get(ITERATE_KEY)) + if (isMap(target)) { + add(depsMap.get(MAP_KEY_ITERATE_KEY)) + } + } else if (isIntegerKey(key)) { + // new index added to array -> length changes + add(depsMap.get('length')) + } + break + case TriggerOpTypes.DELETE: + if (!isArray(target)) { + add(depsMap.get(ITERATE_KEY)) + if (isMap(target)) { + add(depsMap.get(MAP_KEY_ITERATE_KEY)) + } + } + break + case TriggerOpTypes.SET: + if (isMap(target)) { + add(depsMap.get(ITERATE_KEY)) + } + break } } diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 9c131067feb..ac1b1d16d7f 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -16,7 +16,9 @@ import { isString, hasChanged, NOOP, - remove + remove, + isMap, + isSet } from '@vue/shared' import { currentInstance, @@ -335,12 +337,12 @@ function traverse(value: unknown, seen: Set = new Set()) { for (let i = 0; i < value.length; i++) { traverse(value[i], seen) } - } else if (value instanceof Map) { - value.forEach((v, key) => { + } else if (isMap(value)) { + value.forEach((_, key) => { // to register mutation dep for existing keys traverse(value.get(key), seen) }) - } else if (value instanceof Set) { + } else if (isSet(value)) { value.forEach(v => { traverse(v, seen) }) diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 2178c5f1ee7..7daeaa5242c 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -58,9 +58,11 @@ export const hasOwn = ( ): key is keyof typeof val => hasOwnProperty.call(val, key) export const isArray = Array.isArray -export const isSet = (val: any): boolean => { - return toRawType(val) === 'Set' -} +export const isMap = (val: unknown): val is Map => + toTypeString(val) === '[object Map]' +export const isSet = (val: unknown): val is Set => + toTypeString(val) === '[object Set]' + export const isDate = (val: unknown): val is Date => val instanceof Date export const isFunction = (val: unknown): val is Function => typeof val === 'function' diff --git a/packages/shared/src/toDisplayString.ts b/packages/shared/src/toDisplayString.ts index 2c9b6ab48c7..1d0b6928400 100644 --- a/packages/shared/src/toDisplayString.ts +++ b/packages/shared/src/toDisplayString.ts @@ -1,4 +1,4 @@ -import { isArray, isObject, isPlainObject } from './index' +import { isArray, isMap, isObject, isPlainObject, isSet } from './index' /** * For converting {{ interpolation }} values to displayed strings. @@ -13,14 +13,14 @@ export const toDisplayString = (val: unknown): string => { } const replacer = (_key: string, val: any) => { - if (val instanceof Map) { + if (isMap(val)) { return { [`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => { ;(entries as any)[`${key} =>`] = val return entries }, {}) } - } else if (val instanceof Set) { + } else if (isSet(val)) { return { [`Set(${val.size})`]: [...val.values()] } From 24fcf6ae7cd75c782a5aa2771aca259542e2a680 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Mon, 14 Sep 2020 23:28:56 +0800 Subject: [PATCH 21/51] fix(types): properly infer return type from async setup (#2051) fix #2049 --- .../runtime-core/src/apiDefineComponent.ts | 11 +++--- packages/runtime-core/src/componentOptions.ts | 2 ++ .../src/componentPublicInstance.ts | 5 +-- test-dts/defineComponent.test-d.tsx | 36 +++++++++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index eda62eaab03..c054e65a8eb 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -5,7 +5,8 @@ import { ComponentOptionsWithArrayProps, ComponentOptionsWithObjectProps, ComponentOptionsMixin, - RenderFunction + RenderFunction, + UnwrapAsyncBindings } from './componentOptions' import { SetupContext, @@ -37,7 +38,7 @@ export function defineComponent( ): ComponentPublicInstanceConstructor< CreateComponentPublicInstance< Props, - RawBindings, + UnwrapAsyncBindings, {}, {}, {}, @@ -78,7 +79,7 @@ export function defineComponent< ): ComponentPublicInstanceConstructor< CreateComponentPublicInstance< Props, - RawBindings, + UnwrapAsyncBindings, D, C, M, @@ -130,7 +131,7 @@ export function defineComponent< // but now we can export array props in TSX CreateComponentPublicInstance< Readonly<{ [key in PropNames]?: any }>, - RawBindings, + UnwrapAsyncBindings, D, C, M, @@ -181,7 +182,7 @@ export function defineComponent< ): ComponentPublicInstanceConstructor< CreateComponentPublicInstance< ExtractPropTypes, - RawBindings, + UnwrapAsyncBindings, D, C, M, diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 0eb24a6c2a1..d02a1bb0bdc 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -72,6 +72,8 @@ export interface ComponentCustomOptions {} export type RenderFunction = () => VNodeChild +export type UnwrapAsyncBindings = T extends Promise ? S : T + export interface ComponentOptionsBase< Props, RawBindings, diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index 695e5ace3c9..77fcbeeae26 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -27,7 +27,8 @@ import { OptionTypesType, OptionTypesKeys, resolveMergedOptions, - isInBeforeCreate + isInBeforeCreate, + UnwrapAsyncBindings } from './componentOptions' import { EmitsOptions, EmitFn } from './componentEmits' import { Slots } from './componentSlots' @@ -168,7 +169,7 @@ export type ComponentPublicInstance< options?: WatchOptions ): WatchStopHandle } & P & - ShallowUnwrapRef & + ShallowUnwrapRef> & D & ExtractComputedReturns & M & diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index 18c3338abeb..59d6a3bcb28 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -864,3 +864,39 @@ describe('extract instance type', () => { // @ts-expect-error expectError((compA.baseA = 1)) }) + +describe('async setup', () => { + type GT = string & { __brand: unknown } + const Comp = defineComponent({ + async setup() { + // setup context + return { + a: ref(1), + b: { + c: ref('hi') + }, + d: reactive({ + e: ref('hello' as GT) + }) + } + }, + render() { + // assert setup context unwrapping + expectType(this.a) + expectType(this.b.c.value) + expectType(this.d.e) + + // setup context properties should be mutable + this.a = 2 + } + }) + + const vm = {} as InstanceType + // assert setup context unwrapping + expectType(vm.a) + expectType(vm.b.c.value) + expectType(vm.d.e) + + // setup context properties should be mutable + vm.a = 2 +}) From a096a58e412dc37ae618a3b4702f591c580d376a Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 14 Sep 2020 12:41:35 -0400 Subject: [PATCH 22/51] fix(compiler-core): fix v-if block handling for components that fail to resolve fix #2058 --- .../compiler-core/__tests__/transforms/vIf.spec.ts | 4 +++- packages/compiler-core/src/transforms/vIf.ts | 12 ++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/vIf.spec.ts b/packages/compiler-core/__tests__/transforms/vIf.spec.ts index a93c6053e1c..315497a590c 100644 --- a/packages/compiler-core/__tests__/transforms/vIf.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vIf.spec.ts @@ -93,10 +93,12 @@ describe('compiler: v-if', () => { expect((node.branches[0].children[0] as ElementNode).tagType).toBe( ElementTypes.COMPONENT ) + // #2058 since a component may fail to resolve and fallback to a plain + // element, it still needs to be made a block expect( ((node.branches[0].children[0] as ElementNode)! .codegenNode as VNodeCall)!.isBlock - ).toBe(false) + ).toBe(true) }) test('v-if + v-else', () => { diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts index bebf3eb9082..2c00349254d 100644 --- a/packages/compiler-core/src/transforms/vIf.ts +++ b/packages/compiler-core/src/transforms/vIf.ts @@ -29,8 +29,7 @@ import { CREATE_BLOCK, FRAGMENT, CREATE_COMMENT, - OPEN_BLOCK, - TELEPORT + OPEN_BLOCK } from '../runtimeHelpers' import { injectProp, findDir, findProp } from '../utils' import { PatchFlags, PatchFlagNames } from '@vue/shared' @@ -255,14 +254,7 @@ function createChildrenCodegenNode( const vnodeCall = (firstChild as ElementNode) .codegenNode as BlockCodegenNode // Change createVNode to createBlock. - if ( - vnodeCall.type === NodeTypes.VNODE_CALL && - // component vnodes are always tracked and its children are - // compiled into slots so no need to make it a block - ((firstChild as ElementNode).tagType !== ElementTypes.COMPONENT || - // teleport has component type but isn't always tracked - vnodeCall.tag === TELEPORT) - ) { + if (vnodeCall.type === NodeTypes.VNODE_CALL) { vnodeCall.isBlock = true helper(OPEN_BLOCK) helper(CREATE_BLOCK) From 313dd06065b1782d67f6881fbd42ae92a7f9cade Mon Sep 17 00:00:00 2001 From: Stanislav Lashmanov Date: Mon, 14 Sep 2020 19:52:19 +0300 Subject: [PATCH 23/51] fix(runtime-core/inject): handle optional `from` option in inject object config (#2073) --- .../runtime-core/__tests__/apiOptions.spec.ts | 35 ++++++++++++++++--- packages/runtime-core/src/componentOptions.ts | 4 +-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 4dd1910bfa1..00ecb6e4c4c 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -253,7 +253,16 @@ describe('api: options', () => { } }, render() { - return [h(ChildA), h(ChildB), h(ChildC), h(ChildD), h(ChildE)] + return [ + h(ChildA), + h(ChildB), + h(ChildC), + h(ChildD), + h(ChildE), + h(ChildF), + h(ChildG), + h(ChildH) + ] } }) @@ -272,19 +281,37 @@ describe('api: options', () => { from: 'a' } }) - const ChildD = defineChild({ + const ChildD = defineChild( + { + a: { + default: () => 0 + } + }, + 'a' + ) + const ChildE = defineChild({ b: { from: 'c', default: 2 } }) - const ChildE = defineChild({ + const ChildF = defineChild({ b: { from: 'c', default: () => 3 } }) - expect(renderToString(h(Root))).toBe(`11123`) + const ChildG = defineChild({ + b: { + default: 4 + } + }) + const ChildH = defineChild({ + b: { + default: () => 5 + } + }) + expect(renderToString(h(Root))).toBe(`11112345`) }) test('lifecycle', async () => { diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index d02a1bb0bdc..672cb8af92a 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -275,7 +275,7 @@ type ComponentInjectOptions = | string[] | Record< string | symbol, - string | symbol | { from: string | symbol; default?: unknown } + string | symbol | { from?: string | symbol; default?: unknown } > interface LegacyOptions< @@ -460,7 +460,7 @@ export function applyOptions( const opt = injectOptions[key] if (isObject(opt)) { ctx[key] = inject( - opt.from, + opt.from || key, opt.default, true /* treat default function as factory */ ) From 612eb6712a3858e4280946d98153b6f35792c652 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 14 Sep 2020 15:33:38 -0400 Subject: [PATCH 24/51] fix(runtime-core/refs): handle multiple merged refs for dynamic component with vnode fix #2078 --- .../__tests__/apiTemplateRef.spec.ts | 42 ++++++++++++++++++- packages/runtime-core/src/renderer.ts | 20 +++++++-- packages/runtime-core/src/vnode.ts | 35 ++++++++++++---- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts index 808731c230e..1c82d20ec42 100644 --- a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts @@ -6,7 +6,8 @@ import { nextTick, defineComponent, reactive, - serializeInner + serializeInner, + shallowRef } from '@vue/runtime-test' // reference: https://vue-composition-api-rfc.netlify.com/api.html#template-refs @@ -325,4 +326,43 @@ describe('api: template refs', () => { await nextTick() expect(spy.mock.calls[1][0]).toBe('p') }) + + // #2078 + test('handling multiple merged refs', async () => { + const Foo = { + render: () => h('div', 'foo') + } + const Bar = { + render: () => h('div', 'bar') + } + + const viewRef = shallowRef(Foo) + const elRef1 = ref() + const elRef2 = ref() + + const App = { + render() { + if (!viewRef.value) { + return null + } + const view = h(viewRef.value, { ref: elRef1 }) + return h(view, { ref: elRef2 }) + } + } + const root = nodeOps.createElement('div') + render(h(App), root) + + expect(serializeInner(elRef1.value.$el)).toBe('foo') + expect(elRef1.value).toBe(elRef2.value) + + viewRef.value = Bar + await nextTick() + expect(serializeInner(elRef1.value.$el)).toBe('bar') + expect(elRef1.value).toBe(elRef2.value) + + viewRef.value = null + await nextTick() + expect(elRef1.value).toBeNull() + expect(elRef1.value).toBe(elRef2.value) + }) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index a4cf97dc807..670cd41f5c0 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -10,7 +10,8 @@ import { isSameVNodeType, Static, VNodeNormalizedRef, - VNodeHook + VNodeHook, + VNodeNormalizedRefAtom } from './vnode' import { ComponentInternalInstance, @@ -284,6 +285,19 @@ export const setRef = ( parentSuspense: SuspenseBoundary | null, vnode: VNode | null ) => { + if (isArray(rawRef)) { + rawRef.forEach((r, i) => + setRef( + r, + oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef), + parentComponent, + parentSuspense, + vnode + ) + ) + return + } + let value: ComponentPublicInstance | RendererNode | null if (!vnode) { value = null @@ -295,7 +309,7 @@ export const setRef = ( } } - const [owner, ref] = rawRef + const { i: owner, r: ref } = rawRef if (__DEV__ && !owner) { warn( `Missing ref owner context. ref cannot be used on hoisted vnodes. ` + @@ -303,7 +317,7 @@ export const setRef = ( ) return } - const oldRef = oldRawRef && oldRawRef[1] + const oldRef = oldRawRef && (oldRawRef as VNodeNormalizedRefAtom).r const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs const setupState = owner.setupState diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 0c468fd06d5..a34358a9ccc 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -64,7 +64,14 @@ export type VNodeRef = | Ref | ((ref: object | null, refs: Record) => void) -export type VNodeNormalizedRef = [ComponentInternalInstance, VNodeRef] +export type VNodeNormalizedRefAtom = { + i: ComponentInternalInstance + r: VNodeRef +} + +export type VNodeNormalizedRef = + | VNodeNormalizedRefAtom + | (VNodeNormalizedRefAtom)[] type VNodeMountHook = (vnode: VNode) => void type VNodeUpdateHook = (vnode: VNode, oldVNode: VNode) => void @@ -289,11 +296,11 @@ export const InternalObjectKey = `__vInternal` const normalizeKey = ({ key }: VNodeProps): VNode['key'] => key != null ? key : null -const normalizeRef = ({ ref }: VNodeProps): VNode['ref'] => { +const normalizeRef = ({ ref }: VNodeProps): VNodeNormalizedRefAtom | null => { return (ref != null ? isArray(ref) ? ref - : [currentRenderingInstance!, ref] + : { i: currentRenderingInstance, r: ref } : null) as any } @@ -317,7 +324,10 @@ function _createVNode( } if (isVNode(type)) { - const cloned = cloneVNode(type, props) + // createVNode receiving an existing vnode. This happens in cases like + // + // #2078 make sure to merge refs during the clone instead of overwriting it + const cloned = cloneVNode(type, props, true /* mergeRef: true */) if (children) { normalizeChildren(cloned, children) } @@ -429,11 +439,12 @@ function _createVNode( export function cloneVNode( vnode: VNode, - extraProps?: Data & VNodeProps | null + extraProps?: Data & VNodeProps | null, + mergeRef = false ): VNode { // This is intentionally NOT using spread or extend to avoid the runtime // key enumeration cost. - const { props, patchFlag } = vnode + const { props, ref, patchFlag } = vnode const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props return { __v_isVNode: true, @@ -441,7 +452,17 @@ export function cloneVNode( type: vnode.type, props: mergedProps, key: mergedProps && normalizeKey(mergedProps), - ref: extraProps && extraProps.ref ? normalizeRef(extraProps) : vnode.ref, + ref: + extraProps && extraProps.ref + ? // #2078 in the case of + // if the vnode itself already has a ref, cloneVNode will need to merge + // the refs so the single vnode can be set on multiple refs + mergeRef && ref + ? isArray(ref) + ? ref.concat(normalizeRef(extraProps)!) + : [ref, normalizeRef(extraProps)!] + : normalizeRef(extraProps) + : ref, scopeId: vnode.scopeId, children: vnode.children, target: vnode.target, From a32870a8f611dd1146bb17d5605b168a7805c73f Mon Sep 17 00:00:00 2001 From: underfin Date: Tue, 15 Sep 2020 04:02:29 +0800 Subject: [PATCH 25/51] fix: inherit `el` for static nodes inside keyed `template` fragment (#2089) fix #2080 --- .../__tests__/rendererFragment.spec.ts | 48 ++++++++++++++++++- packages/runtime-core/src/renderer.ts | 18 +++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/packages/runtime-core/__tests__/rendererFragment.spec.ts b/packages/runtime-core/__tests__/rendererFragment.spec.ts index 9e1f87aec8e..93140f13f4e 100644 --- a/packages/runtime-core/__tests__/rendererFragment.spec.ts +++ b/packages/runtime-core/__tests__/rendererFragment.spec.ts @@ -10,9 +10,13 @@ import { dumpOps, NodeOpTypes, serializeInner, - createTextVNode + createTextVNode, + createBlock, + openBlock, + createCommentVNode } from '@vue/runtime-test' import { PatchFlags } from '@vue/shared' +import { renderList } from '../src/helpers/renderList' describe('renderer: fragment', () => { it('should allow returning multiple component root nodes', () => { @@ -269,4 +273,46 @@ describe('renderer: fragment', () => { render(null, root) expect(serializeInner(root)).toBe(``) }) + + // #2080 + test('`template` keyed fragment w/ comment + hoisted node', () => { + const root = nodeOps.createElement('div') + const hoisted = h('span') + + const renderFn = (items: string[]) => { + return ( + openBlock(true), + createBlock( + Fragment, + null, + renderList(items, item => { + return ( + openBlock(), + createBlock( + Fragment, + { key: item }, + [ + createCommentVNode('comment'), + hoisted, + createVNode('div', null, item, PatchFlags.TEXT) + ], + PatchFlags.STABLE_FRAGMENT + ) + ) + }), + PatchFlags.KEYED_FRAGMENT + ) + ) + } + + render(renderFn(['one', 'two']), root) + expect(serializeInner(root)).toBe( + `
one
two
` + ) + + render(renderFn(['two', 'one']), root) + expect(serializeInner(root)).toBe( + `
two
one
` + ) + }) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 670cd41f5c0..5246fcb1baa 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1153,8 +1153,10 @@ function baseCreateRenderer( parentSuspense, isSVG ) - if (__DEV__ && parentComponent && parentComponent.type.__hmrId) { - traverseStaticChildren(n1, n2) + // #2080 if the stable fragment has a key, it's a