From 14f1814292c8586802e4d1c6484a115e4000ce0f Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 4 Jan 2020 10:10:30 +0000 Subject: [PATCH 0001/5381] types: improve type error logging and nest ref types --- packages/reactivity/src/ref.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index e2ff79e1859..3c3159ce30b 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -84,18 +84,20 @@ function toProxyRef( type UnwrapArray = { [P in keyof T]: UnwrapRef } -// Recursively unwraps nested value bindings. -export type UnwrapRef = { - cRef: T extends ComputedRef ? UnwrapRef : T - ref: T extends Ref ? UnwrapRef : T - array: T extends Array ? Array> & UnwrapArray : T - object: { [K in keyof T]: UnwrapRef } -}[T extends ComputedRef - ? 'cRef' - : T extends Ref - ? 'ref' - : T extends Array - ? 'array' - : T extends Function | CollectionTypes - ? 'ref' // bail out on types that shouldn't be unwrapped - : T extends object ? 'object' : 'ref'] +type UnwrapProp = T extends ComputedRef + ? UnwrapRef + : T extends Ref + ? UnwrapRef + : T extends Function | CollectionTypes + ? T + : T extends object + ? UnwrapObject + : T extends Array ? Array> & UnwrapArray : T + +type UnwrapObject = { [K in keyof T]: UnwrapProp } + +export type UnwrapRef = T extends object + ? UnwrapObject + : T extends Function | CollectionTypes + ? T + : T extends Array ? Array> & UnwrapArray : T From 07ff08956ffc45eeba6a4df071b448c585b5ad6d Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 4 Jan 2020 14:09:52 +0000 Subject: [PATCH 0002/5381] chore: simplifying and improve tupple & array output type on ref --- packages/reactivity/src/ref.ts | 37 +++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 3c3159ce30b..b6df32a291f 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -82,22 +82,27 @@ function toProxyRef( } as any } -type UnwrapArray = { [P in keyof T]: UnwrapRef } +// Super simple tuple checker +type Tupple> = T[0] extends T[1] + ? T[1] extends T[2] ? never : true + : true -type UnwrapProp = T extends ComputedRef - ? UnwrapRef - : T extends Ref - ? UnwrapRef - : T extends Function | CollectionTypes - ? T - : T extends object - ? UnwrapObject - : T extends Array ? Array> & UnwrapArray : T +export type UnwrapRef = T extends ComputedRef + ? UnwrapRefSimple + : T extends Ref ? UnwrapRefSimple : UnwrapRefSimple -type UnwrapObject = { [K in keyof T]: UnwrapProp } +type UnwrapRefSimple = T extends Function | CollectionTypes + ? T + : T extends Array + ? Tupple extends never ? UnwrappedArray : UnwrapTupple + : T extends object ? UnwrappedObject : T -export type UnwrapRef = T extends object - ? UnwrapObject - : T extends Function | CollectionTypes - ? T - : T extends Array ? Array> & UnwrapArray : T +export type UnwrapTupple = { [P in keyof T]: UnwrapRef } & { + length: number + [Symbol.iterator]: any + [Symbol.unscopables]: any +} + +interface UnwrappedArray extends Array> {} + +type UnwrappedObject = { [P in keyof T]: UnwrapRef } From 9edc4fa1fe54d36edd7208d54eef2ed23da1ad6c Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 4 Jan 2020 14:22:09 +0000 Subject: [PATCH 0003/5381] types: fix failed typings? --- packages/runtime-core/__tests__/apiTemplateRef.spec.ts | 3 +-- packages/runtime-core/src/apiWatch.ts | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts index d164d4571b2..f9b6b1b5856 100644 --- a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts @@ -4,7 +4,6 @@ import { h, render, nextTick, - Ref, createComponent } from '@vue/runtime-test' @@ -142,7 +141,7 @@ describe('api: template refs', () => { foo: ref(null), bar: ref(null) } - const refKey: Ref = ref('foo') + const refKey = ref('foo') const Comp = { setup() { diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index efd3dfd40a4..a3fd6acfaeb 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -72,7 +72,10 @@ export function watch( // Readonly constraint helps the callback to correctly infer value types based // on position in the source array. Otherwise the values will get a union type // of all possible value types. -export function watch[]>>( +export function watch< + T extends Readonly>, + TArgs extends Array = any[] +>( sources: T, cb: WatchHandler>, options?: WatchOptions From da8c31dc7fc14ce0e0af309318b0463130847721 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2020 07:26:02 +0000 Subject: [PATCH 0004/5381] build(deps-dev): bump rollup from 1.29.0 to 1.29.1 Bumps [rollup](https://github.com/rollup/rollup) from 1.29.0 to 1.29.1. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v1.29.0...v1.29.1) Signed-off-by: dependabot-preview[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3dd28e87cf9..6b9a8343198 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5227,9 +5227,9 @@ rollup-pluginutils@^2.5.0, rollup-pluginutils@^2.6.0, rollup-pluginutils@^2.8.2: estree-walker "^0.6.1" rollup@^1.19.4: - version "1.29.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.29.0.tgz#6a1a79eea43ca9d3d79a90c15a1ceecedc72097b" - integrity sha512-V63Iz0dSdI5qPPN5HmCN6OBRzBFhMqNWcvwgq863JtSCTU6Vdvqq6S2fYle/dSCyoPrBkIP3EIr1RVs3HTRqqg== + version "1.29.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.29.1.tgz#8715d0a4ca439be3079f8095989ec8aa60f637bc" + integrity sha512-dGQ+b9d1FOX/gluiggTAVnTvzQZUEkCi/TwZcax7ujugVRHs0nkYJlV9U4hsifGEMojnO+jvEML2CJQ6qXgbHA== dependencies: "@types/estree" "*" "@types/node" "*" From 4f06eebc1c2a29d0e4165c6e87f849732ec2cd0f Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 21 Jan 2020 11:32:17 -0500 Subject: [PATCH 0005/5381] fix(dom): fix and mount and updates --- .../src/transforms/transformElement.ts | 18 +++--- packages/runtime-core/src/renderer.ts | 17 +++-- packages/vue/__tests__/svg.spec.ts | 63 +++++++++++++++++++ 3 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 packages/vue/__tests__/svg.spec.ts diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 09a865112dd..0d907498b67 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -70,9 +70,7 @@ export const transformElement: NodeTransform = (node, context) => { let runtimeDirectives: DirectiveNode[] | undefined let dynamicPropNames: string[] | undefined let dynamicComponent: string | CallExpression | undefined - // technically this is web specific but we are keeping it in core to avoid - // extra complexity - let isSVG = false + let shouldUseBlock = false // handle dynamic component const isProp = findProp(node, 'is') @@ -110,8 +108,12 @@ export const transformElement: NodeTransform = (node, context) => { nodeType = toValidAssetId(tag, `component`) } else { // plain element - nodeType = `"${node.tag}"` - isSVG = node.tag === 'svg' + nodeType = `"${tag}"` + // and must be forced into blocks so that block + // updates inside get proper isSVG flag at runtime. (#639, #643) + // This is technically web-specific, but splitting the logic out of core + // leads to too much unnecessary complexity. + shouldUseBlock = tag === 'svg' || tag === 'foreignObject' } const args: CallExpression['arguments'] = [nodeType] @@ -197,10 +199,8 @@ export const transformElement: NodeTransform = (node, context) => { } const { loc } = node - const vnode = isSVG - ? // must be forced into blocks so that block updates inside retain - // isSVG flag at runtime. (#639, #643) - createSequenceExpression([ + const vnode = shouldUseBlock + ? createSequenceExpression([ createCallExpression(context.helper(OPEN_BLOCK)), createCallExpression(context.helper(CREATE_BLOCK), args, loc) ]) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index e136caa4d5e..d26f73dae9a 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -370,7 +370,7 @@ export function createRenderer< optimized: boolean ) { const el = (vnode.el = hostCreateElement(vnode.type as string, isSVG)) - const { props, shapeFlag, transition, scopeId } = vnode + const { type, props, shapeFlag, transition, scopeId } = vnode // props if (props != null) { @@ -406,7 +406,7 @@ export function createRenderer< null, parentComponent, parentSuspense, - isSVG, + isSVG && type !== 'foreignObject', optimized || vnode.dynamicChildren !== null ) } @@ -562,6 +562,7 @@ export function createRenderer< ) } + const areChildrenSVG = isSVG && n2.type !== 'foreignObject' if (dynamicChildren != null) { patchBlockChildren( n1.dynamicChildren!, @@ -569,11 +570,19 @@ export function createRenderer< el, parentComponent, parentSuspense, - isSVG + areChildrenSVG ) } else if (!optimized) { // full diff - patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG) + patchChildren( + n1, + n2, + el, + null, + parentComponent, + parentSuspense, + areChildrenSVG + ) } if (newProps.onVnodeUpdated != null) { diff --git a/packages/vue/__tests__/svg.spec.ts b/packages/vue/__tests__/svg.spec.ts new file mode 100644 index 00000000000..8644d399c91 --- /dev/null +++ b/packages/vue/__tests__/svg.spec.ts @@ -0,0 +1,63 @@ +// SVG logic is technically dom-specific, but the logic is placed in core +// because splitting it out of core would lead to unnecessary complexity in both +// the renderer and compiler implementations. +// Related files: +// - runtime-core/src/renderer.ts +// - compiler-core/src/transoforms/transformElement.ts + +import { render, h, ref, nextTick } from '../src' + +describe('SVG support', () => { + test('should mount elements with correct namespaces', () => { + const root = document.createElement('div') + document.body.appendChild(root) + const App = { + template: ` +
+ + +
+ + +
+ ` + } + render(h(App), root) + const e0 = document.getElementById('e0')! + expect(e0.namespaceURI).toMatch('xhtml') + expect(e0.querySelector('#e1')!.namespaceURI).toMatch('svg') + expect(e0.querySelector('#e2')!.namespaceURI).toMatch('svg') + expect(e0.querySelector('#e3')!.namespaceURI).toMatch('xhtml') + }) + + test('should patch elements with correct namespaces', async () => { + const root = document.createElement('div') + document.body.appendChild(root) + const cls = ref('foo') + const App = { + setup: () => ({ cls }), + template: ` +
+ + +
+ + +
+ ` + } + render(h(App), root) + const f1 = document.querySelector('#f1')! + const f2 = document.querySelector('#f2')! + expect(f1.getAttribute('class')).toBe('foo') + expect(f2.className).toBe('foo') + + // set a transition class on the
- which is only respected on non-svg + // patches + ;(f2 as any)._vtc = ['baz'] + cls.value = 'bar' + await nextTick() + expect(f1.getAttribute('class')).toBe('bar') + expect(f2.className).toBe('bar baz') + }) +}) From 95a8beb787e6936e6555a9fcf66a1a1545802b59 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2020 07:58:02 +0000 Subject: [PATCH 0006/5381] build(deps-dev): bump @microsoft/api-extractor from 7.7.5 to 7.7.6 Bumps [@microsoft/api-extractor](https://github.com/microsoft/rushstack) from 7.7.5 to 7.7.6. - [Release notes](https://github.com/microsoft/rushstack/releases) - [Commits](https://github.com/microsoft/rushstack/compare/@microsoft/api-extractor_v7.7.5...@microsoft/api-extractor_v7.7.6) Signed-off-by: dependabot-preview[bot] --- yarn.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6b9a8343198..ce15594b56f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -287,22 +287,22 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@microsoft/api-extractor-model@7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.7.4.tgz#45a1bd38499db5ae56dcecf1f68d4cf3c50a63ac" - integrity sha512-/UGBXzEwOAYAS9Xg9I9RF3f+Fp1dowddMlisUlBASGJT38/ZhlMb8Zp0Y0ThJcY+VA6Wya0cMK3c/Lo2u+f2EQ== +"@microsoft/api-extractor-model@7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.7.5.tgz#ddf6eb87d723361204d77d3570a2e7cb7743ec62" + integrity sha512-zMk+iqG7AVPYwAn2S/KgtRLnFLd66+XJx1ld86RT36z3zHcrr1Xg/PbHGfaXr4m+4nT/MASGRJV6/xf7wnaa0A== dependencies: - "@microsoft/node-core-library" "3.19.0" + "@microsoft/node-core-library" "3.19.1" "@microsoft/tsdoc" "0.12.14" "@microsoft/api-extractor@^7.3.9": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.5.tgz#eeae706cb5a9b0e0ae1c3f2547520650de26b826" - integrity sha512-/tZkNOFRS27c/ZCsiTbVdTvD10b7UMCX2hlzqQGN5wMWyoblpQy0cZBuRrQBuRllkgXoXeiMpeTf8NcSSl+IjQ== + version "7.7.6" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.6.tgz#2ace76c268d7124d1a2cfb83a8fd5edc143d9f6d" + integrity sha512-VeqOS7HnlPG6TRK70O3oC10y9mKZK0gWjEl1W+1FoaRSOTXerqByG0eLKwszd1WqyvdFQmMokDLgbG8YcN4nQg== dependencies: - "@microsoft/api-extractor-model" "7.7.4" - "@microsoft/node-core-library" "3.19.0" - "@microsoft/ts-command-line" "4.3.9" + "@microsoft/api-extractor-model" "7.7.5" + "@microsoft/node-core-library" "3.19.1" + "@microsoft/ts-command-line" "4.3.10" "@microsoft/tsdoc" "0.12.14" colors "~1.2.1" lodash "~4.17.15" @@ -310,10 +310,10 @@ source-map "~0.6.1" typescript "~3.7.2" -"@microsoft/node-core-library@3.19.0": - version "3.19.0" - resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.19.0.tgz#b868a38cdb1113f83ee96ad0e9fc24cb3d4c7883" - integrity sha512-ZcqNHT4ztzT3tw9jCn76TUNCXwJpgOd1UK2RB8Gll0U+chTam3bcsXHkNnR6edDfySKx1rIHRgHAHzkqdJwmlg== +"@microsoft/node-core-library@3.19.1": + version "3.19.1" + resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.19.1.tgz#cc881d9a3ccb21857ecc71bfc2df92e52fe82907" + integrity sha512-CTlTX3goPe2HUWg+n5w/cYUFI+qTx2gv4XVycjpPRi5KqwrowZ+wfSWkaM7AQ8RaMZ7d4AXVXeRm+2k6eW261g== dependencies: "@types/node" "10.17.13" colors "~1.2.1" @@ -323,10 +323,10 @@ timsort "~0.3.0" z-schema "~3.18.3" -"@microsoft/ts-command-line@4.3.9": - version "4.3.9" - resolved "https://registry.yarnpkg.com/@microsoft/ts-command-line/-/ts-command-line-4.3.9.tgz#7d6eaccd98c77c3abf1ab93f6cc1abde397836bc" - integrity sha512-G7xXA8uz2bMmaAhbqU8oWl0Y68X7qEWbuAuTkhVHDCgr4wjrUTbyvJ3DXcnANGhVVx2BWGHWUsj/GzMgU4apQQ== +"@microsoft/ts-command-line@4.3.10": + version "4.3.10" + resolved "https://registry.yarnpkg.com/@microsoft/ts-command-line/-/ts-command-line-4.3.10.tgz#fcb4f5ea43c93d17db6cc810bbee39ea32b2a86d" + integrity sha512-AgxArGqPt0H5WTo3fxNFP3Blm3obkCCopVG9kwIo+/mMdXaj6qMDn6+8Bv8+5Nke3CvvXpKAZtu3IaGY5cV1Hg== dependencies: "@types/argparse" "1.0.33" argparse "~1.0.9" From 2569890e31c84146b3fa1e7503e3f5e9ca466c3a Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 22 Jan 2020 09:29:35 -0500 Subject: [PATCH 0007/5381] refactor: move mockWarn utility to @vue/shared close #652 --- packages/compiler-sfc/__tests__/compileStyle.spec.ts | 2 +- packages/compiler-sfc/__tests__/parse.spec.ts | 2 +- packages/reactivity/__tests__/computed.spec.ts | 2 +- packages/reactivity/__tests__/reactive.spec.ts | 2 +- packages/reactivity/__tests__/readonly.spec.ts | 2 +- packages/runtime-core/__tests__/apiApp.spec.ts | 2 +- packages/runtime-core/__tests__/apiInject.spec.ts | 3 ++- packages/runtime-core/__tests__/apiOptions.spec.ts | 4 ++-- packages/runtime-core/__tests__/apiWatch.spec.ts | 3 ++- packages/runtime-core/__tests__/componentProxy.spec.ts | 8 ++------ packages/runtime-core/__tests__/errorHandling.spec.ts | 2 +- .../runtime-core/__tests__/helpers/resolveAssets.spec.ts | 2 +- .../runtime-core/__tests__/helpers/toHandlers.spec.ts | 2 +- .../__tests__/rendererAttrsFallthrough.spec.ts | 2 +- packages/runtime-core/__tests__/rendererChildren.spec.ts | 4 ++-- packages/runtime-test/__tests__/testRuntime.spec.ts | 4 ++-- packages/runtime-test/src/index.ts | 1 - packages/shared/src/index.ts | 1 + .../{runtime-test/src/utils => shared/src}/mockWarn.ts | 0 packages/vue/__tests__/index.spec.ts | 2 +- 20 files changed, 24 insertions(+), 26 deletions(-) rename packages/{runtime-test/src/utils => shared/src}/mockWarn.ts (100%) diff --git a/packages/compiler-sfc/__tests__/compileStyle.spec.ts b/packages/compiler-sfc/__tests__/compileStyle.spec.ts index 5198e7a7e34..b4af3c0972d 100644 --- a/packages/compiler-sfc/__tests__/compileStyle.spec.ts +++ b/packages/compiler-sfc/__tests__/compileStyle.spec.ts @@ -1,5 +1,5 @@ import { compileStyle } from '../src/compileStyle' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' function compile(source: string): string { const res = compileStyle({ diff --git a/packages/compiler-sfc/__tests__/parse.spec.ts b/packages/compiler-sfc/__tests__/parse.spec.ts index affe1f5a368..a55e2e6b288 100644 --- a/packages/compiler-sfc/__tests__/parse.spec.ts +++ b/packages/compiler-sfc/__tests__/parse.spec.ts @@ -1,5 +1,5 @@ import { parse } from '../src' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' import { baseParse, baseCompile } from '@vue/compiler-core' describe('compiler:sfc', () => { diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index 0ab644af7f1..5ab4641e988 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -6,7 +6,7 @@ import { ref, WritableComputedRef } from '../src' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('reactivity/computed', () => { mockWarn() diff --git a/packages/reactivity/__tests__/reactive.spec.ts b/packages/reactivity/__tests__/reactive.spec.ts index 2d134922d3a..62913e67063 100644 --- a/packages/reactivity/__tests__/reactive.spec.ts +++ b/packages/reactivity/__tests__/reactive.spec.ts @@ -1,6 +1,6 @@ import { ref, isRef } from '../src/ref' import { reactive, isReactive, toRaw, markNonReactive } from '../src/reactive' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' import { computed } from '../src/computed' describe('reactivity/reactive', () => { diff --git a/packages/reactivity/__tests__/readonly.spec.ts b/packages/reactivity/__tests__/readonly.spec.ts index bcd1c43ec7f..e009022d08c 100644 --- a/packages/reactivity/__tests__/readonly.spec.ts +++ b/packages/reactivity/__tests__/readonly.spec.ts @@ -12,7 +12,7 @@ import { ref, shallowReadonly } from '../src' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' /** * @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html diff --git a/packages/runtime-core/__tests__/apiApp.spec.ts b/packages/runtime-core/__tests__/apiApp.spec.ts index 7ade99e9e94..6fb8239b8f9 100644 --- a/packages/runtime-core/__tests__/apiApp.spec.ts +++ b/packages/runtime-core/__tests__/apiApp.spec.ts @@ -3,7 +3,6 @@ import { h, nodeOps, serializeInner, - mockWarn, provide, inject, resolveComponent, @@ -13,6 +12,7 @@ import { ref, getCurrentInstance } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('api: createApp', () => { mockWarn() diff --git a/packages/runtime-core/__tests__/apiInject.spec.ts b/packages/runtime-core/__tests__/apiInject.spec.ts index 26359fe4c1a..d979861a82b 100644 --- a/packages/runtime-core/__tests__/apiInject.spec.ts +++ b/packages/runtime-core/__tests__/apiInject.spec.ts @@ -9,7 +9,8 @@ import { readonly, reactive } from '../src/index' -import { render, nodeOps, serialize, mockWarn } from '@vue/runtime-test' +import { render, nodeOps, serialize } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' // reference: https://vue-composition-api-rfc.netlify.com/api.html#provide-inject diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 8a0199e3ffb..7d915eb0ff2 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -8,9 +8,9 @@ import { nextTick, renderToString, ref, - defineComponent, - mockWarn + defineComponent } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('api: options', () => { test('data', async () => { diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 15a0765f97e..ad8f4787145 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1,11 +1,12 @@ import { watch, reactive, computed, nextTick, ref, h } from '../src/index' -import { render, nodeOps, serializeInner, mockWarn } from '@vue/runtime-test' +import { render, nodeOps, serializeInner } from '@vue/runtime-test' import { ITERATE_KEY, DebuggerEvent, TrackOpTypes, TriggerOpTypes } from '@vue/reactivity' +import { mockWarn } from '@vue/shared' // reference: https://vue-composition-api-rfc.netlify.com/api.html#watch diff --git a/packages/runtime-core/__tests__/componentProxy.spec.ts b/packages/runtime-core/__tests__/componentProxy.spec.ts index 2014cd2f8e5..ddfd8cab0bf 100644 --- a/packages/runtime-core/__tests__/componentProxy.spec.ts +++ b/packages/runtime-core/__tests__/componentProxy.spec.ts @@ -1,9 +1,5 @@ -import { - createApp, - getCurrentInstance, - nodeOps, - mockWarn -} from '@vue/runtime-test' +import { createApp, getCurrentInstance, nodeOps } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' import { ComponentInternalInstance } from '../src/component' describe('component: proxy', () => { diff --git a/packages/runtime-core/__tests__/errorHandling.spec.ts b/packages/runtime-core/__tests__/errorHandling.spec.ts index be809d5ff98..d9f753f9330 100644 --- a/packages/runtime-core/__tests__/errorHandling.spec.ts +++ b/packages/runtime-core/__tests__/errorHandling.spec.ts @@ -7,10 +7,10 @@ import { watch, ref, nextTick, - mockWarn, defineComponent } from '@vue/runtime-test' import { setErrorRecovery } from '../src/errorHandling' +import { mockWarn } from '@vue/shared' describe('error handling', () => { mockWarn() diff --git a/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts b/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts index cfa4a3e23d1..392311c1cb5 100644 --- a/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts +++ b/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts @@ -1,5 +1,4 @@ import { - mockWarn, createApp, nodeOps, resolveComponent, @@ -9,6 +8,7 @@ import { resolveDynamicComponent, getCurrentInstance } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('resolveAssets', () => { test('should work', () => { diff --git a/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts b/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts index e07cf141699..000f9004952 100644 --- a/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts +++ b/packages/runtime-core/__tests__/helpers/toHandlers.spec.ts @@ -1,5 +1,5 @@ import { toHandlers } from '../../src/helpers/toHandlers' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('toHandlers', () => { mockWarn() diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index fed38fc3f3a..fe34eee6010 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -8,7 +8,7 @@ import { onUpdated, defineComponent } from '@vue/runtime-dom' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('attribute fallthrough', () => { mockWarn() diff --git a/packages/runtime-core/__tests__/rendererChildren.spec.ts b/packages/runtime-core/__tests__/rendererChildren.spec.ts index 553d73b5e75..93ef3b99b73 100644 --- a/packages/runtime-core/__tests__/rendererChildren.spec.ts +++ b/packages/runtime-core/__tests__/rendererChildren.spec.ts @@ -6,9 +6,9 @@ import { NodeTypes, TestElement, serialize, - serializeInner, - mockWarn + serializeInner } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' mockWarn() diff --git a/packages/runtime-test/__tests__/testRuntime.spec.ts b/packages/runtime-test/__tests__/testRuntime.spec.ts index ec7cbb21eea..be18d4a00a2 100644 --- a/packages/runtime-test/__tests__/testRuntime.spec.ts +++ b/packages/runtime-test/__tests__/testRuntime.spec.ts @@ -12,9 +12,9 @@ import { NodeOpTypes, nextTick, serialize, - triggerEvent, - mockWarn + triggerEvent } from '../src' +import { mockWarn } from '@vue/shared' describe('test renderer', () => { mockWarn() diff --git a/packages/runtime-test/src/index.ts b/packages/runtime-test/src/index.ts index 96c3ad1eb3e..c057da7e018 100644 --- a/packages/runtime-test/src/index.ts +++ b/packages/runtime-test/src/index.ts @@ -26,5 +26,4 @@ export function renderToString(vnode: VNode) { export * from './triggerEvent' export * from './serialize' export * from './nodeOps' -export * from './utils/mockWarn' export * from '@vue/runtime-core' diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index de6596198e7..4d6f700166f 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -5,6 +5,7 @@ export * from './patchFlags' export * from './globalsWhitelist' export * from './codeframe' export * from './domTagConfig' +export * from './mockWarn' export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__ ? Object.freeze({}) diff --git a/packages/runtime-test/src/utils/mockWarn.ts b/packages/shared/src/mockWarn.ts similarity index 100% rename from packages/runtime-test/src/utils/mockWarn.ts rename to packages/shared/src/mockWarn.ts diff --git a/packages/vue/__tests__/index.spec.ts b/packages/vue/__tests__/index.spec.ts index 7b732528bd5..4a7a06bb64d 100644 --- a/packages/vue/__tests__/index.spec.ts +++ b/packages/vue/__tests__/index.spec.ts @@ -1,5 +1,5 @@ import { createApp } from '../src' -import { mockWarn } from '@vue/runtime-test' +import { mockWarn } from '@vue/shared' describe('compiler + runtime integration', () => { mockWarn() From ec63623fe8d395e1cd759f27b90b1ccc1b616931 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Wed, 22 Jan 2020 23:45:27 +0800 Subject: [PATCH 0008/5381] fix: Suspense should include into dynamic children (#653) fix #649 --- packages/runtime-core/__tests__/vnode.spec.ts | 35 ++++++++++++++++++- packages/runtime-core/src/vnode.ts | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 656d27644b9..ea9fc02bda4 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -232,7 +232,7 @@ describe('vnode', () => { }) describe('dynamic children', () => { - test('single call openBlock', () => { + test('with patchFlags', () => { const hoist = createVNode('div') let vnode1 const vnode = (openBlock(), @@ -259,5 +259,38 @@ describe('vnode', () => { expect(vnode.dynamicChildren).toStrictEqual([vnode1, vnode2]) expect(vnode2.dynamicChildren).toStrictEqual([vnode3]) }) + + test('with stateful component', () => { + const hoist = createVNode('div') + let vnode1 + const vnode = (openBlock(), + createBlock('div', null, [ + hoist, + (vnode1 = createVNode({}, null, 'text')) + ])) + expect(vnode.dynamicChildren).toStrictEqual([vnode1]) + }) + + test('with functional component', () => { + const hoist = createVNode('div') + let vnode1 + const vnode = (openBlock(), + createBlock('div', null, [ + hoist, + (vnode1 = createVNode(() => {}, null, 'text')) + ])) + expect(vnode.dynamicChildren).toStrictEqual([vnode1]) + }) + + test('with suspense', () => { + const hoist = createVNode('div') + let vnode1 + const vnode = (openBlock(), + createBlock('div', null, [ + hoist, + (vnode1 = createVNode(() => {}, null, 'text')) + ])) + expect(vnode.dynamicChildren).toStrictEqual([vnode1]) + }) }) }) diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 1f08d5cab5b..33c177d6f5c 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -274,6 +274,7 @@ export function createVNode( shouldTrack > 0 && currentBlock !== null && (patchFlag > 0 || + shapeFlag & ShapeFlags.SUSPENSE || shapeFlag & ShapeFlags.STATEFUL_COMPONENT || shapeFlag & ShapeFlags.FUNCTIONAL_COMPONENT) ) { From 0b992307a6113d8b87cb7406b61138dc05ef1f4a Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 22 Jan 2020 10:51:17 -0500 Subject: [PATCH 0009/5381] build: adjust release tag --- scripts/release.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/release.js b/scripts/release.js index 0ea5c9247c2..9bdd8d9b078 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -184,10 +184,10 @@ async function publishPackage(pkgName, version, runIfNotDry) { // for now (alpha/beta phase), every package except "vue" can be published as // `latest`, whereas "vue" will be published under the "next" tag. - const releaseTag = pkgName === 'vue' ? 'next' : 'latest' + const releaseTag = pkgName === 'vue' ? 'next' : null // TODO use inferred release channel after official 3.0 release - // const releaseTag = semver.prerelease(version)[0] || 'latest' + // const releaseTag = semver.prerelease(version)[0] || null step(`Publishing ${pkgName}...`) try { @@ -197,8 +197,7 @@ async function publishPackage(pkgName, version, runIfNotDry) { 'publish', '--new-version', version, - '--tag', - releaseTag, + ...(releaseTag ? ['--tag', releaseTag] : []), '--access', 'public' ], From b41677bf42a91a1c039e6ce352d303339d533459 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 22 Jan 2020 11:10:30 -0500 Subject: [PATCH 0010/5381] release: v3.0.0-alpha.3 --- CHANGELOG.md | 23 +++++++++++++++++++++++ package.json | 2 +- packages/compiler-core/package.json | 2 +- packages/compiler-dom/package.json | 4 ++-- packages/compiler-sfc/package.json | 8 ++++---- packages/reactivity/package.json | 2 +- packages/runtime-core/package.json | 4 ++-- packages/runtime-dom/package.json | 4 ++-- packages/runtime-test/package.json | 4 ++-- packages/server-renderer/package.json | 2 +- packages/shared/package.json | 2 +- packages/size-check/package.json | 2 +- packages/template-explorer/package.json | 2 +- packages/vue/package.json | 6 +++--- 14 files changed, 45 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65de86668b6..d2301ccf161 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +# [3.0.0-alpha.3](https://github.com/vuejs/vue-next/compare/v3.0.0-alpha.2...v3.0.0-alpha.3) (2020-01-22) + + +### Bug Fixes + +* Suspense should include into dynamic children ([#653](https://github.com/vuejs/vue-next/issues/653)) ([ec63623](https://github.com/vuejs/vue-next/commit/ec63623fe8d395e1cd759f27b90b1ccc1b616931)), closes [#649](https://github.com/vuejs/vue-next/issues/649) +* **compiler-core:** avoid override user keys when injecting branch key ([#630](https://github.com/vuejs/vue-next/issues/630)) ([aca2c2a](https://github.com/vuejs/vue-next/commit/aca2c2a81e2793befce516378a02afd1e4da3d3d)) +* **compiler-core:** force into blocks for correct runtime isSVG ([f2ac28b](https://github.com/vuejs/vue-next/commit/f2ac28b31e9f1e8ebcd68ca9a1e8ea29653b0916)) +* **compiler-sfc:** only transform relative asset URLs ([#628](https://github.com/vuejs/vue-next/issues/628)) ([c71ca35](https://github.com/vuejs/vue-next/commit/c71ca354b9368135b55676c5817cebffaf3fd9c5)) +* **dom:** fix and mount and updates ([4f06eeb](https://github.com/vuejs/vue-next/commit/4f06eebc1c2a29d0e4165c6e87f849732ec2cd0f)) +* **runtime-core:** condition for parent node check should be any different nodes ([c35fea3](https://github.com/vuejs/vue-next/commit/c35fea3d608acbb571ace6693284061e1cadf7ba)), closes [#622](https://github.com/vuejs/vue-next/issues/622) +* **runtime-core:** isSVG check should also apply for patch branch ([035b656](https://github.com/vuejs/vue-next/commit/035b6560f7eb64ce940ed0d06e19086ad9a3890f)), closes [#639](https://github.com/vuejs/vue-next/issues/639) +* **runtime-core:** should not warn unused attrs when accessed via setup context ([751d838](https://github.com/vuejs/vue-next/commit/751d838fb963e580a40df2d84840ba2198480185)), closes [#625](https://github.com/vuejs/vue-next/issues/625) +* **transition:** handle multiple transition classes ([#638](https://github.com/vuejs/vue-next/issues/638)) ([#645](https://github.com/vuejs/vue-next/issues/645)) ([98d50d8](https://github.com/vuejs/vue-next/commit/98d50d874dcb32a246216b936e442e5b95ab4825)) + + +### Features + +* **runtime-core:** emit now returns array of return values from all triggered handlers ([e81c8a3](https://github.com/vuejs/vue-next/commit/e81c8a32c7b66211cbaecffa93efd4629ec45ad9)), closes [#635](https://github.com/vuejs/vue-next/issues/635) +* **runtime-core:** support app.unmount(container) ([#601](https://github.com/vuejs/vue-next/issues/601)) ([04ac6c4](https://github.com/vuejs/vue-next/commit/04ac6c467a4122877c204d7494c86f89498d2dc6)), closes [#593](https://github.com/vuejs/vue-next/issues/593) + + + # [3.0.0-alpha.2](https://github.com/vuejs/vue-next/compare/v3.0.0-alpha.1...v3.0.0-alpha.2) (2020-01-13) diff --git a/package.json b/package.json index 6600cfe963d..301ef7c57a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "3.0.0-alpha.2", + "version": "3.0.0-alpha.3", "workspaces": [ "packages/*" ], diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json index fb65e2b13bd..92c9a21e316 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/compiler-core", "main": "index.js", "module": "dist/compiler-core.esm-bundler.js", diff --git a/packages/compiler-dom/package.json b/packages/compiler-dom/package.json index 9baa2b2d26b..338a837a066 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/compiler-dom", "main": "index.js", "module": "dist/compiler-dom.esm-bundler.js", @@ -34,6 +34,6 @@ }, "homepage": "https://github.com/vuejs/vue/tree/dev/packages/compiler-dom#readme", "dependencies": { - "@vue/compiler-core": "3.0.0-alpha.2" + "@vue/compiler-core": "3.0.0-alpha.3" } } diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json index ce431054f38..34029768a90 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/compiler-sfc", "main": "dist/compiler-sfc.cjs.js", "types": "dist/compiler-sfc.d.ts", @@ -27,11 +27,11 @@ }, "homepage": "https://github.com/vuejs/vue/tree/dev/packages/compiler-sfc#readme", "peerDependencies": { - "vue": "3.0.0-alpha.2" + "vue": "3.0.0-alpha.3" }, "dependencies": { - "@vue/compiler-core": "3.0.0-alpha.2", - "@vue/compiler-dom": "3.0.0-alpha.2", + "@vue/compiler-core": "3.0.0-alpha.3", + "@vue/compiler-dom": "3.0.0-alpha.3", "consolidate": "^0.15.1", "hash-sum": "^2.0.0", "lru-cache": "^5.1.1", diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index 2ecb76f5f46..9f5ac009929 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@vue/reactivity", - "version": "3.0.0-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/reactivity", "main": "index.js", "module": "dist/reactivity.esm-bundler.js", diff --git a/packages/runtime-core/package.json b/packages/runtime-core/package.json index b45b96655e0..c69cf8311ff 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/runtime-core", "main": "index.js", "module": "dist/runtime-core.esm-bundler.js", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/vuejs/vue/tree/dev/packages/runtime-core#readme", "dependencies": { - "@vue/reactivity": "3.0.0-alpha.2" + "@vue/reactivity": "3.0.0-alpha.3" } } diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json index 25e0a5ed390..5099786cf40 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/runtime-dom", "main": "index.js", "module": "dist/runtime-dom.esm-bundler.js", @@ -37,7 +37,7 @@ }, "homepage": "https://github.com/vuejs/vue/tree/dev/packages/runtime-dom#readme", "dependencies": { - "@vue/runtime-core": "3.0.0-alpha.2", + "@vue/runtime-core": "3.0.0-alpha.3", "csstype": "^2.6.8" } } diff --git a/packages/runtime-test/package.json b/packages/runtime-test/package.json index d58315098d8..bcd4df6aa74 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/runtime-test", "private": true, "main": "index.js", @@ -30,6 +30,6 @@ }, "homepage": "https://github.com/vuejs/vue/tree/dev/packages/runtime-test#readme", "dependencies": { - "@vue/runtime-core": "3.0.0-alpha.2" + "@vue/runtime-core": "3.0.0-alpha.3" } } diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index 64c4ec71f02..d0e695dfb2b 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-alpha.2", + "version": "3.0.0-alpha.3", "description": "@vue/server-renderer", "main": "index.js", "types": "dist/server-renderer.d.ts", diff --git a/packages/shared/package.json b/packages/shared/package.json index b668c83d477..c84c64ab403 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,5 +1,5 @@ { "name": "@vue/shared", - "version": "3.0.0-alpha.2", + "version": "3.0.0-alpha.3", "private": true } diff --git a/packages/size-check/package.json b/packages/size-check/package.json index edf3177fe1d..adb75b1615d 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-alpha.2", + "version": "3.0.0-alpha.3", "private": true, "buildOptions": { "name": "Vue", diff --git a/packages/template-explorer/package.json b/packages/template-explorer/package.json index fb726f37c2a..5ce900e0dae 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-alpha.2", + "version": "3.0.0-alpha.3", "private": true, "buildOptions": { "formats": [ diff --git a/packages/vue/package.json b/packages/vue/package.json index 4a84a35ded6..126ff9ead60 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "3.0.0-alpha.2", + "version": "3.0.0-alpha.3", "description": "vue", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js", @@ -34,8 +34,8 @@ }, "homepage": "https://github.com/vuejs/vue/tree/dev/packages/vue#readme", "dependencies": { - "@vue/compiler-dom": "3.0.0-alpha.2", - "@vue/runtime-dom": "3.0.0-alpha.2" + "@vue/compiler-dom": "3.0.0-alpha.3", + "@vue/runtime-dom": "3.0.0-alpha.3" }, "devDependencies": { "lodash": "^4.17.15", From 52e4ac072765b018837c5ba9781a27a467bf6956 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 22 Jan 2020 11:12:55 -0500 Subject: [PATCH 0011/5381] chore: fix changelog formatting [ci skip] --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2301ccf161..955b21edce6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ * Suspense should include into dynamic children ([#653](https://github.com/vuejs/vue-next/issues/653)) ([ec63623](https://github.com/vuejs/vue-next/commit/ec63623fe8d395e1cd759f27b90b1ccc1b616931)), closes [#649](https://github.com/vuejs/vue-next/issues/649) * **compiler-core:** avoid override user keys when injecting branch key ([#630](https://github.com/vuejs/vue-next/issues/630)) ([aca2c2a](https://github.com/vuejs/vue-next/commit/aca2c2a81e2793befce516378a02afd1e4da3d3d)) -* **compiler-core:** force into blocks for correct runtime isSVG ([f2ac28b](https://github.com/vuejs/vue-next/commit/f2ac28b31e9f1e8ebcd68ca9a1e8ea29653b0916)) +* **compiler-core:** force `` into blocks for correct runtime isSVG ([f2ac28b](https://github.com/vuejs/vue-next/commit/f2ac28b31e9f1e8ebcd68ca9a1e8ea29653b0916)) * **compiler-sfc:** only transform relative asset URLs ([#628](https://github.com/vuejs/vue-next/issues/628)) ([c71ca35](https://github.com/vuejs/vue-next/commit/c71ca354b9368135b55676c5817cebffaf3fd9c5)) -* **dom:** fix and mount and updates ([4f06eeb](https://github.com/vuejs/vue-next/commit/4f06eebc1c2a29d0e4165c6e87f849732ec2cd0f)) +* **dom:** fix `` and `` mount and updates ([4f06eeb](https://github.com/vuejs/vue-next/commit/4f06eebc1c2a29d0e4165c6e87f849732ec2cd0f)) * **runtime-core:** condition for parent node check should be any different nodes ([c35fea3](https://github.com/vuejs/vue-next/commit/c35fea3d608acbb571ace6693284061e1cadf7ba)), closes [#622](https://github.com/vuejs/vue-next/issues/622) * **runtime-core:** isSVG check should also apply for patch branch ([035b656](https://github.com/vuejs/vue-next/commit/035b6560f7eb64ce940ed0d06e19086ad9a3890f)), closes [#639](https://github.com/vuejs/vue-next/issues/639) * **runtime-core:** should not warn unused attrs when accessed via setup context ([751d838](https://github.com/vuejs/vue-next/commit/751d838fb963e580a40df2d84840ba2198480185)), closes [#625](https://github.com/vuejs/vue-next/issues/625) From 3919c7840d80d970cc443fc88c82323585fc1794 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2020 08:07:53 +0000 Subject: [PATCH 0012/5381] build(deps-dev): bump @microsoft/api-extractor from 7.7.6 to 7.7.7 Bumps [@microsoft/api-extractor](https://github.com/microsoft/rushstack) from 7.7.6 to 7.7.7. - [Release notes](https://github.com/microsoft/rushstack/releases) - [Commits](https://github.com/microsoft/rushstack/compare/@microsoft/api-extractor_v7.7.6...@microsoft/api-extractor_v7.7.7) Signed-off-by: dependabot-preview[bot] --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index ce15594b56f..5ca13ba172d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -287,21 +287,21 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@microsoft/api-extractor-model@7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.7.5.tgz#ddf6eb87d723361204d77d3570a2e7cb7743ec62" - integrity sha512-zMk+iqG7AVPYwAn2S/KgtRLnFLd66+XJx1ld86RT36z3zHcrr1Xg/PbHGfaXr4m+4nT/MASGRJV6/xf7wnaa0A== +"@microsoft/api-extractor-model@7.7.6": + version "7.7.6" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.7.6.tgz#3575bab3170b2774ccf17c5f7723d81d50ac60e2" + integrity sha512-tcVC1OD7aEJkAOnGMrIk5heRTBhqWv7pOu9fCksEUo+kyvK0Q26xOFFSS1Rz6MwFvkzBsCxC+C6AyhDTxUUJeQ== dependencies: - "@microsoft/node-core-library" "3.19.1" + "@microsoft/node-core-library" "3.19.2" "@microsoft/tsdoc" "0.12.14" "@microsoft/api-extractor@^7.3.9": - version "7.7.6" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.6.tgz#2ace76c268d7124d1a2cfb83a8fd5edc143d9f6d" - integrity sha512-VeqOS7HnlPG6TRK70O3oC10y9mKZK0gWjEl1W+1FoaRSOTXerqByG0eLKwszd1WqyvdFQmMokDLgbG8YcN4nQg== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.7.tgz#eb2d71ac0819265a5c1289ade1a5652e60658dea" + integrity sha512-D3aheH8C76R7tWDDRdvtzhi0U8PBs+bQDR6rzyad6cprxn9GWbN0e6FmpLLKaUEmVipk4qOLyX+9ojQ10WSIgw== dependencies: - "@microsoft/api-extractor-model" "7.7.5" - "@microsoft/node-core-library" "3.19.1" + "@microsoft/api-extractor-model" "7.7.6" + "@microsoft/node-core-library" "3.19.2" "@microsoft/ts-command-line" "4.3.10" "@microsoft/tsdoc" "0.12.14" colors "~1.2.1" @@ -310,10 +310,10 @@ source-map "~0.6.1" typescript "~3.7.2" -"@microsoft/node-core-library@3.19.1": - version "3.19.1" - resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.19.1.tgz#cc881d9a3ccb21857ecc71bfc2df92e52fe82907" - integrity sha512-CTlTX3goPe2HUWg+n5w/cYUFI+qTx2gv4XVycjpPRi5KqwrowZ+wfSWkaM7AQ8RaMZ7d4AXVXeRm+2k6eW261g== +"@microsoft/node-core-library@3.19.2": + version "3.19.2" + resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.19.2.tgz#57a564969ce93c7b352d157f70057e605f04ba0e" + integrity sha512-jySSnueZqXNvIsnt/3hsi7tjwhKFVFFDg8Cbx8z50UI9oPWy5xYBE88SXmxfIXO6OOmxPMWzvGoo78WlMfNsyQ== dependencies: "@types/node" "10.17.13" colors "~1.2.1" From aefb7d282ed716923ca1a288a63a83a94af87ebc Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 23 Jan 2020 13:42:31 -0500 Subject: [PATCH 0013/5381] fix(reactivity): Array methods relying on identity should work with raw values --- .../reactivity/__tests__/reactive.spec.ts | 21 +++++++++++++++++++ packages/reactivity/src/baseHandlers.ts | 15 ++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/reactivity/__tests__/reactive.spec.ts b/packages/reactivity/__tests__/reactive.spec.ts index 62913e67063..9db682f8973 100644 --- a/packages/reactivity/__tests__/reactive.spec.ts +++ b/packages/reactivity/__tests__/reactive.spec.ts @@ -44,6 +44,27 @@ describe('reactivity/reactive', () => { expect(clone[0]).toBe(observed[0]) }) + test('Array identity methods should work with raw values', () => { + const raw = {} + const arr = reactive([{}, {}]) + arr.push(raw) + expect(arr.indexOf(raw)).toBe(2) + expect(arr.indexOf(raw, 3)).toBe(-1) + expect(arr.includes(raw)).toBe(true) + expect(arr.includes(raw, 3)).toBe(false) + expect(arr.lastIndexOf(raw)).toBe(2) + expect(arr.lastIndexOf(raw, 1)).toBe(-1) + + // should work also for the observed version + const observed = arr[2] + expect(arr.indexOf(observed)).toBe(2) + expect(arr.indexOf(observed, 3)).toBe(-1) + expect(arr.includes(observed)).toBe(true) + expect(arr.includes(observed, 3)).toBe(false) + expect(arr.lastIndexOf(observed)).toBe(2) + expect(arr.lastIndexOf(observed, 1)).toBe(-1) + }) + test('nested reactives', () => { const original = { nested: { diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index 30769705523..cee6588988a 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -2,7 +2,7 @@ import { reactive, readonly, toRaw } from './reactive' import { TrackOpTypes, TriggerOpTypes } from './operations' import { track, trigger, ITERATE_KEY } from './effect' import { LOCKED } from './lock' -import { isObject, hasOwn, isSymbol, hasChanged } from '@vue/shared' +import { isObject, hasOwn, isSymbol, hasChanged, isArray } from '@vue/shared' import { isRef } from './ref' const builtInSymbols = new Set( @@ -15,8 +15,21 @@ const get = /*#__PURE__*/ createGetter() const readonlyGet = /*#__PURE__*/ createGetter(true) const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true) +const arrayIdentityInstrumentations: Record = {} +;['includes', 'indexOf', 'lastIndexOf'].forEach(key => { + arrayIdentityInstrumentations[key] = function( + value: unknown, + ...args: any[] + ): any { + return toRaw(this)[key](toRaw(value), ...args) + } +}) + function createGetter(isReadonly = false, shallow = false) { return function get(target: object, key: string | symbol, receiver: object) { + if (isArray(target) && hasOwn(arrayIdentityInstrumentations, key)) { + return Reflect.get(arrayIdentityInstrumentations, key, receiver) + } const res = Reflect.get(target, key, receiver) if (isSymbol(key) && builtInSymbols.has(key)) { return res From 963c71a7ed8bd4f2ff913dcccdc47acb64fbb506 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2020 07:56:52 +0000 Subject: [PATCH 0014/5381] build(deps-dev): bump @types/jest from 24.9.0 to 24.9.1 Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 24.9.0 to 24.9.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest) Signed-off-by: dependabot-preview[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5ca13ba172d..6fad939b642 100644 --- a/yarn.lock +++ b/yarn.lock @@ -496,9 +496,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@^24.0.21": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.9.0.tgz#78c6991cd1734cf0d390be24875e310bb0a9fb74" - integrity sha512-dXvuABY9nM1xgsXlOtLQXJKdacxZJd7AtvLsKZ/0b57ruMXDKCOXAC/M75GbllQX6o1pcZ5hAG4JzYy7Z/wM2w== + version "24.9.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.9.1.tgz#02baf9573c78f1b9974a5f36778b366aa77bd534" + integrity sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q== dependencies: jest-diff "^24.3.0" From 48152bc88ea817ae23e2987dce99d64b426366c1 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 25 Jan 2020 22:31:29 -0500 Subject: [PATCH 0015/5381] fix(runtime-dom): should not access document in non-browser env fix #657 --- packages/runtime-dom/src/nodeOps.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-dom/src/nodeOps.ts b/packages/runtime-dom/src/nodeOps.ts index 332e6654c45..291eecd05a5 100644 --- a/packages/runtime-dom/src/nodeOps.ts +++ b/packages/runtime-dom/src/nodeOps.ts @@ -1,4 +1,4 @@ -const doc = document +const doc = (typeof document !== 'undefined' ? document : null) as Document const svgNS = 'http://www.w3.org/2000/svg' export const nodeOps = { From 2837ce842856d51dfbb55e3fa4a36a352446fb54 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sun, 26 Jan 2020 14:13:55 -0500 Subject: [PATCH 0016/5381] fix(v-model/emit): update:camelCase events should trigger kebab case equivalent close #656 --- .../runtime-core/__tests__/component.spec.ts | 26 +++++++++++++++++++ packages/runtime-core/src/component.ts | 9 +++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/component.spec.ts b/packages/runtime-core/__tests__/component.spec.ts index 848509af8c7..bf9377e1b99 100644 --- a/packages/runtime-core/__tests__/component.spec.ts +++ b/packages/runtime-core/__tests__/component.spec.ts @@ -78,7 +78,9 @@ describe('renderer: component', () => { setup() { return () => h(Child, { + // emit triggering single handler onBar: () => 1, + // emit triggering multiple handlers onBaz: [() => Promise.resolve(2), () => Promise.resolve(3)] }) } @@ -86,8 +88,32 @@ describe('renderer: component', () => { render(h(App), nodeOps.createElement('div')) + // assert return values from emit expect(noMatchEmitResult).toMatchObject([]) expect(singleEmitResult).toMatchObject([1]) expect(await Promise.all(multiEmitResult)).toMatchObject([2, 3]) }) + + // for v-model:foo-bar usage in DOM templates + test('emit update:xxx events should trigger kebab-case equivalent', () => { + const Child = defineComponent({ + setup(_, { emit }) { + emit('update:fooBar', 1) + return () => h('div') + } + }) + + const handler = jest.fn() + const App = { + setup() { + return () => + h(Child, { + 'onUpdate:foo-bar': handler + }) + } + } + + render(h(App), nodeOps.createElement('div')) + expect(handler).toHaveBeenCalled() + }) }) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 9bfaf50b001..b46d10ab550 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -25,7 +25,8 @@ import { NO, makeMap, isPromise, - isArray + isArray, + hyphenate } from '@vue/shared' import { SuspenseBoundary } from './components/Suspense' import { CompilerOptions } from '@vue/compiler-core' @@ -221,7 +222,11 @@ export function defineComponentInstance( emit: (event, ...args): any[] => { const props = instance.vnode.props || EMPTY_OBJ - const handler = props[`on${event}`] || props[`on${capitalize(event)}`] + let handler = props[`on${event}`] || props[`on${capitalize(event)}`] + if (!handler && event.indexOf('update:') === 0) { + event = hyphenate(event) + handler = props[`on${event}`] || props[`on${capitalize(event)}`] + } if (handler) { const res = callWithAsyncErrorHandling( handler, From 70e730fd197f105139365e120ad424b8f9230aee Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2020 08:06:41 +0000 Subject: [PATCH 0017/5381] build(deps-dev): bump rollup from 1.29.1 to 1.30.0 Bumps [rollup](https://github.com/rollup/rollup) from 1.29.1 to 1.30.0. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v1.29.1...v1.30.0) Signed-off-by: dependabot-preview[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6fad939b642..fb92c2720c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5227,9 +5227,9 @@ rollup-pluginutils@^2.5.0, rollup-pluginutils@^2.6.0, rollup-pluginutils@^2.8.2: estree-walker "^0.6.1" rollup@^1.19.4: - version "1.29.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.29.1.tgz#8715d0a4ca439be3079f8095989ec8aa60f637bc" - integrity sha512-dGQ+b9d1FOX/gluiggTAVnTvzQZUEkCi/TwZcax7ujugVRHs0nkYJlV9U4hsifGEMojnO+jvEML2CJQ6qXgbHA== + version "1.30.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.30.0.tgz#ae9c893804e8eaa8f8f74b0aaf7e7fb4374a9d01" + integrity sha512-ANcmfaSQwpcJtZUTA0ZMNBtFcQ1B4A5FldlNqEK0WdWm9sHSKu93ffa2KV1ux8HA/yKIV/ZARV28m7rNdXJgEw== dependencies: "@types/estree" "*" "@types/node" "*" From eacd3909928fcd84e1f99d2e4bbee95a8edc79e2 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 22 Jan 2020 10:39:09 -0500 Subject: [PATCH 0018/5381] chore: scaffold ssr compiler --- packages/compiler-ssr/README.md | 1 + packages/compiler-ssr/api-extractor.json | 7 ++++++ packages/compiler-ssr/package.json | 32 ++++++++++++++++++++++++ packages/compiler-ssr/src/index.ts | 3 +++ 4 files changed, 43 insertions(+) create mode 100644 packages/compiler-ssr/README.md create mode 100644 packages/compiler-ssr/api-extractor.json create mode 100644 packages/compiler-ssr/package.json create mode 100644 packages/compiler-ssr/src/index.ts diff --git a/packages/compiler-ssr/README.md b/packages/compiler-ssr/README.md new file mode 100644 index 00000000000..5beb121e1f5 --- /dev/null +++ b/packages/compiler-ssr/README.md @@ -0,0 +1 @@ +# @vue/compiler-ssr \ No newline at end of file diff --git a/packages/compiler-ssr/api-extractor.json b/packages/compiler-ssr/api-extractor.json new file mode 100644 index 00000000000..305e85ffe67 --- /dev/null +++ b/packages/compiler-ssr/api-extractor.json @@ -0,0 +1,7 @@ +{ + "extends": "../../api-extractor.json", + "mainEntryPointFilePath": "./dist/packages//src/index.d.ts", + "dtsRollup": { + "untrimmedFilePath": "./dist/.d.ts" + } +} \ No newline at end of file diff --git a/packages/compiler-ssr/package.json b/packages/compiler-ssr/package.json new file mode 100644 index 00000000000..a368e6f8511 --- /dev/null +++ b/packages/compiler-ssr/package.json @@ -0,0 +1,32 @@ +{ + "name": "@vue/compiler-ssr", + "version": "3.0.0-alpha.2", + "description": "@vue/compiler-ssr", + "main": "dist/compiler-ssr.cjs.js", + "types": "dist/compiler-ssr.d.ts", + "files": [ + "dist" + ], + "buildOptions": { + "prod": false, + "formats": [ + "cjs" + ] + }, + "repository": { + "type": "git", + "url": "git+https://github.com/vuejs/vue.git" + }, + "keywords": [ + "vue" + ], + "author": "Evan You", + "license": "MIT", + "bugs": { + "url": "https://github.com/vuejs/vue/issues" + }, + "homepage": "https://github.com/vuejs/vue/tree/dev/packages/compiler-ssr#readme", + "dependencies": { + "@vue/compiler-core": "3.0.0-alpha.2" + } +} diff --git a/packages/compiler-ssr/src/index.ts b/packages/compiler-ssr/src/index.ts new file mode 100644 index 00000000000..d8c2d5fd142 --- /dev/null +++ b/packages/compiler-ssr/src/index.ts @@ -0,0 +1,3 @@ +export function hello(): string { + return 'TODO' +} From c07751fd3605f301dc0f02fd2a48acc7ba7a0397 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 23 Jan 2020 15:05:38 -0500 Subject: [PATCH 0019/5381] refactor: adjust `createApp` related API signatures BREAKING CHANGE: `createApp` API has been adjusted. - `createApp()` now accepts the root component, and optionally a props object to pass to the root component. - `app.mount()` now accepts a single argument (the root container) - `app.unmount()` no longer requires arguments. New behavior looks like the following: ``` js const app = createApp(RootComponent) app.mount('#app') app.unmount() ``` --- .../{apiApp.spec.ts => apiCreateApp.spec.ts} | 215 ++++++++---------- .../__tests__/componentProxy.spec.ts | 20 +- .../__tests__/helpers/resolveAssets.spec.ts | 13 +- packages/runtime-core/src/apiCreateApp.ts | 44 ++-- packages/runtime-core/src/index.ts | 8 +- packages/runtime-core/src/renderer.ts | 4 +- .../__tests__/directives/vModel.spec.ts | 27 ++- .../__tests__/directives/vShow.spec.ts | 15 +- packages/runtime-dom/src/index.ts | 27 +-- packages/runtime-test/src/index.ts | 4 +- packages/vue/__tests__/index.spec.ts | 28 ++- packages/vue/examples/classic/commits.html | 10 +- packages/vue/examples/classic/grid.html | 10 +- packages/vue/examples/classic/markdown.html | 10 +- packages/vue/examples/classic/svg.html | 11 +- packages/vue/examples/classic/todomvc.html | 10 +- packages/vue/examples/classic/tree.html | 48 ++-- .../vue/examples/composition/commits.html | 6 +- packages/vue/examples/composition/grid.html | 10 +- .../vue/examples/composition/markdown.html | 6 +- packages/vue/examples/composition/svg.html | 7 +- .../vue/examples/composition/todomvc.html | 6 +- packages/vue/examples/composition/tree.html | 48 ++-- packages/vue/examples/transition/list.html | 6 +- packages/vue/examples/transition/modal.html | 9 +- 25 files changed, 276 insertions(+), 326 deletions(-) rename packages/runtime-core/__tests__/{apiApp.spec.ts => apiCreateApp.spec.ts} (81%) diff --git a/packages/runtime-core/__tests__/apiApp.spec.ts b/packages/runtime-core/__tests__/apiCreateApp.spec.ts similarity index 81% rename from packages/runtime-core/__tests__/apiApp.spec.ts rename to packages/runtime-core/__tests__/apiCreateApp.spec.ts index 6fb8239b8f9..0442cf70626 100644 --- a/packages/runtime-core/__tests__/apiApp.spec.ts +++ b/packages/runtime-core/__tests__/apiCreateApp.spec.ts @@ -30,18 +30,18 @@ describe('api: createApp', () => { } const root1 = nodeOps.createElement('div') - createApp().mount(Comp, root1) + createApp(Comp).mount(root1) expect(serializeInner(root1)).toBe(`0`) // mount with props const root2 = nodeOps.createElement('div') - const app2 = createApp() - app2.mount(Comp, root2, { count: 1 }) + const app2 = createApp(Comp, { count: 1 }) + app2.mount(root2) expect(serializeInner(root2)).toBe(`1`) // remount warning const root3 = nodeOps.createElement('div') - app2.mount(Comp, root3) + app2.mount(root3) expect(serializeInner(root3)).toBe(``) expect(`already been mounted`).toHaveBeenWarned() }) @@ -59,18 +59,14 @@ describe('api: createApp', () => { } const root = nodeOps.createElement('div') - const app = createApp() - app.mount(Comp, root) + const app = createApp(Comp) + app.mount(root) app.unmount(root) expect(serializeInner(root)).toBe(``) }) test('provide', () => { - const app = createApp() - app.provide('foo', 1) - app.provide('bar', 2) - const Root = { setup() { // test override @@ -87,25 +83,16 @@ describe('api: createApp', () => { } } + const app = createApp(Root) + app.provide('foo', 1) + app.provide('bar', 2) + const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect(serializeInner(root)).toBe(`3,2`) }) test('component', () => { - const app = createApp() - - const FooBar = () => 'foobar!' - app.component('FooBar', FooBar) - expect(app.component('FooBar')).toBe(FooBar) - - app.component('BarBaz', () => 'barbaz!') - - app.component('BarBaz', () => 'barbaz!') - expect( - 'Component "BarBaz" has already been registered in target app.' - ).toHaveBeenWarnedTimes(1) - const Root = { // local override components: { @@ -122,33 +109,29 @@ describe('api: createApp', () => { } } + const app = createApp(Root) + + const FooBar = () => 'foobar!' + app.component('FooBar', FooBar) + expect(app.component('FooBar')).toBe(FooBar) + + app.component('BarBaz', () => 'barbaz!') + + app.component('BarBaz', () => 'barbaz!') + expect( + 'Component "BarBaz" has already been registered in target app.' + ).toHaveBeenWarnedTimes(1) + const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect(serializeInner(root)).toBe(`
foobar!barbaz-local!
`) }) test('directive', () => { - const app = createApp() - const spy1 = jest.fn() const spy2 = jest.fn() const spy3 = jest.fn() - const FooBar = { mounted: spy1 } - app.directive('FooBar', FooBar) - expect(app.directive('FooBar')).toBe(FooBar) - - app.directive('BarBaz', { - mounted: spy2 - }) - - app.directive('BarBaz', { - mounted: spy2 - }) - expect( - 'Directive "BarBaz" has already been registered in target app.' - ).toHaveBeenWarnedTimes(1) - const Root = { // local override directives: { @@ -165,8 +148,25 @@ describe('api: createApp', () => { } } + const app = createApp(Root) + + const FooBar = { mounted: spy1 } + app.directive('FooBar', FooBar) + expect(app.directive('FooBar')).toBe(FooBar) + + app.directive('BarBaz', { + mounted: spy2 + }) + + app.directive('BarBaz', { + mounted: spy2 + }) + expect( + 'Directive "BarBaz" has already been registered in target app.' + ).toHaveBeenWarnedTimes(1) + const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect(spy1).toHaveBeenCalled() expect(spy2).not.toHaveBeenCalled() expect(spy3).toHaveBeenCalled() @@ -232,7 +232,7 @@ describe('api: createApp', () => { } } - const app = createApp() + const app = createApp(Comp) app.mixin(mixinA) app.mixin(mixinB) @@ -246,7 +246,7 @@ describe('api: createApp', () => { ).toHaveBeenWarnedTimes(1) const root = nodeOps.createElement('div') - app.mount(Comp, root) + app.mount(root) expect(serializeInner(root)).toBe(`123`) expect(calls).toEqual([ @@ -272,11 +272,6 @@ describe('api: createApp', () => { } const PluginD: any = undefined - const app = createApp() - app.use(PluginA) - app.use(PluginB, 1, 1) - app.use(PluginC) - const Root = { setup() { const foo = inject('foo') @@ -284,8 +279,14 @@ describe('api: createApp', () => { return () => `${foo},${bar}` } } + + const app = createApp(Root) + app.use(PluginA) + app.use(PluginB, 1, 1) + app.use(PluginC) + const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect(serializeInner(root)).toBe(`1,2`) app.use(PluginA) @@ -301,18 +302,14 @@ describe('api: createApp', () => { }) test('config.errorHandler', () => { - const app = createApp() - const error = new Error() const count = ref(0) - const handler = (app.config.errorHandler = jest.fn( - (err, instance, info) => { - expect(err).toBe(error) - expect((instance as any).count).toBe(count.value) - expect(info).toBe(`render function`) - } - )) + const handler = jest.fn((err, instance, info) => { + expect(err).toBe(error) + expect((instance as any).count).toBe(count.value) + expect(info).toBe(`render function`) + }) const Root = { setup() { @@ -326,21 +323,19 @@ describe('api: createApp', () => { } } - app.mount(Root, nodeOps.createElement('div')) + const app = createApp(Root) + app.config.errorHandler = handler + app.mount(nodeOps.createElement('div')) expect(handler).toHaveBeenCalled() }) test('config.warnHandler', () => { - const app = createApp() let ctx: any - - const handler = (app.config.warnHandler = jest.fn( - (msg, instance, trace) => { - expect(msg).toMatch(`Component is missing template or render function`) - expect(instance).toBe(ctx.proxy) - expect(trace).toMatch(`Hello`) - } - )) + const handler = jest.fn((msg, instance, trace) => { + expect(msg).toMatch(`Component is missing template or render function`) + expect(instance).toBe(ctx.proxy) + expect(trace).toMatch(`Hello`) + }) const Root = { name: 'Hello', @@ -349,7 +344,9 @@ describe('api: createApp', () => { } } - app.mount(Root, nodeOps.createElement('div')) + const app = createApp(Root) + app.config.warnHandler = handler + app.mount(nodeOps.createElement('div')) expect(handler).toHaveBeenCalledTimes(1) }) @@ -357,104 +354,82 @@ describe('api: createApp', () => { const isNativeTag = jest.fn(tag => tag === 'div') test('Component.name', () => { - const app = createApp() - Object.defineProperty(app.config, 'isNativeTag', { - value: isNativeTag, - writable: false - }) - const Root = { name: 'div', - setup() { - return { - count: ref(0) - } - }, render() { return null } } - app.mount(Root, nodeOps.createElement('div')) - expect( - `Do not use built-in or reserved HTML elements as component id: div` - ).toHaveBeenWarned() - }) + const app = createApp(Root) - test('Component.components', () => { - const app = createApp() Object.defineProperty(app.config, 'isNativeTag', { value: isNativeTag, writable: false }) + app.mount(nodeOps.createElement('div')) + expect( + `Do not use built-in or reserved HTML elements as component id: div` + ).toHaveBeenWarned() + }) + + test('Component.components', () => { const Root = { components: { div: () => 'div' }, - setup() { - return { - count: ref(0) - } - }, render() { return null } } - app.mount(Root, nodeOps.createElement('div')) + const app = createApp(Root) + Object.defineProperty(app.config, 'isNativeTag', { + value: isNativeTag, + writable: false + }) + + app.mount(nodeOps.createElement('div')) expect( `Do not use built-in or reserved HTML elements as component id: div` ).toHaveBeenWarned() }) test('Component.directives', () => { - const app = createApp() - Object.defineProperty(app.config, 'isNativeTag', { - value: isNativeTag, - writable: false - }) - const Root = { directives: { bind: () => {} }, - setup() { - return { - count: ref(0) - } - }, render() { return null } } - app.mount(Root, nodeOps.createElement('div')) + const app = createApp(Root) + Object.defineProperty(app.config, 'isNativeTag', { + value: isNativeTag, + writable: false + }) + + app.mount(nodeOps.createElement('div')) expect( `Do not use built-in directive ids as custom directive id: bind` ).toHaveBeenWarned() }) test('register using app.component', () => { - const app = createApp() + const app = createApp({ + render() {} + }) + Object.defineProperty(app.config, 'isNativeTag', { value: isNativeTag, writable: false }) - const Root = { - setup() { - return { - count: ref(0) - } - }, - render() { - return null - } - } - app.component('div', () => 'div') - app.mount(Root, nodeOps.createElement('div')) + app.mount(nodeOps.createElement('div')) expect( `Do not use built-in or reserved HTML elements as component id: div` ).toHaveBeenWarned() diff --git a/packages/runtime-core/__tests__/componentProxy.spec.ts b/packages/runtime-core/__tests__/componentProxy.spec.ts index ddfd8cab0bf..0790f2246e1 100644 --- a/packages/runtime-core/__tests__/componentProxy.spec.ts +++ b/packages/runtime-core/__tests__/componentProxy.spec.ts @@ -1,4 +1,4 @@ -import { createApp, getCurrentInstance, nodeOps } from '@vue/runtime-test' +import { h, render, getCurrentInstance, nodeOps } from '@vue/runtime-test' import { mockWarn } from '@vue/shared' import { ComponentInternalInstance } from '../src/component' @@ -6,7 +6,6 @@ describe('component: proxy', () => { mockWarn() test('data', () => { - const app = createApp() let instance: ComponentInternalInstance let instanceProxy: any const Comp = { @@ -23,14 +22,13 @@ describe('component: proxy', () => { return null } } - app.mount(Comp, nodeOps.createElement('div')) + render(h(Comp), nodeOps.createElement('div')) expect(instanceProxy.foo).toBe(1) instanceProxy.foo = 2 expect(instance!.data.foo).toBe(2) }) test('renderContext', () => { - const app = createApp() let instance: ComponentInternalInstance let instanceProxy: any const Comp = { @@ -47,14 +45,13 @@ describe('component: proxy', () => { return null } } - app.mount(Comp, nodeOps.createElement('div')) + render(h(Comp), nodeOps.createElement('div')) expect(instanceProxy.foo).toBe(1) instanceProxy.foo = 2 expect(instance!.renderContext.foo).toBe(2) }) test('propsProxy', () => { - const app = createApp() let instance: ComponentInternalInstance let instanceProxy: any const Comp = { @@ -72,7 +69,7 @@ describe('component: proxy', () => { instanceProxy = this } } - app.mount(Comp, nodeOps.createElement('div')) + render(h(Comp), nodeOps.createElement('div')) expect(instanceProxy.foo).toBe(1) expect(instance!.propsProxy!.foo).toBe(1) expect(() => (instanceProxy.foo = 2)).toThrow(TypeError) @@ -80,7 +77,6 @@ describe('component: proxy', () => { }) test('public properties', () => { - const app = createApp() let instance: ComponentInternalInstance let instanceProxy: any const Comp = { @@ -92,7 +88,7 @@ describe('component: proxy', () => { instanceProxy = this } } - app.mount(Comp, nodeOps.createElement('div')) + render(h(Comp), nodeOps.createElement('div')) expect(instanceProxy.$data).toBe(instance!.data) expect(instanceProxy.$props).toBe(instance!.propsProxy) expect(instanceProxy.$attrs).toBe(instance!.attrs) @@ -108,7 +104,6 @@ describe('component: proxy', () => { }) test('sink', async () => { - const app = createApp() let instance: ComponentInternalInstance let instanceProxy: any const Comp = { @@ -120,14 +115,13 @@ describe('component: proxy', () => { instanceProxy = this } } - app.mount(Comp, nodeOps.createElement('div')) + render(h(Comp), nodeOps.createElement('div')) instanceProxy.foo = 1 expect(instanceProxy.foo).toBe(1) expect(instance!.sink.foo).toBe(1) }) test('has check', () => { - const app = createApp() let instanceProxy: any const Comp = { render() {}, @@ -148,7 +142,7 @@ describe('component: proxy', () => { instanceProxy = this } } - app.mount(Comp, nodeOps.createElement('div'), { msg: 'hello' }) + render(h(Comp, { msg: 'hello' }), nodeOps.createElement('div')) // props expect('msg' in instanceProxy).toBe(true) diff --git a/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts b/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts index 392311c1cb5..779814b7930 100644 --- a/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts +++ b/packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts @@ -12,7 +12,6 @@ import { mockWarn } from '@vue/shared' describe('resolveAssets', () => { test('should work', () => { - const app = createApp() const FooBar = () => null const BarBaz = { mounted: () => null } @@ -49,8 +48,9 @@ describe('resolveAssets', () => { } } + const app = createApp(Root) const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect(component1!).toBe(FooBar) expect(component2!).toBe(FooBar) expect(component3!).toBe(FooBar) @@ -78,7 +78,6 @@ describe('resolveAssets', () => { }) test('not exist', () => { - const app = createApp() const Root = { setup() { resolveComponent('foo') @@ -87,14 +86,14 @@ describe('resolveAssets', () => { } } + const app = createApp(Root) const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect('Failed to resolve component: foo').toHaveBeenWarned() expect('Failed to resolve directive: bar').toHaveBeenWarned() }) test('resolve dynamic component', () => { - const app = createApp() const dynamicComponents = { foo: () => 'foo', bar: () => 'bar', @@ -112,8 +111,10 @@ describe('resolveAssets', () => { } } } + + const app = createApp(Root) const root = nodeOps.createElement('div') - app.mount(Root, root) + app.mount(root) expect(foo).toBe(dynamicComponents.foo) expect(bar).toBe(dynamicComponents.bar) expect(baz).toBe(dynamicComponents.baz) diff --git a/packages/runtime-core/src/apiCreateApp.ts b/packages/runtime-core/src/apiCreateApp.ts index fdd377d0264..a01b5ecb608 100644 --- a/packages/runtime-core/src/apiCreateApp.ts +++ b/packages/runtime-core/src/apiCreateApp.ts @@ -16,16 +16,11 @@ export interface App { component(name: string, component: Component): this directive(name: string): Directive | undefined directive(name: string, directive: Directive): this - mount( - rootComponent: - | Component - // for compatibility with defineComponent() return types - | { new (): ComponentPublicInstance }, - rootContainer: HostElement | string, - rootProps?: Data - ): ComponentPublicInstance + mount(rootContainer: HostElement | string): ComponentPublicInstance unmount(rootContainer: HostElement | string): void provide(key: InjectionKey | string, value: T): this + rootComponent: Component + rootContainer: HostElement | null } export interface AppConfig { @@ -79,16 +74,30 @@ export function createAppContext(): AppContext { } } +export type CreateAppFunction = ( + rootComponent: + | Component + // for compatibility with defineComponent() return types + | { new (): ComponentPublicInstance }, + rootProps?: Data | null +) => App + export function createAppAPI( render: RootRenderFunction -): () => App { - return function createApp(): App { +): CreateAppFunction { + return function createApp( + rootComponent: Component, + rootProps?: Data | null + ): App { const context = createAppContext() const installedPlugins = new Set() let isMounted = false const app: App = { + rootComponent, + rootContainer: null, + get config() { return context.config }, @@ -165,11 +174,7 @@ export function createAppAPI( return app }, - mount( - rootComponent: Component, - rootContainer: HostElement, - rootProps?: Data | null - ): any { + mount(rootContainer: HostElement): any { if (!isMounted) { if (rootProps != null && !isObject(rootProps)) { __DEV__ && @@ -190,6 +195,7 @@ export function createAppAPI( render(vnode, rootContainer) isMounted = true + app.rootContainer = rootContainer return vnode.component!.proxy } else if (__DEV__) { warn( @@ -198,8 +204,12 @@ export function createAppAPI( } }, - unmount(rootContainer: HostElement) { - render(null, rootContainer) + unmount() { + if (isMounted) { + render(null, app.rootContainer!) + } else if (__DEV__) { + warn(`Cannot unmount an app that is not mounted.`) + } }, provide(key, value) { diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 181e53f8dd2..435ede78176 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -99,7 +99,13 @@ export { registerRuntimeCompiler } from './component' // Types ----------------------------------------------------------------------- -export { App, AppConfig, AppContext, Plugin } from './apiCreateApp' +export { + App, + AppConfig, + AppContext, + Plugin, + CreateAppFunction +} from './apiCreateApp' export { VNode, VNodeTypes, VNodeProps } from './vnode' export { Component, diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index d26f73dae9a..7af49a21d93 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -46,7 +46,7 @@ import { ShapeFlags } from './shapeFlags' import { pushWarningContext, popWarningContext, warn } from './warning' import { invokeDirectiveHook } from './directives' import { ComponentPublicInstance } from './componentProxy' -import { App, createAppAPI } from './apiCreateApp' +import { createAppAPI, CreateAppFunction } from './apiCreateApp' import { SuspenseBoundary, queueEffectWithSuspense, @@ -174,7 +174,7 @@ export function createRenderer< options: RendererOptions ): { render: RootRenderFunction - createApp: () => App + createApp: CreateAppFunction } { type HostVNode = VNode type HostVNodeChildren = VNodeChildren diff --git a/packages/runtime-dom/__tests__/directives/vModel.spec.ts b/packages/runtime-dom/__tests__/directives/vModel.spec.ts index cd187ff80af..aac67c00d2d 100644 --- a/packages/runtime-dom/__tests__/directives/vModel.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vModel.spec.ts @@ -1,6 +1,6 @@ import { - createApp, h, + render, nextTick, defineComponent, vModelDynamic, @@ -20,10 +20,9 @@ const setValue = function(this: any, value: any) { this.value = value } -let app: any, root: any +let root: any beforeEach(() => { - app = createApp() root = document.createElement('div') as any }) @@ -44,9 +43,9 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) - const input = root.querySelector('input') + const input = root.querySelector('input')! const data = root._vnode.component.data input.value = 'foo' @@ -75,7 +74,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const input = root.querySelector('textarea') const data = root._vnode.component.data @@ -136,7 +135,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const number = root.querySelector('.number') const trim = root.querySelector('.trim') @@ -176,7 +175,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const input = root.querySelector('input') const data = root._vnode.component.data @@ -219,7 +218,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const input = root.querySelector('input') const data = root._vnode.component.data @@ -262,7 +261,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const input = root.querySelector('input') const data = root._vnode.component.data @@ -314,7 +313,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const foo = root.querySelector('.foo') const bar = root.querySelector('.bar') @@ -384,7 +383,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const foo = root.querySelector('.foo') const bar = root.querySelector('.bar') @@ -437,7 +436,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const input = root.querySelector('select') const foo = root.querySelector('option[value=foo]') @@ -494,7 +493,7 @@ describe('vModel', () => { ] } }) - app.mount(component, root) + render(h(component), root) const input = root.querySelector('select') const foo = root.querySelector('option[value=foo]') diff --git a/packages/runtime-dom/__tests__/directives/vShow.spec.ts b/packages/runtime-dom/__tests__/directives/vShow.spec.ts index 76eef6513e4..6c21e5f83f0 100644 --- a/packages/runtime-dom/__tests__/directives/vShow.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vShow.spec.ts @@ -5,16 +5,15 @@ import { nextTick, VNode } from '@vue/runtime-core' -import { createApp, vShow } from '@vue/runtime-dom' +import { render, vShow } from '@vue/runtime-dom' const withVShow = (node: VNode, exp: any) => withDirectives(node, [[vShow, exp]]) -let app: any, root: any +let root: any beforeEach(() => { - app = createApp() - root = document.createElement('div') as any + root = document.createElement('div') }) describe('runtime-dom: v-show directive', () => { @@ -27,7 +26,7 @@ describe('runtime-dom: v-show directive', () => { return [withVShow(h('div'), this.value)] } }) - app.mount(component, root) + render(h(component), root) const $div = root.querySelector('div') @@ -43,7 +42,7 @@ describe('runtime-dom: v-show directive', () => { return [withVShow(h('div'), this.value)] } }) - app.mount(component, root) + render(h(component), root) const $div = root.querySelector('div') @@ -59,7 +58,7 @@ describe('runtime-dom: v-show directive', () => { return [withVShow(h('div'), this.value)] } }) - app.mount(component, root) + render(h(component), root) const $div = root.querySelector('div') const data = root._vnode.component.data @@ -110,7 +109,7 @@ describe('runtime-dom: v-show directive', () => { ] } }) - app.mount(component, root) + render(h(component), root) const $div = root.querySelector('div') const data = root._vnode.component.data diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index 8d5de566483..51a8e0aa53d 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -1,8 +1,8 @@ import { createRenderer, warn, - App, - RootRenderFunction + RootRenderFunction, + CreateAppFunction } from '@vue/runtime-core' import { nodeOps } from './nodeOps' import { patchProp } from './patchProp' @@ -17,8 +17,8 @@ const { render: baseRender, createApp: baseCreateApp } = createRenderer({ // use explicit type casts here to avoid import() calls in rolled-up d.ts export const render = baseRender as RootRenderFunction -export const createApp = (): App => { - const app = baseCreateApp() +export const createApp: CreateAppFunction = (...args) => { + const app = baseCreateApp(...args) if (__DEV__) { // Inject `isNativeTag` @@ -29,8 +29,8 @@ export const createApp = (): App => { }) } - const { mount, unmount } = app - app.mount = (component, container, props): any => { + const { mount } = app + app.mount = (container): any => { if (isString(container)) { container = document.querySelector(container)! if (!container) { @@ -39,6 +39,7 @@ export const createApp = (): App => { return } } + const component = app.rootComponent if ( __RUNTIME_COMPILE__ && !isFunction(component) && @@ -49,19 +50,7 @@ export const createApp = (): App => { } // clear content before mounting container.innerHTML = '' - return mount(component, container, props) - } - - app.unmount = container => { - if (isString(container)) { - container = document.querySelector(container)! - if (!container) { - __DEV__ && - warn(`Failed to unmount app: mount target selector returned null.`) - return - } - } - unmount(container) + return mount(container) } return app diff --git a/packages/runtime-test/src/index.ts b/packages/runtime-test/src/index.ts index c057da7e018..7b6dcfd97e2 100644 --- a/packages/runtime-test/src/index.ts +++ b/packages/runtime-test/src/index.ts @@ -2,7 +2,7 @@ import { createRenderer, VNode, RootRenderFunction, - App + CreateAppFunction } from '@vue/runtime-core' import { nodeOps, TestNode, TestElement } from './nodeOps' import { patchProp } from './patchProp' @@ -14,7 +14,7 @@ const { render: baseRender, createApp: baseCreateApp } = createRenderer({ }) export const render = baseRender as RootRenderFunction -export const createApp = baseCreateApp as () => App +export const createApp = baseCreateApp as CreateAppFunction // convenience for one-off render validations export function renderToString(vnode: VNode) { diff --git a/packages/vue/__tests__/index.spec.ts b/packages/vue/__tests__/index.spec.ts index 4a7a06bb64d..3bde76341e8 100644 --- a/packages/vue/__tests__/index.spec.ts +++ b/packages/vue/__tests__/index.spec.ts @@ -14,7 +14,7 @@ describe('compiler + runtime integration', () => { } } } - createApp().mount(App, container) + createApp(App).mount(container) expect(container.innerHTML).toBe(`0`) }) @@ -33,7 +33,7 @@ describe('compiler + runtime integration', () => { } } } - createApp().mount(App, container) + createApp(App).mount(container) expect(container.innerHTML).toBe(`0`) }) @@ -51,7 +51,7 @@ describe('compiler + runtime integration', () => { } } } - createApp().mount(App, container) + createApp(App).mount(container) expect(container.innerHTML).toBe(`0`) }) @@ -60,7 +60,7 @@ describe('compiler + runtime integration', () => { const App = { template: `
` } - createApp().mount(App, container) + createApp(App).mount(container) expect( `Template compilation error: Element is missing end tag` ).toHaveBeenWarned() @@ -78,26 +78,24 @@ describe('compiler + runtime integration', () => { }) it('should support custom element', () => { - const app = createApp() - const container = document.createElement('div') - const App = { + const app = createApp({ template: '' - } + }) + const container = document.createElement('div') app.config.isCustomElement = tag => tag === 'custom' - app.mount(App, container) + app.mount(container) expect(container.innerHTML).toBe('') }) it('should support using element innerHTML as template', () => { - const app = createApp() - const container = document.createElement('div') - container.innerHTML = '{{msg}}' - const App = { + const app = createApp({ data: { msg: 'hello' } - } - app.mount(App, container) + }) + const container = document.createElement('div') + container.innerHTML = '{{msg}}' + app.mount(container) expect(container.innerHTML).toBe('hello') }) }) diff --git a/packages/vue/examples/classic/commits.html b/packages/vue/examples/classic/commits.html index d88f0e28b25..1a258753874 100644 --- a/packages/vue/examples/classic/commits.html +++ b/packages/vue/examples/classic/commits.html @@ -24,12 +24,12 @@

Latest Vue.js Commits

\n`) - .descriptor.styles[0] - // TODO need to actually test this with SourceMapConsumer + // Padding determines how many blank lines will there be before the style block + const padding = Math.round(Math.random() * 10) + const style = parse( + `${'\n'.repeat(padding)}\n` + ).descriptor.styles[0] + expect(style.map).not.toBeUndefined() + + const consumer = new SourceMapConsumer(style.map!) + consumer.eachMapping(mapping => { + expect(mapping.originalLine - mapping.generatedLine).toBe(padding) + }) }) test('script block', () => { - const script = parse(`\n`) - .descriptor.script - // TODO need to actually test this with SourceMapConsumer + // Padding determines how many blank lines will there be before the style block + const padding = Math.round(Math.random() * 10) + const script = parse( + `${'\n'.repeat(padding)}\n` + ).descriptor.script + expect(script!.map).not.toBeUndefined() + + const consumer = new SourceMapConsumer(script!.map!) + consumer.eachMapping(mapping => { + expect(mapping.originalLine - mapping.generatedLine).toBe(padding) + }) }) }) From 5495c70c4a3f740ef4ac575ffee5466ca747cca1 Mon Sep 17 00:00:00 2001 From: Jonas <30421456+jonaskuske@users.noreply.github.com> Date: Mon, 10 Feb 2020 15:36:19 +0100 Subject: [PATCH 0142/5381] fix(transition-group): handle multiple move-classes (#679) fix #678 --- packages/runtime-dom/src/components/TransitionGroup.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts index bd372364486..490edb8c5ff 100644 --- a/packages/runtime-dom/src/components/TransitionGroup.ts +++ b/packages/runtime-dom/src/components/TransitionGroup.ts @@ -187,9 +187,11 @@ function hasCSSTransform( // is applied. const clone = el.cloneNode() as HTMLElement if (el._vtc) { - el._vtc.forEach(cls => clone.classList.remove(cls)) + el._vtc.forEach(cls => { + cls.split(/\s+/).forEach(c => c && clone.classList.remove(c)) + }) } - clone.classList.add(moveClass) + moveClass.split(/\s+/).forEach(c => c && clone.classList.add(c)) clone.style.display = 'none' const container = (root.nodeType === 1 ? root From 571ed4226be618dcc9f95e4c2da8d82d7d2f7750 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Feb 2020 11:00:37 -0500 Subject: [PATCH 0143/5381] feat(compiler-core/v-on): support @vnode-xxx usage for vnode hooks --- .../compiler-core/__tests__/transforms/vOn.spec.ts | 14 ++++++++++++++ packages/compiler-core/src/transforms/vOn.ts | 13 +++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/vOn.spec.ts b/packages/compiler-core/__tests__/transforms/vOn.spec.ts index 3ba3c4a8182..2ad2b4f1440 100644 --- a/packages/compiler-core/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vOn.spec.ts @@ -300,6 +300,20 @@ describe('compiler: transform v-on', () => { expect(onError).not.toHaveBeenCalled() }) + test('case conversion for vnode hooks', () => { + const { node } = parseWithVOn(`
`) + const props = (node.codegenNode as CallExpression) + .arguments[1] as ObjectExpression + expect(props.properties[0]).toMatchObject({ + key: { + content: `onVnodeMounted` + }, + value: { + content: `onMount` + } + }) + }) + describe('cacheHandler', () => { test('empty handler', () => { const { root, node } = parseWithVOn(`
`, { diff --git a/packages/compiler-core/src/transforms/vOn.ts b/packages/compiler-core/src/transforms/vOn.ts index c56b300c010..113a1181880 100644 --- a/packages/compiler-core/src/transforms/vOn.ts +++ b/packages/compiler-core/src/transforms/vOn.ts @@ -8,7 +8,7 @@ import { createCompoundExpression, SimpleExpressionNode } from '../ast' -import { capitalize } from '@vue/shared' +import { capitalize, camelize } from '@vue/shared' import { createCompilerError, ErrorCodes } from '../errors' import { processExpression } from './transformExpression' import { isMemberExpression, hasScopeRef } from '../utils' @@ -38,11 +38,12 @@ export const transformOn: DirectiveTransform = ( let eventName: ExpressionNode if (arg.type === NodeTypes.SIMPLE_EXPRESSION) { if (arg.isStatic) { - eventName = createSimpleExpression( - `on${capitalize(arg.content)}`, - true, - arg.loc - ) + const rawName = arg.content + // for @vnode-xxx event listeners, auto convert it to camelCase + const normalizedName = rawName.startsWith(`vnode`) + ? capitalize(camelize(rawName)) + : capitalize(rawName) + eventName = createSimpleExpression(`on${normalizedName}`, true, arg.loc) } else { eventName = createCompoundExpression([`"on" + (`, arg, `)`]) } From 778f3a5e886a1a1136bc8b00b849370d7c4041be Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Feb 2020 12:06:36 -0500 Subject: [PATCH 0144/5381] fix(runtime-core): should not return early on text patchFlag fix vnode updated hook on elements with dynamic text children --- packages/runtime-core/src/renderer.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index f4c68387f63..cee334a8fcc 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -542,12 +542,10 @@ export function createRenderer< // text // This flag is matched when the element has only dynamic text children. - // this flag is terminal (i.e. skips children diffing). if (patchFlag & PatchFlags.TEXT) { if (n1.children !== n2.children) { hostSetElementText(el, n2.children as string) } - return // terminal } } else if (!optimized && dynamicChildren == null) { // unoptimized, full diff From 8a87074df013fdbb0e88f34074c2605e4af2937c Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Feb 2020 13:09:15 -0500 Subject: [PATCH 0145/5381] fix(runtime-core/scheduler): avoid duplicate updates of child component --- .../runtime-core/__tests__/scheduler.spec.ts | 26 ++++++++++++++++++- packages/runtime-core/src/renderer.ts | 10 ++++++- packages/runtime-core/src/scheduler.ts | 12 ++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/scheduler.spec.ts b/packages/runtime-core/__tests__/scheduler.spec.ts index 03a7abc1629..65535d679a0 100644 --- a/packages/runtime-core/__tests__/scheduler.spec.ts +++ b/packages/runtime-core/__tests__/scheduler.spec.ts @@ -1,4 +1,9 @@ -import { queueJob, nextTick, queuePostFlushCb } from '../src/scheduler' +import { + queueJob, + nextTick, + queuePostFlushCb, + invalidateJob +} from '../src/scheduler' describe('scheduler', () => { it('nextTick', async () => { @@ -230,4 +235,23 @@ describe('scheduler', () => { expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2']) }) }) + + test('invalidateJob', async () => { + const calls: string[] = [] + const job1 = () => { + calls.push('job1') + invalidateJob(job2) + job2() + } + const job2 = () => { + calls.push('job2') + } + // queue both jobs + queueJob(job1) + queueJob(job2) + expect(calls).toEqual([]) + await nextTick() + // job2 should be called only once + expect(calls).toEqual(['job1', 'job2']) + }) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index cee334a8fcc..e2f87c8f277 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -30,7 +30,12 @@ import { isFunction, PatchFlags } from '@vue/shared' -import { queueJob, queuePostFlushCb, flushPostFlushCbs } from './scheduler' +import { + queueJob, + queuePostFlushCb, + flushPostFlushCbs, + invalidateJob +} from './scheduler' import { effect, stop, @@ -895,6 +900,9 @@ export function createRenderer< } else { // normal update instance.next = n2 + // in case the child component is also queued, remove it to avoid + // double updating the same child component in the same flush. + invalidateJob(instance.update) // instance.update is the reactive effect runner. instance.update() } diff --git a/packages/runtime-core/src/scheduler.ts b/packages/runtime-core/src/scheduler.ts index 78d3d59cd1d..a13a01280e0 100644 --- a/packages/runtime-core/src/scheduler.ts +++ b/packages/runtime-core/src/scheduler.ts @@ -1,7 +1,7 @@ import { ErrorCodes, callWithErrorHandling } from './errorHandling' import { isArray } from '@vue/shared' -const queue: Function[] = [] +const queue: (Function | null)[] = [] const postFlushCbs: Function[] = [] const p = Promise.resolve() @@ -22,6 +22,13 @@ export function queueJob(job: () => void) { } } +export function invalidateJob(job: () => void) { + const i = queue.indexOf(job) + if (i > -1) { + queue[i] = null + } +} + export function queuePostFlushCb(cb: Function | Function[]) { if (!isArray(cb)) { postFlushCbs.push(cb) @@ -64,6 +71,9 @@ function flushJobs(seen?: CountMap) { seen = seen || new Map() } while ((job = queue.shift())) { + if (job === null) { + continue + } if (__DEV__) { checkRecursiveUpdates(seen!, job) } From cfadb98011e188114bb822ee6f678cd09ddac7e3 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Feb 2020 13:15:36 -0500 Subject: [PATCH 0146/5381] fix(runtime-core): rework vnode hooks handling - peroperly support directive on components (e.g. ) - consistently invoke raw vnode hooks on component vnodes (fix #684) --- .../runtime-core/__tests__/directives.spec.ts | 170 ++++++++++++++++-- packages/runtime-core/src/component.ts | 2 + packages/runtime-core/src/componentProps.ts | 22 ++- .../runtime-core/src/componentRenderUtils.ts | 36 +++- 4 files changed, 204 insertions(+), 26 deletions(-) diff --git a/packages/runtime-core/__tests__/directives.spec.ts b/packages/runtime-core/__tests__/directives.spec.ts index e8e64bb78ec..bfd6e439a46 100644 --- a/packages/runtime-core/__tests__/directives.spec.ts +++ b/packages/runtime-core/__tests__/directives.spec.ts @@ -98,6 +98,15 @@ describe('directives', () => { expect(prevVNode).toBe(null) }) as DirectiveHook) + const dir = { + beforeMount, + mounted, + beforeUpdate, + updated, + beforeUnmount, + unmounted + } + let _instance: ComponentInternalInstance | null = null let _vnode: VNode | null = null let _prevVnode: VNode | null = null @@ -109,14 +118,7 @@ describe('directives', () => { _prevVnode = _vnode _vnode = withDirectives(h('div', count.value), [ [ - { - beforeMount, - mounted, - beforeUpdate, - updated, - beforeUnmount, - unmounted - }, + dir, // value count.value, // argument @@ -132,17 +134,17 @@ describe('directives', () => { const root = nodeOps.createElement('div') render(h(Comp), root) - expect(beforeMount).toHaveBeenCalled() - expect(mounted).toHaveBeenCalled() + expect(beforeMount).toHaveBeenCalledTimes(1) + expect(mounted).toHaveBeenCalledTimes(1) count.value++ await nextTick() - expect(beforeUpdate).toHaveBeenCalled() - expect(updated).toHaveBeenCalled() + expect(beforeUpdate).toHaveBeenCalledTimes(1) + expect(updated).toHaveBeenCalledTimes(1) render(null, root) - expect(beforeUnmount).toHaveBeenCalled() - expect(unmounted).toHaveBeenCalled() + expect(beforeUnmount).toHaveBeenCalledTimes(1) + expect(unmounted).toHaveBeenCalledTimes(1) }) it('should work with a function directive', async () => { @@ -198,4 +200,144 @@ describe('directives', () => { await nextTick() expect(fn).toHaveBeenCalledTimes(2) }) + + it('should work on component vnode', async () => { + const count = ref(0) + + function assertBindings(binding: DirectiveBinding) { + expect(binding.value).toBe(count.value) + expect(binding.arg).toBe('foo') + expect(binding.instance).toBe(_instance && _instance.proxy) + expect(binding.modifiers && binding.modifiers.ok).toBe(true) + } + + const beforeMount = jest.fn(((el, binding, vnode, prevVNode) => { + expect(el.tag).toBe('div') + // should not be inserted yet + expect(el.parentNode).toBe(null) + expect(root.children.length).toBe(0) + + assertBindings(binding) + + expect(vnode.type).toBe(_vnode!.type) + expect(prevVNode).toBe(null) + }) as DirectiveHook) + + const mounted = jest.fn(((el, binding, vnode, prevVNode) => { + expect(el.tag).toBe('div') + // should be inserted now + expect(el.parentNode).toBe(root) + expect(root.children[0]).toBe(el) + + assertBindings(binding) + + expect(vnode.type).toBe(_vnode!.type) + expect(prevVNode).toBe(null) + }) as DirectiveHook) + + const beforeUpdate = jest.fn(((el, binding, vnode, prevVNode) => { + expect(el.tag).toBe('div') + expect(el.parentNode).toBe(root) + expect(root.children[0]).toBe(el) + + // node should not have been updated yet + // expect(el.children[0].text).toBe(`${count.value - 1}`) + + assertBindings(binding) + + expect(vnode.type).toBe(_vnode!.type) + expect(prevVNode!.type).toBe(_prevVnode!.type) + }) as DirectiveHook) + + const updated = jest.fn(((el, binding, vnode, prevVNode) => { + expect(el.tag).toBe('div') + expect(el.parentNode).toBe(root) + expect(root.children[0]).toBe(el) + + // node should have been updated + expect(el.children[0].text).toBe(`${count.value}`) + + assertBindings(binding) + + expect(vnode.type).toBe(_vnode!.type) + expect(prevVNode!.type).toBe(_prevVnode!.type) + }) as DirectiveHook) + + const beforeUnmount = jest.fn(((el, binding, vnode, prevVNode) => { + expect(el.tag).toBe('div') + // should be removed now + expect(el.parentNode).toBe(root) + expect(root.children[0]).toBe(el) + + assertBindings(binding) + + expect(vnode.type).toBe(_vnode!.type) + expect(prevVNode).toBe(null) + }) as DirectiveHook) + + const unmounted = jest.fn(((el, binding, vnode, prevVNode) => { + expect(el.tag).toBe('div') + // should have been removed + expect(el.parentNode).toBe(null) + expect(root.children.length).toBe(0) + + assertBindings(binding) + + expect(vnode.type).toBe(_vnode!.type) + expect(prevVNode).toBe(null) + }) as DirectiveHook) + + const dir = { + beforeMount, + mounted, + beforeUpdate, + updated, + beforeUnmount, + unmounted + } + + let _instance: ComponentInternalInstance | null = null + let _vnode: VNode | null = null + let _prevVnode: VNode | null = null + + const Child = (props: { count: number }) => { + _prevVnode = _vnode + _vnode = h('div', props.count) + return _vnode + } + + const Comp = { + setup() { + _instance = currentInstance + }, + render() { + return withDirectives(h(Child, { count: count.value }), [ + [ + dir, + // value + count.value, + // argument + 'foo', + // modifiers + { ok: true } + ] + ]) + } + } + + const root = nodeOps.createElement('div') + render(h(Comp), root) + + expect(beforeMount).toHaveBeenCalledTimes(1) + expect(mounted).toHaveBeenCalledTimes(1) + + count.value++ + await nextTick() + expect(beforeUpdate).toHaveBeenCalledTimes(1) + expect(updated).toHaveBeenCalledTimes(1) + + render(null, root) + expect(beforeUnmount).toHaveBeenCalledTimes(1) + expect(unmounted).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 3081ecad264..f7b12400fc1 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -113,6 +113,7 @@ export interface ComponentInternalInstance { data: Data props: Data attrs: Data + vnodeHooks: Data slots: Slots proxy: ComponentPublicInstance | null // alternative proxy used only for runtime-compiled render functions using @@ -186,6 +187,7 @@ export function createComponentInstance( data: EMPTY_OBJ, props: EMPTY_OBJ, attrs: EMPTY_OBJ, + vnodeHooks: EMPTY_OBJ, slots: EMPTY_OBJ, refs: EMPTY_OBJ, diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index baad88fd30c..a0d1b8046b1 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -11,7 +11,8 @@ import { hasOwn, toRawType, PatchFlags, - makeMap + makeMap, + isReservedProp } from '@vue/shared' import { warn } from './warning' import { Data, ComponentInternalInstance } from './component' @@ -104,7 +105,8 @@ export function resolveProps( const { 0: options, 1: needCastKeys } = normalizePropsOptions(_options)! const props: Data = {} - let attrs: Data | undefined = void 0 + let attrs: Data | undefined = undefined + let vnodeHooks: Data | undefined = undefined // update the instance propsProxy (passed to setup()) to trigger potential // changes @@ -123,21 +125,28 @@ export function resolveProps( if (rawProps != null) { for (const key in rawProps) { + const value = rawProps[key] // key, ref are reserved and never passed down - if (key === 'key' || key === 'ref') continue + if (isReservedProp(key)) { + if (key !== 'key' && key !== 'ref') { + // vnode hooks. + ;(vnodeHooks || (vnodeHooks = {}))[key] = value + } + continue + } // prop option names are camelized during normalization, so to support // kebab -> camel conversion here we need to camelize the key. if (hasDeclaredProps) { const camelKey = camelize(key) if (hasOwn(options, camelKey)) { - setProp(camelKey, rawProps[key]) + setProp(camelKey, value) } else { // Any non-declared props are put into a separate `attrs` object // for spreading. Make sure to preserve original key casing - ;(attrs || (attrs = {}))[key] = rawProps[key] + ;(attrs || (attrs = {}))[key] = value } } else { - setProp(key, rawProps[key]) + setProp(key, value) } } } @@ -206,6 +215,7 @@ export function resolveProps( instance.props = props instance.attrs = options ? attrs || EMPTY_OBJ : props + instance.vnodeHooks = vnodeHooks || EMPTY_OBJ } const normalizationMap = new WeakMap< diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index eb26c1d9359..33a3f57cd22 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -46,6 +46,7 @@ export function renderComponentRoot( props, slots, attrs, + vnodeHooks, emit } = instance @@ -92,14 +93,23 @@ export function renderComponentRoot( } } + // inherit vnode hooks + if (vnodeHooks !== EMPTY_OBJ) { + result = cloneVNode(result, vnodeHooks) + } + // inherit directives + if (vnode.dirs != null) { + if (__DEV__ && !isElementRoot(result)) { + warn( + `Runtime directive used on component with non-element root node. ` + + `The directives will not function as intended.` + ) + } + result.dirs = vnode.dirs + } // inherit transition data if (vnode.transition != null) { - if ( - __DEV__ && - !(result.shapeFlag & ShapeFlags.COMPONENT) && - !(result.shapeFlag & ShapeFlags.ELEMENT) && - result.type !== Comment - ) { + if (__DEV__ && !isElementRoot(result)) { warn( `Component inside renders non-element root node ` + `that cannot be animated.` @@ -115,6 +125,14 @@ export function renderComponentRoot( return result } +function isElementRoot(vnode: VNode) { + return ( + vnode.shapeFlag & ShapeFlags.COMPONENT || + vnode.shapeFlag & ShapeFlags.ELEMENT || + vnode.type === Comment // potential v-if branch switch + ) +} + export function shouldUpdateComponent( prevVNode: VNode, nextVNode: VNode, @@ -137,6 +155,11 @@ export function shouldUpdateComponent( return true } + // force child update on runtime directive usage on component vnode. + if (nextVNode.dirs != null) { + return true + } + if (patchFlag > 0) { if (patchFlag & PatchFlags.DYNAMIC_SLOTS) { // slot content that references values that might have changed, @@ -174,6 +197,7 @@ export function shouldUpdateComponent( } return hasPropsChanged(prevProps, nextProps) } + return false } From 6d10a6c77242aec98103f15d6cb672ba63c18abf Mon Sep 17 00:00:00 2001 From: Dmitry Sharshakov Date: Mon, 10 Feb 2020 22:37:35 +0300 Subject: [PATCH 0147/5381] feat(server-renderer): support on-the-fly template compilation (#707) --- .../__tests__/renderToString.spec.ts | 107 +++++++++++++++++- packages/server-renderer/package.json | 3 + .../server-renderer/src/renderToString.ts | 54 ++++++++- 3 files changed, 157 insertions(+), 7 deletions(-) diff --git a/packages/server-renderer/__tests__/renderToString.spec.ts b/packages/server-renderer/__tests__/renderToString.spec.ts index c7a7cfb980c..051f59b4f03 100644 --- a/packages/server-renderer/__tests__/renderToString.spec.ts +++ b/packages/server-renderer/__tests__/renderToString.spec.ts @@ -6,10 +6,12 @@ import { resolveComponent, ComponentOptions } from 'vue' -import { escapeHtml } from '@vue/shared' +import { escapeHtml, mockWarn } from '@vue/shared' import { renderToString, renderComponent } from '../src/renderToString' import { ssrRenderSlot } from '../src/helpers/ssrRenderSlot' +mockWarn() + describe('ssr: renderToString', () => { test('should apply app context', async () => { const app = createApp({ @@ -56,6 +58,31 @@ describe('ssr: renderToString', () => { ).toBe(`
hello
`) }) + describe('template components', () => { + test('render', async () => { + expect( + await renderToString( + createApp({ + data() { + return { msg: 'hello' } + }, + template: `
{{ msg }}
` + }) + ) + ).toBe(`
hello
`) + }) + + test('handle compiler errors', async () => { + await renderToString(createApp({ template: `<` })) + + expect( + '[Vue warn]: Template compilation error: Unexpected EOF in tag.\n' + + '1 | <\n' + + ' | ^' + ).toHaveBeenWarned() + }) + }) + test('nested vnode components', async () => { const Child = { props: ['msg'], @@ -96,7 +123,22 @@ describe('ssr: renderToString', () => { ).toBe(`
parent
hello
`) }) - test('mixing optimized / vnode components', async () => { + test('nested template components', async () => { + const Child = { + props: ['msg'], + template: `
{{ msg }}
` + } + const app = createApp({ + template: `
parent
` + }) + app.component('Child', Child) + + expect(await renderToString(app)).toBe( + `
parent
hello
` + ) + }) + + test('mixing optimized / vnode / template components', async () => { const OptimizedChild = { props: ['msg'], ssrRender(ctx: any, push: any) { @@ -111,6 +153,11 @@ describe('ssr: renderToString', () => { } } + const TemplateChild = { + props: ['msg'], + template: `
{{ msg }}
` + } + expect( await renderToString( createApp({ @@ -120,11 +167,21 @@ describe('ssr: renderToString', () => { renderComponent(OptimizedChild, { msg: 'opt' }, null, parent) ) push(renderComponent(VNodeChild, { msg: 'vnode' }, null, parent)) + push( + renderComponent( + TemplateChild, + { msg: 'template' }, + null, + parent + ) + ) push(`
`) } }) ) - ).toBe(`
parent
opt
vnode
`) + ).toBe( + `
parent
opt
vnode
template
` + ) }) test('nested components with optimized slots', async () => { @@ -236,6 +293,50 @@ describe('ssr: renderToString', () => { ) }) + test('nested components with template slots', async () => { + const Child = { + props: ['msg'], + template: `
` + } + + const app = createApp({ + template: `
parent{{ msg }}
` + }) + app.component('Child', Child) + + expect(await renderToString(app)).toBe( + `
parent
` + + `from slot` + + `
` + ) + }) + + test('nested render fn components with template slots', async () => { + const Child = { + props: ['msg'], + render(this: any) { + return h( + 'div', + { + class: 'child' + }, + this.$slots.default({ msg: 'from slot' }) + ) + } + } + + const app = createApp({ + template: `
parent{{ msg }}
` + }) + app.component('Child', Child) + + expect(await renderToString(app)).toBe( + `
parent
` + + `from slot` + + `
` + ) + }) + test('async components', async () => { const Child = { // should wait for resovled render context from setup() diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index b8b47c549fd..2d30373e0b4 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -28,5 +28,8 @@ "homepage": "https://github.com/vuejs/vue/tree/dev/packages/server-renderer#readme", "peerDependencies": { "vue": "3.0.0-alpha.4" + }, + "dependencies": { + "@vue/compiler-ssr": "3.0.0-alpha.4" } } diff --git a/packages/server-renderer/src/renderToString.ts b/packages/server-renderer/src/renderToString.ts index 1b0eff4cc3f..074d98b0423 100644 --- a/packages/server-renderer/src/renderToString.ts +++ b/packages/server-renderer/src/renderToString.ts @@ -11,7 +11,8 @@ import { Portal, ShapeFlags, ssrUtils, - Slots + Slots, + warn } from 'vue' import { isString, @@ -19,10 +20,14 @@ import { isArray, isFunction, isVoidTag, - escapeHtml + escapeHtml, + NO, + generateCodeFrame } from '@vue/shared' +import { compile } from '@vue/compiler-ssr' import { ssrRenderAttrs } from './helpers/ssrRenderAttrs' import { SSRSlots } from './helpers/ssrRenderSlot' +import { CompilerError } from '@vue/compiler-dom' const { isVNode, @@ -126,6 +131,44 @@ function renderComponentVNode( } } +type SSRRenderFunction = ( + ctx: any, + push: (item: any) => void, + parentInstance: ComponentInternalInstance +) => void +const compileCache: Record = Object.create(null) + +function ssrCompile( + template: string, + instance: ComponentInternalInstance +): SSRRenderFunction { + const cached = compileCache[template] + if (cached) { + return cached + } + + const { code } = compile(template, { + isCustomElement: instance.appContext.config.isCustomElement || NO, + isNativeTag: instance.appContext.config.isNativeTag || NO, + onError(err: CompilerError) { + if (__DEV__) { + const message = `Template compilation error: ${err.message}` + const codeFrame = + err.loc && + generateCodeFrame( + template as string, + err.loc.start.offset, + err.loc.end.offset + ) + warn(codeFrame ? `${message}\n${codeFrame}` : message) + } else { + throw err + } + } + }) + return (compileCache[template] = Function(code)()) +} + function renderComponentSubTree( instance: ComponentInternalInstance ): ResolvedSSRBuffer | Promise { @@ -134,6 +177,10 @@ function renderComponentSubTree( if (isFunction(comp)) { renderVNode(push, renderComponentRoot(instance), instance) } else { + if (!comp.ssrRender && !comp.render && isString(comp.template)) { + comp.ssrRender = ssrCompile(comp.template, instance) + } + if (comp.ssrRender) { // optimized // set current rendering instance for asset resolution @@ -143,11 +190,10 @@ function renderComponentSubTree( } else if (comp.render) { renderVNode(push, renderComponentRoot(instance), instance) } else { - // TODO on the fly template compilation support throw new Error( `Component ${ comp.name ? `${comp.name} ` : `` - } is missing render function.` + } is missing template or render function.` ) } } From ade07c64a1f98c0958e80db0458c699c21998f64 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Feb 2020 16:49:37 -0500 Subject: [PATCH 0148/5381] fix(compiler-core): fix keep-alive when used in templates fix #715 --- .../transforms/transformElement.spec.ts | 28 ++++++++----- .../src/transforms/transformElement.ts | 42 ++++++++++++------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index dc581f0f09d..048a5693e60 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -346,18 +346,26 @@ describe('compiler: element transform', () => { test('should handle ', () => { function assert(tag: string) { - const { root, node } = parseWithElementTransform( - `<${tag}>` - ) + const root = parse(`
<${tag}>
`) + transform(root, { + nodeTransforms: [transformElement, transformText] + }) expect(root.components.length).toBe(0) expect(root.helpers).toContain(KEEP_ALIVE) - expect(node.callee).toBe(CREATE_VNODE) - expect(node.arguments).toMatchObject([ - KEEP_ALIVE, - `null`, - // keep-alive should not compile content to slots - [{ type: NodeTypes.ELEMENT, tag: 'span' }] - ]) + const node = (root.children[0] as any).children[0].codegenNode + expect(node.type).toBe(NodeTypes.JS_SEQUENCE_EXPRESSION) + expect(node.expressions[1]).toMatchObject({ + type: NodeTypes.JS_CALL_EXPRESSION, + callee: CREATE_BLOCK, // should be forced into a block + arguments: [ + KEEP_ALIVE, + `null`, + // keep-alive should not compile content to slots + [{ type: NodeTypes.ELEMENT, tag: 'span' }], + // should get a dynamic slots flag to force updates + genFlagText(PatchFlags.DYNAMIC_SLOTS) + ] + }) } assert(`keep-alive`) diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 1d685dce59b..f12f2204938 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -67,7 +67,7 @@ export const transformElement: NodeTransform = (node, context) => { // updates inside get proper isSVG flag at runtime. (#639, #643) // This is technically web-specific, but splitting the logic out of core // leads to too much unnecessary complexity. - const shouldUseBlock = + let shouldUseBlock = !isComponent && (tag === 'svg' || tag === 'foreignObject') const nodeType = isComponent @@ -101,21 +101,35 @@ export const transformElement: NodeTransform = (node, context) => { args.push(`null`) } - if (__DEV__ && nodeType === KEEP_ALIVE && node.children.length > 1) { - context.onError( - createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, { - start: node.children[0].loc.start, - end: node.children[node.children.length - 1].loc.end, - source: '' - }) - ) + if (nodeType === KEEP_ALIVE) { + // Although a built-in component, we compile KeepAlive with raw children + // instead of slot functions so that it can be used inside Transition + // or other Transition-wrapping HOCs. + // To ensure correct updates with block optimizations, we need to: + // 1. Force keep-alive into a block. This avoids its children being + // collected by a parent block. + shouldUseBlock = true + // 2. Force keep-alive to always be updated, since it uses raw children. + patchFlag |= PatchFlags.DYNAMIC_SLOTS + if (__DEV__ && node.children.length > 1) { + context.onError( + createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, { + start: node.children[0].loc.start, + end: node.children[node.children.length - 1].loc.end, + source: '' + }) + ) + } } - // Portal & KeepAlive should have normal children instead of slots - // Portal is not a real component has dedicated handling in the renderer - // KeepAlive should not track its own deps so that it can be used inside - // Transition - if (isComponent && nodeType !== PORTAL && nodeType !== KEEP_ALIVE) { + const shouldBuildAsSlots = + isComponent && + // Portal is not a real component has dedicated handling in the renderer + nodeType !== PORTAL && + // explained above. + nodeType !== KEEP_ALIVE + + if (shouldBuildAsSlots) { const { slots, hasDynamicSlots } = buildSlots(node, context) args.push(slots) if (hasDynamicSlots) { From 47e984d31f08f009a477712e2e82b991a0c046de Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Feb 2020 17:29:12 -0500 Subject: [PATCH 0149/5381] refactor(compiler): provide _ctx and _cache via arguments --- .../__snapshots__/codegen.spec.ts.snap | 53 +++++++------------ .../__snapshots__/compile.spec.ts.snap | 8 ++- .../__snapshots__/scopeId.spec.ts.snap | 18 +++---- .../compiler-core/__tests__/codegen.spec.ts | 10 +--- .../compiler-core/__tests__/scopeId.spec.ts | 4 +- .../__snapshots__/hoistStatic.spec.ts.snap | 46 ++++++++-------- .../__snapshots__/transformText.spec.ts.snap | 15 +++--- .../__snapshots__/vFor.spec.ts.snap | 24 ++++----- .../transforms/__snapshots__/vIf.spec.ts.snap | 16 +++--- .../__snapshots__/vModel.spec.ts.snap | 17 +++--- .../__snapshots__/vOnce.spec.ts.snap | 15 ++---- .../__snapshots__/vSlot.spec.ts.snap | 27 ++++------ packages/compiler-core/src/codegen.ts | 13 +---- .../__snapshots__/index.spec.ts.snap | 2 +- .../__snapshots__/vModel.spec.ts.snap | 24 ++++----- .../__snapshots__/vShow.spec.ts.snap | 2 +- .../compileTemplate.spec.ts.snap | 2 +- .../templateTransformAssetUrl.spec.ts.snap | 9 ++-- .../templateTransformSrcset.spec.ts.snap | 3 +- .../__tests__/compileTemplate.spec.ts | 2 +- .../runtime-core/src/componentRenderUtils.ts | 7 ++- 21 files changed, 129 insertions(+), 188 deletions(-) diff --git a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap index d38ec84dae9..8adf793ee7e 100644 --- a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap @@ -2,7 +2,7 @@ exports[`compiler: codegen ArrayExpression 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return [ foo, @@ -14,18 +14,14 @@ return function render() { exports[`compiler: codegen CacheExpression 1`] = ` " -export function render() { - const _ctx = this - const _cache = _ctx.$cache +export function render(_ctx, _cache) { return _cache[1] || (_cache[1] = foo) }" `; exports[`compiler: codegen CacheExpression w/ isVNode: true 1`] = ` " -export function render() { - const _ctx = this - const _cache = _ctx.$cache +export function render(_ctx, _cache) { return _cache[1] || ( _setBlockTracking(-1), _cache[1] = foo, @@ -37,7 +33,7 @@ export function render() { exports[`compiler: codegen ConditionalExpression 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return ok ? foo() @@ -50,7 +46,7 @@ return function render() { exports[`compiler: codegen Element (callExpression + objectExpression + TemplateChildNode[]) 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return _createVNode(\\"div\\", { id: \\"foo\\", @@ -65,7 +61,7 @@ return function render() { exports[`compiler: codegen SequenceExpression 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return (foo, bar(baz)) } @@ -74,7 +70,7 @@ return function render() { exports[`compiler: codegen assets + temps 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { const _component_Foo = _resolveComponent(\\"Foo\\") const _component_bar_baz = _resolveComponent(\\"bar-baz\\") @@ -90,7 +86,7 @@ return function render() { exports[`compiler: codegen comment 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return _createCommentVNode(\\"foo\\") } @@ -99,7 +95,7 @@ return function render() { exports[`compiler: codegen compound expression 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return _ctx.foo + _toDisplayString(bar) + nested } @@ -108,7 +104,7 @@ return function render() { exports[`compiler: codegen forNode 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return (foo, bar) } @@ -118,7 +114,7 @@ return function render() { exports[`compiler: codegen function mode preamble 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, resolveDirective: _resolveDirective } = _Vue @@ -130,8 +126,7 @@ return function render() { exports[`compiler: codegen function mode preamble w/ prefixIdentifiers: true 1`] = ` "const { createVNode: _createVNode, resolveDirective: _resolveDirective } = Vue -return function render() { - const _ctx = this +return function render(_ctx, _cache) { return null }" `; @@ -141,7 +136,7 @@ exports[`compiler: codegen hoists 1`] = ` const _hoisted_1 = hello const _hoisted_2 = { id: \\"foo\\" } -return function render() { +return function render(_ctx, _cache) { with (this) { return null } @@ -150,7 +145,7 @@ return function render() { exports[`compiler: codegen ifNode 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return (foo, bar) } @@ -159,7 +154,7 @@ return function render() { exports[`compiler: codegen interpolation 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return _toDisplayString(hello) } @@ -169,8 +164,7 @@ return function render() { exports[`compiler: codegen module mode preamble 1`] = ` "import { createVNode as _createVNode, resolveDirective as _resolveDirective } from \\"vue\\" -export function render() { - const _ctx = this +export function render(_ctx, _cache) { return null }" `; @@ -181,23 +175,14 @@ exports[`compiler: codegen module mode preamble w/ optimizeBindings: true 1`] = // Binding optimization for webpack code-split const _createVNode = createVNode, _resolveDirective = resolveDirective -export function render() { - const _ctx = this - return null -}" -`; - -exports[`compiler: codegen prefixIdentifiers: true should inject _ctx statement 1`] = ` -" -return function render() { - const _ctx = this +export function render(_ctx, _cache) { return null }" `; exports[`compiler: codegen static text 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { return \\"hello\\" } @@ -206,7 +191,7 @@ return function render() { exports[`compiler: codegen temps 1`] = ` " -return function render() { +return function render(_ctx, _cache) { with (this) { let _temp0, _temp1, _temp2 diff --git a/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap index 5b51457ac16..21168dc096a 100644 --- a/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap @@ -3,7 +3,7 @@ exports[`compiler: integration tests function mode 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { toDisplayString: _toDisplayString, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment, renderList: _renderList, createTextVNode: _createTextVNode } = _Vue @@ -28,8 +28,7 @@ return function render() { exports[`compiler: integration tests function mode w/ prefixIdentifiers: true 1`] = ` "const { toDisplayString: _toDisplayString, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment, renderList: _renderList, createTextVNode: _createTextVNode } = Vue -return function render() { - const _ctx = this +return function render(_ctx, _cache) { return (_openBlock(), _createBlock(\\"div\\", { id: \\"foo\\", class: _ctx.bar.baz @@ -50,8 +49,7 @@ return function render() { exports[`compiler: integration tests module mode 1`] = ` "import { toDisplayString as _toDisplayString, createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, Fragment as _Fragment, renderList as _renderList, createTextVNode as _createTextVNode } from \\"vue\\" -export function render() { - const _ctx = this +export function render(_ctx, _cache) { return (_openBlock(), _createBlock(\\"div\\", { id: \\"foo\\", class: _ctx.bar.baz diff --git a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap index d5e7e571e2a..6193c0acdf6 100644 --- a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`scopeId compiler support should push scopeId for hoisted nodes 1`] = ` -"import { createVNode as _createVNode, createBlock as _createBlock, openBlock as _openBlock, withScopeId as _withScopeId, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \\"vue\\" +"import { createVNode as _createVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, createBlock as _createBlock, openBlock as _openBlock, withScopeId as _withScopeId, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \\"vue\\" const _withId = _withScopeId(\\"test\\") _pushScopeId(\\"test\\") @@ -9,10 +9,10 @@ const _hoisted_1 = _createVNode(\\"div\\", null, \\"hello\\") const _hoisted_2 = _createVNode(\\"div\\", null, \\"world\\") _popScopeId() -export const render = _withId(function render() { - const _ctx = this +export const render = _withId(function render(_ctx, _cache) { return (_openBlock(), _createBlock(\\"div\\", null, [ _hoisted_1, + _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */), _hoisted_2 ])) })" @@ -22,8 +22,7 @@ exports[`scopeId compiler support should wrap default slot 1`] = ` "import { createVNode as _createVNode, resolveComponent as _resolveComponent, createBlock as _createBlock, openBlock as _openBlock, withScopeId as _withScopeId } from \\"vue\\" const _withId = _withScopeId(\\"test\\") -export const render = _withId(function render() { - const _ctx = this +export const render = _withId(function render(_ctx, _cache) { const _component_Child = _resolveComponent(\\"Child\\") return (_openBlock(), _createBlock(_component_Child, null, { @@ -39,8 +38,7 @@ exports[`scopeId compiler support should wrap dynamic slots 1`] = ` "import { createVNode as _createVNode, resolveComponent as _resolveComponent, renderList as _renderList, createSlots as _createSlots, createBlock as _createBlock, openBlock as _openBlock, withScopeId as _withScopeId } from \\"vue\\" const _withId = _withScopeId(\\"test\\") -export const render = _withId(function render() { - const _ctx = this +export const render = _withId(function render(_ctx, _cache) { const _component_Child = _resolveComponent(\\"Child\\") return (_openBlock(), _createBlock(_component_Child, null, _createSlots({ _compiled: true }, [ @@ -68,8 +66,7 @@ exports[`scopeId compiler support should wrap named slots 1`] = ` "import { toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, createVNode as _createVNode, resolveComponent as _resolveComponent, createBlock as _createBlock, openBlock as _openBlock, withScopeId as _withScopeId } from \\"vue\\" const _withId = _withScopeId(\\"test\\") -export const render = _withId(function render() { - const _ctx = this +export const render = _withId(function render(_ctx, _cache) { const _component_Child = _resolveComponent(\\"Child\\") return (_openBlock(), _createBlock(_component_Child, null, { @@ -88,8 +85,7 @@ exports[`scopeId compiler support should wrap render function 1`] = ` "import { createVNode as _createVNode, createBlock as _createBlock, openBlock as _openBlock, withScopeId as _withScopeId } from \\"vue\\" const _withId = _withScopeId(\\"test\\") -export const render = _withId(function render() { - const _ctx = this +export const render = _withId(function render(_ctx, _cache) { return (_openBlock(), _createBlock(\\"div\\")) })" `; diff --git a/packages/compiler-core/__tests__/codegen.spec.ts b/packages/compiler-core/__tests__/codegen.spec.ts index 04e6b017bcd..02add36a59e 100644 --- a/packages/compiler-core/__tests__/codegen.spec.ts +++ b/packages/compiler-core/__tests__/codegen.spec.ts @@ -183,12 +183,6 @@ describe('compiler: codegen', () => { expect(code).toMatchSnapshot() }) - test('prefixIdentifiers: true should inject _ctx statement', () => { - const { code } = generate(createRoot(), { prefixIdentifiers: true }) - expect(code).toMatch(`const _ctx = this\n`) - expect(code).toMatchSnapshot() - }) - test('static text', () => { const { code } = generate( createRoot({ @@ -422,7 +416,6 @@ describe('compiler: codegen', () => { prefixIdentifiers: true } ) - expect(code).toMatch(`const _cache = _ctx.$cache`) expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`) expect(code).toMatchSnapshot() }) @@ -442,7 +435,6 @@ describe('compiler: codegen', () => { prefixIdentifiers: true } ) - expect(code).toMatch(`const _cache = _ctx.$cache`) expect(code).toMatch( ` _cache[1] || ( @@ -596,7 +588,7 @@ describe('compiler: codegen', () => { ) expect(code).toMatchInlineSnapshot(` " - return function render() { + return function render(_ctx, _cache) { with (this) { return foo = bar } diff --git a/packages/compiler-core/__tests__/scopeId.spec.ts b/packages/compiler-core/__tests__/scopeId.spec.ts index 4991ab3497a..f009b87a0b1 100644 --- a/packages/compiler-core/__tests__/scopeId.spec.ts +++ b/packages/compiler-core/__tests__/scopeId.spec.ts @@ -19,7 +19,7 @@ describe('scopeId compiler support', () => { }) expect(ast.helpers).toContain(WITH_SCOPE_ID) expect(code).toMatch(`const _withId = _withScopeId("test")`) - expect(code).toMatch(`export const render = _withId(function render() {`) + expect(code).toMatch(`export const render = _withId(function render(`) expect(code).toMatchSnapshot() }) @@ -68,7 +68,7 @@ describe('scopeId compiler support', () => { test('should push scopeId for hoisted nodes', () => { const { ast, code } = baseCompile( - `
hello
world
`, + `
hello
{{ foo }}
world
`, { mode: 'module', scopeId: 'test', diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap index 5a472c56217..0b355441d6d 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap @@ -6,7 +6,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = _createVNode(\\"div\\", { key: \\"foo\\" }) -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -26,7 +26,7 @@ const _hoisted_1 = _createVNode(\\"p\\", null, [ _createVNode(\\"span\\") ]) -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -45,7 +45,7 @@ const _hoisted_1 = _createVNode(\\"div\\", null, [ _createCommentVNode(\\"comment\\") ]) -return function render() { +return function render(_ctx, _cache) { with (this) { const { createCommentVNode: _createCommentVNode, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -63,7 +63,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = _createVNode(\\"span\\") const _hoisted_2 = _createVNode(\\"div\\") -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -81,7 +81,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = _createVNode(\\"span\\", { class: \\"inline\\" }, \\"hello\\") -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -98,7 +98,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = { id: \\"foo\\" } -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, withDirectives: _withDirectives, resolveDirective: _resolveDirective, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -119,7 +119,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = { id: \\"foo\\" } -return function render() { +return function render(_ctx, _cache) { with (this) { const { toDisplayString: _toDisplayString, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -136,7 +136,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = { id: \\"foo\\" } -return function render() { +return function render(_ctx, _cache) { with (this) { const { resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -157,7 +157,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = { class: { foo: true } } -return function render() { +return function render(_ctx, _cache) { with (this) { const { toDisplayString: _toDisplayString, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -179,7 +179,7 @@ const _hoisted_1 = _createVNode(\\"span\\", null, [ _toDisplayString(true) ]) -return function render() { +return function render(_ctx, _cache) { with (this) { const { toDisplayString: _toDisplayString, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -196,7 +196,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = _createVNode(\\"span\\", { foo: 0 }, _toDisplayString(1)) -return function render() { +return function render(_ctx, _cache) { with (this) { const { toDisplayString: _toDisplayString, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -210,9 +210,7 @@ return function render() { exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist elements with cached handlers 1`] = ` "import { createVNode as _createVNode, createBlock as _createBlock, openBlock as _openBlock } from \\"vue\\" -export function render() { - const _ctx = this - const _cache = _ctx.$cache +export function render(_ctx, _cache) { return (_openBlock(), _createBlock(\\"div\\", null, [ _createVNode(\\"div\\", null, [ _createVNode(\\"div\\", { @@ -226,7 +224,7 @@ export function render() { exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that refer scope variables (2) 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, toDisplayString: _toDisplayString, createVNode: _createVNode } = _Vue @@ -244,7 +242,7 @@ return function render() { exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that refer scope variables (v-slot) 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -261,7 +259,7 @@ return function render() { exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that refer scope variables 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, toDisplayString: _toDisplayString, createVNode: _createVNode } = _Vue @@ -279,7 +277,7 @@ return function render() { exports[`compiler: hoistStatic transform should NOT hoist components 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -295,7 +293,7 @@ return function render() { exports[`compiler: hoistStatic transform should NOT hoist element with dynamic key 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -309,7 +307,7 @@ return function render() { exports[`compiler: hoistStatic transform should NOT hoist element with dynamic props 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -323,7 +321,7 @@ return function render() { exports[`compiler: hoistStatic transform should NOT hoist element with dynamic ref 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -337,7 +335,7 @@ return function render() { exports[`compiler: hoistStatic transform should NOT hoist root node 1`] = ` "const _Vue = Vue -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue @@ -353,7 +351,7 @@ const { createVNode: _createVNode } = _Vue const _hoisted_1 = { id: \\"foo\\" } const _hoisted_2 = _createVNode(\\"span\\") -return function render() { +return function render(_ctx, _cache) { with (this) { const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue @@ -378,7 +376,7 @@ const _hoisted_1 = { } const _hoisted_2 = _createVNode(\\"span\\") -return function render() { +return function render(_ctx, _cache) { with (this) { const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = _Vue diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/transformText.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/transformText.spec.ts.snap index 227ac7df60b..8c133b21938 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/transformText.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/transformText.spec.ts.snap @@ -3,7 +3,7 @@ exports[`compiler: transform text