Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: vuejs/core
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.0.4
Choose a base ref
...
head repository: vuejs/core
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.0.5
Choose a head ref

Commits on Dec 3, 2020

  1. Copy the full SHA
    3f8f9b6 View commit details
  2. Copy the full SHA
    ad4d391 View commit details
  3. refactor: cache constant check result on transform context

    also fix edge case for missed createVNode import on static svg nodes
    yyx990803 committed Dec 3, 2020
    Copy the full SHA
    a835250 View commit details
  4. fix(runtime-core): skip patchBlockChildren if n1.dynamicChildren is n…

    …ull (#2717)
    
    fix #2715 
    
    The bug was introduced by #2485 where a compiled slot may result in a bailed Fragment
    which then gets its dynamicChildren set to `null` by the renderer.
    edison1105 authored Dec 3, 2020
    13
    Copy the full SHA
    c59897c View commit details
  5. Copy the full SHA
    df48fc2 View commit details
  6. Copy the full SHA
    3016b81 View commit details
  7. Copy the full SHA
    cbaa380 View commit details

Commits on Dec 4, 2020

  1. build(deps-dev): bump rollup from 2.34.0 to 2.34.1 (#2723)

    Bumps [rollup](https://github.com/rollup/rollup) from 2.34.0 to 2.34.1.
    - [Release notes](https://github.com/rollup/rollup/releases)
    - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
    - [Commits](rollup/rollup@v2.34.0...v2.34.1)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    
    Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
    dependabot-preview[bot] authored Dec 4, 2020
    Copy the full SHA
    0af8c8d View commit details
  2. Copy the full SHA
    6684c63 View commit details
  3. Copy the full SHA
    47b3652 View commit details
  4. Copy the full SHA
    d2d27b2 View commit details
  5. Copy the full SHA
    338d869 View commit details
  6. Copy the full SHA
    b2189ba View commit details
  7. Copy the full SHA
    82bf7eb View commit details
  8. Copy the full SHA
    3867bb4 View commit details
  9. Copy the full SHA
    db786b1 View commit details
  10. Copy the full SHA
    5b9b37f View commit details
  11. Copy the full SHA
    dbe22ba View commit details

Commits on Dec 7, 2020

  1. Copy the full SHA
    28672c9 View commit details
  2. Copy the full SHA
    84c281f View commit details
  3. Copy the full SHA
    0f8e639 View commit details
  4. Copy the full SHA
    8936e53 View commit details

Commits on Dec 8, 2020

  1. Copy the full SHA
    82e0969 View commit details
  2. Copy the full SHA
    d87bc2b View commit details

Commits on Dec 9, 2020

  1. Copy the full SHA
    fff36d5 View commit details
  2. Copy the full SHA
    18897c4 View commit details

Commits on Dec 11, 2020

  1. Copy the full SHA
    e0d570c View commit details
  2. Copy the full SHA
    1f0437e View commit details
  3. Copy the full SHA
    07559e5 View commit details

Commits on Dec 14, 2020

  1. Copy the full SHA
    ab0a605 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    170079b View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3ca7336 View commit details

Commits on Dec 15, 2020

  1. Copy the full SHA
    b951bf3 View commit details
  2. Copy the full SHA
    d9187cd View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f3cebe0 View commit details

Commits on Dec 16, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b81d279 View commit details

Commits on Dec 18, 2020

  1. feat(devtools): send instance

    Akryum committed Dec 18, 2020
    2

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3626ff0 View commit details

Commits on Dec 21, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    92d7ad1 View commit details

Commits on Dec 22, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f67d280 View commit details

Commits on Dec 24, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0a6105f View commit details

Commits on Dec 28, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ce0eca8 View commit details

Commits on Dec 29, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e5a5a2c View commit details

Commits on Dec 30, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    670ec4d View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    02493a4 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    88f6b33 View commit details
  4. test(ssr): refactor ssr render tests

    Merge renderToString and renderToStream to run the same tests
    yyx990803 committed Dec 30, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8ad1aab View commit details
  5. ci: remove ls-lint usage

    yyx990803 committed Dec 30, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    addea2c View commit details
  6. release: v3.0.5

    yyx990803 committed Dec 30, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5a5d037 View commit details
Showing with 1,440 additions and 1,795 deletions.
  1. +0 −1 .circleci/config.yml
  2. +1 −1 .github/workflows/size-check.yml
  3. +0 −7 .ls-lint.yml
  4. +22 −0 CHANGELOG.md
  5. +2 −4 package.json
  6. +15 −0 packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap
  7. +49 −1 packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts
  8. +2 −2 packages/compiler-core/package.json
  9. +9 −16 packages/compiler-core/src/parse.ts
  10. +2 −0 packages/compiler-core/src/transform.ts
  11. +23 −26 packages/compiler-core/src/transforms/hoistStatic.ts
  12. +2 −2 packages/compiler-core/src/transforms/transformElement.ts
  13. +1 −1 packages/compiler-core/src/transforms/transformText.ts
  14. +4 −1 packages/compiler-core/src/transforms/vFor.ts
  15. +3 −3 packages/compiler-dom/package.json
  16. +32 −0 packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap
  17. +7 −2 packages/compiler-sfc/__tests__/parse.spec.ts
  18. +32 −0 packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts
  19. +6 −6 packages/compiler-sfc/package.json
  20. +1 −1 packages/compiler-sfc/src/parse.ts
  21. +9 −4 packages/compiler-sfc/src/templateTransformAssetUrl.ts
  22. +1 −1 packages/compiler-sfc/src/templateUtils.ts
  23. +3 −3 packages/compiler-ssr/package.json
  24. +2 −2 packages/reactivity/package.json
  25. +3 −3 packages/runtime-core/package.json
  26. +16 −5 packages/runtime-core/src/apiWatch.ts
  27. +9 −3 packages/runtime-core/src/component.ts
  28. +36 −3 packages/runtime-core/src/componentOptions.ts
  29. +4 −8 packages/runtime-core/src/components/KeepAlive.ts
  30. +2 −1 packages/runtime-core/src/devtools.ts
  31. +3 −4 packages/runtime-core/src/helpers/resolveAssets.ts
  32. +10 −3 packages/runtime-core/src/renderer.ts
  33. +3 −3 packages/runtime-dom/package.json
  34. +10 −11 packages/runtime-dom/src/components/Transition.ts
  35. +2 −6 packages/runtime-dom/src/components/TransitionGroup.ts
  36. +22 −7 packages/runtime-dom/src/index.ts
  37. +3 −3 packages/runtime-test/package.json
  38. +719 −0 packages/server-renderer/__tests__/render.spec.ts
  39. +0 −622 packages/server-renderer/__tests__/renderToStream.spec.ts
  40. +0 −621 packages/server-renderer/__tests__/renderToString.spec.ts
  41. +4 −4 packages/server-renderer/package.json
  42. +30 −2 packages/server-renderer/src/helpers/ssrRenderSlot.ts
  43. +1 −1 packages/shared/package.json
  44. +1 −1 packages/shared/src/patchFlags.ts
  45. +1 −1 packages/size-check/package.json
  46. +1 −1 packages/template-explorer/package.json
  47. +103 −103 packages/vue/__tests__/Transition.spec.ts
  48. +22 −23 packages/vue/__tests__/TransitionGroup.spec.ts
  49. +1 −1 packages/vue/__tests__/index.spec.ts
  50. +4 −4 packages/vue/package.json
  51. +18 −2 scripts/build.js
  52. +36 −0 test-dts/defineComponent.test-d.tsx
  53. +18 −4 test-dts/watch.test-d.ts
  54. +130 −261 yarn.lock
1 change: 0 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -33,7 +33,6 @@ jobs:
- *restore_cache
- *install_deps
- *save_cache
- run: yarn ls-lint
- run: yarn test --ci

test-dts:
2 changes: 1 addition & 1 deletion .github/workflows/size-check.yml
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v1
- uses: bahmutov/npm-install@v1

- uses: posva/size-check-action@v1.1.0
- uses: posva/size-check-action@v1.1.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: size
7 changes: 0 additions & 7 deletions .ls-lint.yml

This file was deleted.

22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
## [3.0.5](https://github.com/vuejs/vue-next/compare/v3.0.4...v3.0.5) (2020-12-30)


### Bug Fixes

* **compiler-core:** fix missing createVNode import on nested v-for ([ad4d391](https://github.com/vuejs/vue-next/commit/ad4d3915d39515a3e9ff2de691f82cb922a314b9)), closes [#2718](https://github.com/vuejs/vue-next/issues/2718)
* **compiler-sfc:** should keep template nodes with no content ([#2468](https://github.com/vuejs/vue-next/issues/2468)) ([5b9b37f](https://github.com/vuejs/vue-next/commit/5b9b37fc9b363be2989c1e9d76ab6e950cdfe2ad)), closes [#2463](https://github.com/vuejs/vue-next/issues/2463)
* **compiler-sfc:** support transforming asset urls with full base url. ([#2477](https://github.com/vuejs/vue-next/issues/2477)) ([db786b1](https://github.com/vuejs/vue-next/commit/db786b1afe41c26611a215e6d6599d50312b9c2f))
* **runtime-core:** component mount anchor memory leak ([#2459](https://github.com/vuejs/vue-next/issues/2459)) ([3867bb4](https://github.com/vuejs/vue-next/commit/3867bb4c14131ef94098a62bffba97a5b7d1fe66)), closes [#2458](https://github.com/vuejs/vue-next/issues/2458)
* **runtime-core:** skip patchBlockChildren if n1.dynamicChildren is null ([#2717](https://github.com/vuejs/vue-next/issues/2717)) ([c59897c](https://github.com/vuejs/vue-next/commit/c59897c7b0dbd82b5bbf3fbca945c0639ac37fb8)), closes [#2715](https://github.com/vuejs/vue-next/issues/2715) [#2485](https://github.com/vuejs/vue-next/issues/2485)
* **runtime-dom:** support mounting app on ShadowRoot ([#2447](https://github.com/vuejs/vue-next/issues/2447)) ([b2189ba](https://github.com/vuejs/vue-next/commit/b2189ba2f3400ab6bf9ee75b56ac11e65f7bd061)), closes [#2399](https://github.com/vuejs/vue-next/issues/2399)
* **ssr:** properly handle ssr empty slot and fallback ([88f6b33](https://github.com/vuejs/vue-next/commit/88f6b33d054c18802375ec99c4a57e4acc649a02))
* **transition:** ensure manual style manipulation in transition leave hooks work ([cbaa380](https://github.com/vuejs/vue-next/commit/cbaa3805064cb581fc2007cf63774c91d39844fe)), closes [#2720](https://github.com/vuejs/vue-next/issues/2720)
* **transition:** ensure styles from *-leave-active trigger transition ([#2716](https://github.com/vuejs/vue-next/issues/2716)) ([3f8f9b6](https://github.com/vuejs/vue-next/commit/3f8f9b67b3b54a7ae8405baf6d28be7ec074509d)), closes [#2712](https://github.com/vuejs/vue-next/issues/2712)


### Features

* **devtools:** send instance ([3626ff0](https://github.com/vuejs/vue-next/commit/3626ff07fe5107080c52e85018070562c84b796e))



## [3.0.4](https://github.com/vuejs/vue-next/compare/v3.0.3...v3.0.4) (2020-12-02)


6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"private": true,
"version": "3.0.4",
"version": "3.0.5",
"workspaces": [
"packages/*"
],
@@ -10,7 +10,6 @@
"size": "node scripts/build.js vue runtime-dom size-check -p -f global",
"lint": "eslint --ext .ts packages/*/src/**",
"format": "prettier --write --parser typescript \"packages/**/*.ts?(x)\"",
"ls-lint": "ls-lint",
"test": "node scripts/build.js vue -f global -d && jest --runInBand",
"test-dts": "node scripts/build.js shared reactivity runtime-core runtime-dom -dt -f esm-bundler && yarn test-dts-only",
"test-dts-only": "tsc -p ./test-dts/tsconfig.json && tsc -p ./test-dts/tsconfig.build.json",
@@ -26,7 +25,7 @@
"directory": "test-dts"
},
"gitHooks": {
"pre-commit": "ls-lint && lint-staged",
"pre-commit": "lint-staged",
"commit-msg": "node scripts/verifyCommit.js"
},
"lint-staged": {
@@ -43,7 +42,6 @@
},
"devDependencies": {
"@babel/types": "^7.12.0",
"@ls-lint/ls-lint": "^1.9.2",
"@microsoft/api-extractor": "^7.9.15",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.0.0",
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`compiler: expression transform bindingMetadata inline mode 1`] = `
"(_ctx, _cache) => {
return (_openBlock(), _createBlock(\\"div\\", null, _toDisplayString(__props.props) + \\" \\" + _toDisplayString(_unref(setup)) + \\" \\" + _toDisplayString(setupConst) + \\" \\" + _toDisplayString(_ctx.data) + \\" \\" + _toDisplayString(_ctx.options), 1 /* TEXT */))
}"
`;

exports[`compiler: expression transform bindingMetadata non-inline mode 1`] = `
"const { toDisplayString: _toDisplayString, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock(\\"div\\", null, _toDisplayString($props.props) + \\" \\" + _toDisplayString($setup.setup) + \\" \\" + _toDisplayString($data.data) + \\" \\" + _toDisplayString($options.options), 1 /* TEXT */))
}"
`;
Original file line number Diff line number Diff line change
@@ -6,7 +6,9 @@ import {
NodeTypes,
CompilerOptions,
InterpolationNode,
ConstantTypes
ConstantTypes,
BindingTypes,
baseCompile
} from '../../src'
import { transformIf } from '../../src/transforms/vIf'
import { transformExpression } from '../../src/transforms/transformExpression'
@@ -457,4 +459,50 @@ describe('compiler: expression transform', () => {
})
})
})

describe('bindingMetadata', () => {
const bindingMetadata = {
props: BindingTypes.PROPS,
setup: BindingTypes.SETUP_MAYBE_REF,
setupConst: BindingTypes.SETUP_CONST,
data: BindingTypes.DATA,
options: BindingTypes.OPTIONS
}

function compileWithBindingMetadata(
template: string,
options?: CompilerOptions
) {
return baseCompile(template, {
prefixIdentifiers: true,
bindingMetadata,
...options
})
}

test('non-inline mode', () => {
const { code } = compileWithBindingMetadata(
`<div>{{ props }} {{ setup }} {{ data }} {{ options }}</div>`
)
expect(code).toMatch(`$props.props`)
expect(code).toMatch(`$setup.setup`)
expect(code).toMatch(`$data.data`)
expect(code).toMatch(`$options.options`)
expect(code).toMatch(`_ctx, _cache, $props, $setup, $data, $options`)
expect(code).toMatchSnapshot()
})

test('inline mode', () => {
const { code } = compileWithBindingMetadata(
`<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }}</div>`,
{ inline: true }
)
expect(code).toMatch(`__props.props`)
expect(code).toMatch(`_unref(setup)`)
expect(code).toMatch(`_toDisplayString(setupConst)`)
expect(code).toMatch(`_ctx.data`)
expect(code).toMatch(`_ctx.options`)
expect(code).toMatchSnapshot()
})
})
})
4 changes: 2 additions & 2 deletions packages/compiler-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",
@@ -31,7 +31,7 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-core#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/shared": "3.0.5",
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"estree-walker": "^2.0.1",
25 changes: 9 additions & 16 deletions packages/compiler-core/src/parse.ts
Original file line number Diff line number Diff line change
@@ -29,6 +29,13 @@ import {
type OptionalOptions = 'isNativeTag' | 'isBuiltInComponent'
type MergedParserOptions = Omit<Required<ParserOptions>, OptionalOptions> &
Pick<ParserOptions, OptionalOptions>
type AttributeValue =
| {
content: string
isQuoted: boolean
loc: SourceLocation
}
| undefined

// The default decoder only provides escapes for characters reserved as part of
// the template syntax, and is only used if the custom renderer did not provide
@@ -590,13 +597,7 @@ function parseAttribute(
advanceBy(context, name.length)

// Value
let value:
| {
content: string
isQuoted: boolean
loc: SourceLocation
}
| undefined = undefined
let value: AttributeValue = undefined

if (/^[\t\r\n\f ]*=/.test(context.source)) {
advanceSpaces(context)
@@ -702,15 +703,7 @@ function parseAttribute(
}
}

function parseAttributeValue(
context: ParserContext
):
| {
content: string
isQuoted: boolean
loc: SourceLocation
}
| undefined {
function parseAttributeValue(context: ParserContext): AttributeValue {
const start = getCursor(context)
let content: string

2 changes: 2 additions & 0 deletions packages/compiler-core/src/transform.ts
Original file line number Diff line number Diff line change
@@ -111,6 +111,7 @@ export interface TransformContext
removeIdentifiers(exp: ExpressionNode | string): void
hoist(exp: JSChildNode): SimpleExpressionNode
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
constantCache: Map<TemplateChildNode, ConstantTypes>
}

export function createTransformContext(
@@ -163,6 +164,7 @@ export function createTransformContext(
directives: new Set(),
hoists: [],
imports: new Set(),
constantCache: new Map(),
temps: 0,
cached: 0,
identifiers: Object.create(null),
49 changes: 23 additions & 26 deletions packages/compiler-core/src/transforms/hoistStatic.ts
Original file line number Diff line number Diff line change
@@ -14,12 +14,12 @@ import {
import { TransformContext } from '../transform'
import { PatchFlags, isString, isSymbol } from '@vue/shared'
import { isSlotOutlet } from '../utils'
import { CREATE_VNODE } from '../runtimeHelpers'

export function hoistStatic(root: RootNode, context: TransformContext) {
walk(
root,
context,
new Map(),
// Root node is unfortunately non-hoistable due to potential parent
// fallthrough attributes.
isSingleElementRoot(root, root.children[0])
@@ -41,7 +41,6 @@ export function isSingleElementRoot(
function walk(
node: ParentNode,
context: TransformContext,
resultCache: Map<TemplateChildNode, ConstantTypes>,
doNotHoistNode: boolean = false
) {
let hasHoistedNode = false
@@ -65,7 +64,7 @@ function walk(
) {
const constantType = doNotHoistNode
? ConstantTypes.NOT_CONSTANT
: getConstantType(child, resultCache)
: getConstantType(child, context)
if (constantType > ConstantTypes.NOT_CONSTANT) {
if (constantType < ConstantTypes.CAN_STRINGIFY) {
canStringify = false
@@ -87,7 +86,7 @@ function walk(
(!flag ||
flag === PatchFlags.NEED_PATCH ||
flag === PatchFlags.TEXT) &&
getGeneratedPropsConstantType(child, resultCache) >=
getGeneratedPropsConstantType(child, context) >=
ConstantTypes.CAN_HOIST
) {
const props = getNodeProps(child)
@@ -98,7 +97,7 @@ function walk(
}
}
} else if (child.type === NodeTypes.TEXT_CALL) {
const contentType = getConstantType(child.content, resultCache)
const contentType = getConstantType(child.content, context)
if (contentType > 0) {
if (contentType < ConstantTypes.CAN_STRINGIFY) {
canStringify = false
@@ -112,17 +111,16 @@ function walk(

// walk further
if (child.type === NodeTypes.ELEMENT) {
walk(child, context, resultCache)
walk(child, context)
} else if (child.type === NodeTypes.FOR) {
// Do not hoist v-for single child because it has to be a block
walk(child, context, resultCache, child.children.length === 1)
walk(child, context, child.children.length === 1)
} else if (child.type === NodeTypes.IF) {
for (let i = 0; i < child.branches.length; i++) {
// Do not hoist v-if single child because it has to be a block
walk(
child.branches[i],
context,
resultCache,
child.branches[i].children.length === 1
)
}
@@ -136,14 +134,15 @@ function walk(

export function getConstantType(
node: TemplateChildNode | SimpleExpressionNode,
resultCache: Map<TemplateChildNode, ConstantTypes> = new Map()
context: TransformContext
): ConstantTypes {
const { constantCache } = context
switch (node.type) {
case NodeTypes.ELEMENT:
if (node.tagType !== ElementTypes.ELEMENT) {
return ConstantTypes.NOT_CONSTANT
}
const cached = resultCache.get(node)
const cached = constantCache.get(node)
if (cached !== undefined) {
return cached
}
@@ -161,12 +160,9 @@ export function getConstantType(
// non-hoistable expressions that refers to scope variables, e.g. compiler
// injected keys or cached event handlers. Therefore we need to always
// check the codegenNode's props to be sure.
const generatedPropsType = getGeneratedPropsConstantType(
node,
resultCache
)
const generatedPropsType = getGeneratedPropsConstantType(node, context)
if (generatedPropsType === ConstantTypes.NOT_CONSTANT) {
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
return ConstantTypes.NOT_CONSTANT
}
if (generatedPropsType < returnType) {
@@ -175,9 +171,9 @@ export function getConstantType(

// 2. its children.
for (let i = 0; i < node.children.length; i++) {
const childType = getConstantType(node.children[i], resultCache)
const childType = getConstantType(node.children[i], context)
if (childType === ConstantTypes.NOT_CONSTANT) {
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
return ConstantTypes.NOT_CONSTANT
}
if (childType < returnType) {
@@ -193,9 +189,9 @@ export function getConstantType(
for (let i = 0; i < node.props.length; i++) {
const p = node.props[i]
if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind' && p.exp) {
const expType = getConstantType(p.exp, resultCache)
const expType = getConstantType(p.exp, context)
if (expType === ConstantTypes.NOT_CONSTANT) {
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
return ConstantTypes.NOT_CONSTANT
}
if (expType < returnType) {
@@ -210,12 +206,13 @@ export function getConstantType(
// nested updates.
if (codegenNode.isBlock) {
codegenNode.isBlock = false
context.helper(CREATE_VNODE)
}

resultCache.set(node, returnType)
constantCache.set(node, returnType)
return returnType
} else {
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
constantCache.set(node, ConstantTypes.NOT_CONSTANT)
return ConstantTypes.NOT_CONSTANT
}
case NodeTypes.TEXT:
@@ -227,7 +224,7 @@ export function getConstantType(
return ConstantTypes.NOT_CONSTANT
case NodeTypes.INTERPOLATION:
case NodeTypes.TEXT_CALL:
return getConstantType(node.content, resultCache)
return getConstantType(node.content, context)
case NodeTypes.SIMPLE_EXPRESSION:
return node.constType
case NodeTypes.COMPOUND_EXPRESSION:
@@ -237,7 +234,7 @@ export function getConstantType(
if (isString(child) || isSymbol(child)) {
continue
}
const childType = getConstantType(child, resultCache)
const childType = getConstantType(child, context)
if (childType === ConstantTypes.NOT_CONSTANT) {
return ConstantTypes.NOT_CONSTANT
} else if (childType < returnType) {
@@ -256,15 +253,15 @@ export function getConstantType(

function getGeneratedPropsConstantType(
node: PlainElementNode,
resultCache: Map<TemplateChildNode, ConstantTypes>
context: TransformContext
): ConstantTypes {
let returnType = ConstantTypes.CAN_STRINGIFY
const props = getNodeProps(node)
if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
const { properties } = props
for (let i = 0; i < properties.length; i++) {
const { key, value } = properties[i]
const keyType = getConstantType(key, resultCache)
const keyType = getConstantType(key, context)
if (keyType === ConstantTypes.NOT_CONSTANT) {
return keyType
}
@@ -274,7 +271,7 @@ function getGeneratedPropsConstantType(
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
return ConstantTypes.NOT_CONSTANT
}
const valueType = getConstantType(value, resultCache)
const valueType = getConstantType(value, context)
if (valueType === ConstantTypes.NOT_CONSTANT) {
return valueType
}
4 changes: 2 additions & 2 deletions packages/compiler-core/src/transforms/transformElement.ts
Original file line number Diff line number Diff line change
@@ -168,7 +168,7 @@ export const transformElement: NodeTransform = (node, context) => {
type === NodeTypes.COMPOUND_EXPRESSION
if (
hasDynamicTextChild &&
getConstantType(child) === ConstantTypes.NOT_CONSTANT
getConstantType(child, context) === ConstantTypes.NOT_CONSTANT
) {
patchFlag |= PatchFlags.TEXT
}
@@ -373,7 +373,7 @@ export function buildProps(
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
getConstantType(value) > 0)
getConstantType(value, context) > 0)
) {
// skip if the prop is a cached handler or has constant value
return
2 changes: 1 addition & 1 deletion packages/compiler-core/src/transforms/transformText.ts
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ export const transformText: NodeTransform = (node, context) => {
// mark dynamic text with flag so it gets patched inside a block
if (
!context.ssr &&
getConstantType(child) === ConstantTypes.NOT_CONSTANT
getConstantType(child, context) === ConstantTypes.NOT_CONSTANT
) {
callArgs.push(
PatchFlags.TEXT +
5 changes: 4 additions & 1 deletion packages/compiler-core/src/transforms/vFor.ts
Original file line number Diff line number Diff line change
@@ -37,7 +37,8 @@ import {
RENDER_LIST,
OPEN_BLOCK,
CREATE_BLOCK,
FRAGMENT
FRAGMENT,
CREATE_VNODE
} from '../runtimeHelpers'
import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression'
@@ -168,6 +169,8 @@ export const transformFor = createStructuralDirectiveTransform(
if (childBlock.isBlock) {
helper(OPEN_BLOCK)
helper(CREATE_BLOCK)
} else {
helper(CREATE_VNODE)
}
}

6 changes: 3 additions & 3 deletions packages/compiler-dom/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",
@@ -36,7 +36,7 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-dom#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/compiler-core": "3.0.4"
"@vue/shared": "3.0.5",
"@vue/compiler-core": "3.0.5"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`compiler sfc: transform asset url should allow for full base URLs, with paths 1`] = `
"import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(\\"img\\", { src: \\"http://localhost:3000/src/logo.png\\" }))
}"
`;

exports[`compiler sfc: transform asset url should allow for full base URLs, without paths 1`] = `
"import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(\\"img\\", { src: \\"http://localhost:3000/logo.png\\" }))
}"
`;

exports[`compiler sfc: transform asset url should allow for full base URLs, without port 1`] = `
"import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(\\"img\\", { src: \\"http://localhost/logo.png\\" }))
}"
`;

exports[`compiler sfc: transform asset url should allow for full base URLs, without protocol 1`] = `
"import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(\\"img\\", { src: \\"//localhost/logo.png\\" }))
}"
`;

exports[`compiler sfc: transform asset url support uri fragment 1`] = `
"import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
import _imports_0 from '@svg/file.svg'
9 changes: 7 additions & 2 deletions packages/compiler-sfc/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
@@ -111,8 +111,13 @@ h1 { color: red }
)
})

test('should ignore nodes with no content', () => {
expect(parse(`<template/>`).descriptor.template).toBe(null)
test('should keep template nodes with no content', () => {
const { descriptor } = parse(`<template/>`)
expect(descriptor.template).toBeTruthy()
expect(descriptor.template!.content).toBeFalsy()
})

test('should ignore other nodes with no content', () => {
expect(parse(`<script/>`).descriptor.script).toBe(null)
expect(parse(`<style/>`).descriptor.styles.length).toBe(0)
expect(parse(`<custom/>`).descriptor.customBlocks.length).toBe(0)
32 changes: 32 additions & 0 deletions packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts
Original file line number Diff line number Diff line change
@@ -94,4 +94,36 @@ describe('compiler sfc: transform asset url', () => {
// should not remove it
expect(code).toMatch(`"xlink:href": "#myCircle"`)
})

test('should allow for full base URLs, with paths', () => {
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
base: 'http://localhost:3000/src/'
})

expect(code).toMatchSnapshot()
})

test('should allow for full base URLs, without paths', () => {
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
base: 'http://localhost:3000'
})

expect(code).toMatchSnapshot()
})

test('should allow for full base URLs, without port', () => {
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
base: 'http://localhost'
})

expect(code).toMatchSnapshot()
})

test('should allow for full base URLs, without protocol', () => {
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
base: '//localhost'
})

expect(code).toMatchSnapshot()
})
})
12 changes: 6 additions & 6 deletions packages/compiler-sfc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-sfc",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"types": "dist/compiler-sfc.d.ts",
@@ -31,15 +31,15 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-sfc#readme",
"peerDependencies": {
"vue": "3.0.4"
"vue": "3.0.5"
},
"dependencies": {
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"@vue/compiler-core": "3.0.4",
"@vue/compiler-dom": "3.0.4",
"@vue/compiler-ssr": "3.0.4",
"@vue/shared": "3.0.4",
"@vue/compiler-core": "3.0.5",
"@vue/compiler-dom": "3.0.5",
"@vue/compiler-ssr": "3.0.5",
"@vue/shared": "3.0.5",
"consolidate": "^0.16.0",
"estree-walker": "^2.0.1",
"hash-sum": "^2.0.0",
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/parse.ts
Original file line number Diff line number Diff line change
@@ -138,7 +138,7 @@ export function parse(
if (node.type !== NodeTypes.ELEMENT) {
return
}
if (!node.children.length && !hasSrc(node)) {
if (!node.children.length && !hasSrc(node) && node.tag !== 'template') {
return
}
switch (node.tag) {
13 changes: 9 additions & 4 deletions packages/compiler-sfc/src/templateTransformAssetUrl.ts
Original file line number Diff line number Diff line change
@@ -121,12 +121,17 @@ export const transformAssetUrl: NodeTransform = (
attr.value.content[0] !== '@' &&
isRelativeUrl(attr.value.content)
) {
// Allow for full hostnames provided in options.base
const base = parseUrl(options.base)
const protocol = base.protocol || ''
const host = base.host ? protocol + '//' + base.host : ''
const basePath = base.path || '/'

// when packaged in the browser, path will be using the posix-
// only version provided by rollup-plugin-node-builtins.
attr.value.content = (path.posix || path).join(
options.base,
url.path + (url.hash || '')
)
attr.value.content =
host +
(path.posix || path).join(basePath, url.path + (url.hash || ''))
}
return
}
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/templateUtils.ts
Original file line number Diff line number Diff line change
@@ -35,5 +35,5 @@ export function parseUrl(url: string): UrlWithStringQuery {
function parseUriParts(urlString: string): UrlWithStringQuery {
// A TypeError is thrown if urlString is not a string
// @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost
return uriParse(isString(urlString) ? urlString : '')
return uriParse(isString(urlString) ? urlString : '', false, true)
}
6 changes: 3 additions & 3 deletions packages/compiler-ssr/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-ssr",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/compiler-ssr",
"main": "dist/compiler-ssr.cjs.js",
"types": "dist/compiler-ssr.d.ts",
@@ -28,7 +28,7 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-ssr#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/compiler-dom": "3.0.4"
"@vue/shared": "3.0.5",
"@vue/compiler-dom": "3.0.5"
}
}
4 changes: 2 additions & 2 deletions packages/reactivity/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/reactivity",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",
@@ -36,6 +36,6 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/reactivity#readme",
"dependencies": {
"@vue/shared": "3.0.4"
"@vue/shared": "3.0.5"
}
}
6 changes: 3 additions & 3 deletions packages/runtime-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-core",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/runtime-core",
"main": "index.js",
"module": "dist/runtime-core.esm-bundler.js",
@@ -32,7 +32,7 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-core#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/reactivity": "3.0.4"
"@vue/shared": "3.0.5",
"@vue/reactivity": "3.0.5"
}
}
21 changes: 16 additions & 5 deletions packages/runtime-core/src/apiWatch.ts
Original file line number Diff line number Diff line change
@@ -78,15 +78,26 @@ export function watchEffect(
// initial value for watchers to trigger on undefined initial values
const INITIAL_WATCHER_VALUE = {}

type MultiWatchSources = (WatchSource<unknown> | object)[]

// overload #1: array of multiple sources + cb
// 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<
T extends Readonly<Array<WatchSource<unknown> | object>>,
T extends MultiWatchSources,
Immediate extends Readonly<boolean> = false
>(
sources: T,
sources: [...T],
cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #2 for multiple sources w/ `as const`
// watch([foo, bar] as const, () => {})
// somehow [...T] breaks when the type is readonly
export function watch<
T extends Readonly<MultiWatchSources>,
Immediate extends Readonly<boolean> = false
>(
source: T,
cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
options?: WatchOptions<Immediate>
): WatchStopHandle
12 changes: 9 additions & 3 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
@@ -801,15 +801,21 @@ const classifyRE = /(?:^|[-_])(\w)/g
const classify = (str: string): string =>
str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '')

export function getComponentName(
Component: ConcreteComponent
): string | undefined {
return isFunction(Component)
? Component.displayName || Component.name
: Component.name
}

/* istanbul ignore next */
export function formatComponentName(
instance: ComponentInternalInstance | null,
Component: ConcreteComponent,
isRoot = false
): string {
let name = isFunction(Component)
? Component.displayName || Component.name
: Component.name
let name = getComponentName(Component)
if (!name && Component.__file) {
const match = Component.__file.match(/([^/\\]+)\.\w+$/)
if (match) {
39 changes: 36 additions & 3 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ import {
import { warn } from './warning'
import { VNodeChild } from './vnode'
import { callWithAsyncErrorHandling } from './errorHandling'
import { UnionToIntersection } from './helpers/typeUtils'

/**
* Interface for declaring custom options.
@@ -80,6 +81,19 @@ export interface ComponentCustomOptions {}

export type RenderFunction = () => VNodeChild

type ExtractOptionProp<T> = T extends ComponentOptionsBase<
infer P,
any,
any,
any,
any,
any,
any,
any
>
? unknown extends P ? {} : P
: {}

export interface ComponentOptionsBase<
Props,
RawBindings,
@@ -97,7 +111,9 @@ export interface ComponentOptionsBase<
ComponentCustomOptions {
setup?: (
this: void,
props: Props,
props: Props &
UnionToIntersection<ExtractOptionProp<Mixin>> &
UnionToIntersection<ExtractOptionProp<Extends>>,
ctx: SetupContext<E>
) => Promise<RawBindings> | RawBindings | RenderFunction | void
name?: string
@@ -358,8 +374,24 @@ interface LegacyOptions<
// since that leads to some sort of circular inference and breaks ThisType
// for the entire component.
data?: (
this: CreateComponentPublicInstance<Props>,
vm: CreateComponentPublicInstance<Props>
this: CreateComponentPublicInstance<
Props,
{},
{},
{},
MethodOptions,
Mixin,
Extends
>,
vm: CreateComponentPublicInstance<
Props,
{},
{},
{},
MethodOptions,
Mixin,
Extends
>
) => D
computed?: C
methods?: M
@@ -590,6 +622,7 @@ export function applyOptions(
deferredData.forEach(dataFn => resolveData(instance, dataFn, publicThis))
}
if (dataOptions) {
// @ts-ignore dataOptions is not fully type safe
resolveData(instance, dataOptions, publicThis)
}
if (__DEV__) {
12 changes: 4 additions & 8 deletions packages/runtime-core/src/components/KeepAlive.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {
ConcreteComponent,
getCurrentInstance,
FunctionalComponent,
SetupContext,
ComponentInternalInstance,
LifecycleHooks,
currentInstance
currentInstance,
getComponentName
} from '../component'
import { VNode, cloneVNode, isVNode, VNodeProps } from '../vnode'
import { warn } from '../warning'
@@ -151,7 +151,7 @@ const KeepAliveImpl = {

function pruneCache(filter?: (name: string) => boolean) {
cache.forEach((vnode, key) => {
const name = getName(vnode.type as ConcreteComponent)
const name = getComponentName(vnode.type as ConcreteComponent)
if (name && (!filter || !filter(name))) {
pruneCacheEntry(key)
}
@@ -235,7 +235,7 @@ const KeepAliveImpl = {

let vnode = getInnerChild(rawVNode)
const comp = vnode.type as ConcreteComponent
const name = getName(comp)
const name = getComponentName(comp)
const { include, exclude, max } = props

if (
@@ -301,10 +301,6 @@ export const KeepAlive = (KeepAliveImpl as any) as {
}
}

function getName(comp: ConcreteComponent): string | void {
return (comp as FunctionalComponent).displayName || comp.name
}

function matches(pattern: MatchPattern, name: string): boolean {
if (isArray(pattern)) {
return pattern.some((p: string | RegExp) => matches(p, name))
3 changes: 2 additions & 1 deletion packages/runtime-core/src/devtools.ts
Original file line number Diff line number Diff line change
@@ -67,7 +67,8 @@ function createDevtoolsComponentHook(hook: DevtoolsHooks) {
hook,
component.appContext.app,
component.uid,
component.parent ? component.parent.uid : undefined
component.parent ? component.parent.uid : undefined,
component
)
}
}
7 changes: 3 additions & 4 deletions packages/runtime-core/src/helpers/resolveAssets.ts
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ import { currentRenderingInstance } from '../componentRenderUtils'
import {
currentInstance,
ConcreteComponent,
FunctionalComponent,
ComponentOptions
ComponentOptions,
getComponentName
} from '../component'
import { Directive } from '../directives'
import { camelize, capitalize, isString } from '@vue/shared'
@@ -73,8 +73,7 @@ function resolveAsset(
return Component
}

const selfName =
(Component as FunctionalComponent).displayName || Component.name
const selfName = getComponentName(Component)
if (
selfName &&
(selfName === name ||
13 changes: 10 additions & 3 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
@@ -1139,12 +1139,15 @@ function baseCreateRenderer(
if (
patchFlag > 0 &&
patchFlag & PatchFlags.STABLE_FRAGMENT &&
dynamicChildren
dynamicChildren &&
// #2715 the previous fragment could've been a BAILed one as a result
// of renderSlot() with no valid children
n1.dynamicChildren
) {
// a stable fragment (template root or <template v-for>) doesn't need to
// patch children order, but it may contain dynamicChildren.
patchBlockChildren(
n1.dynamicChildren!,
n1.dynamicChildren,
dynamicChildren,
container,
parentComponent,
@@ -1392,8 +1395,9 @@ function baseCreateRenderer(
}
// onVnodeMounted
if ((vnodeHook = props && props.onVnodeMounted)) {
const scopedInitialVNode = initialVNode
queuePostRenderEffect(() => {
invokeVNodeHook(vnodeHook!, parent, initialVNode)
invokeVNodeHook(vnodeHook!, parent, scopedInitialVNode)
}, parentSuspense)
}
// activated hook for keep-alive roots.
@@ -1407,6 +1411,9 @@ function baseCreateRenderer(
queuePostRenderEffect(a, parentSuspense)
}
instance.isMounted = true

// #2458: deference mount-only object parameters to prevent memleaks
initialVNode = container = anchor = null as any
} else {
// updateComponent
// This is triggered by mutation of component's own state (next: null)
6 changes: 3 additions & 3 deletions packages/runtime-dom/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-dom",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/runtime-dom",
"main": "index.js",
"module": "dist/runtime-dom.esm-bundler.js",
@@ -35,8 +35,8 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-dom#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/runtime-core": "3.0.4",
"@vue/shared": "3.0.5",
"@vue/runtime-core": "3.0.5",
"csstype": "^2.6.8"
}
}
21 changes: 10 additions & 11 deletions packages/runtime-dom/src/components/Transition.ts
Original file line number Diff line number Diff line change
@@ -143,29 +143,23 @@ export function resolveTransitionProps(
return extend(baseProps, {
onBeforeEnter(el) {
onBeforeEnter && onBeforeEnter(el)
addTransitionClass(el, enterActiveClass)
addTransitionClass(el, enterFromClass)
addTransitionClass(el, enterActiveClass)
},
onBeforeAppear(el) {
onBeforeAppear && onBeforeAppear(el)
addTransitionClass(el, appearActiveClass)
addTransitionClass(el, appearFromClass)
addTransitionClass(el, appearActiveClass)
},
onEnter: makeEnterHook(false),
onAppear: makeEnterHook(true),
onLeave(el, done) {
const resolve = () => finishLeave(el, done)
addTransitionClass(el, leaveActiveClass)
addTransitionClass(el, leaveFromClass)
// ref #2531, #2593
// disabling the transition before nextFrame ensures styles from
// *-leave-from and *-enter-from classes are applied instantly before
// the transition starts. This is applied for enter transition as well
// so that it accounts for `visibility: hidden` cases.
const cachedTransition = (el as HTMLElement).style.transitionProperty
;(el as HTMLElement).style.transitionProperty = 'none'
// force reflow so *-leave-from classes immediately take effect (#2593)
forceReflow()
addTransitionClass(el, leaveActiveClass)
nextFrame(() => {
;(el as HTMLElement).style.transitionProperty = cachedTransition
removeTransitionClass(el, leaveFromClass)
addTransitionClass(el, leaveToClass)
if (!(onLeave && onLeave.length > 1)) {
@@ -366,3 +360,8 @@ function getTimeout(delays: string[], durations: string[]): number {
function toMs(s: string): number {
return Number(s.slice(0, -1).replace(',', '.')) * 1000
}

// synchronously force layout to put elements into a certain state
export function forceReflow() {
return document.body.offsetHeight
}
8 changes: 2 additions & 6 deletions packages/runtime-dom/src/components/TransitionGroup.ts
Original file line number Diff line number Diff line change
@@ -5,7 +5,8 @@ import {
ElementWithTransition,
getTransitionInfo,
resolveTransitionProps,
TransitionPropsValidators
TransitionPropsValidators,
forceReflow
} from './Transition'
import {
Fragment,
@@ -172,11 +173,6 @@ function applyTranslation(c: VNode): VNode | undefined {
}
}

// this is put in a dedicated function to avoid the line from being treeshaken
function forceReflow() {
return document.body.offsetHeight
}

function hasCSSTransform(
el: ElementWithTransition,
root: Node,
29 changes: 22 additions & 7 deletions packages/runtime-dom/src/index.ts
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ export const createApp = ((...args) => {
}

const { mount } = app
app.mount = (containerOrSelector: Element | string): any => {
app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
const container = normalizeContainer(containerOrSelector)
if (!container) return
const component = app._component
@@ -68,8 +68,10 @@ export const createApp = ((...args) => {
// clear content before mounting
container.innerHTML = ''
const proxy = mount(container)
container.removeAttribute('v-cloak')
container.setAttribute('data-v-app', '')
if (container instanceof Element) {
container.removeAttribute('v-cloak')
container.setAttribute('data-v-app', '')
}
return proxy
}

@@ -84,7 +86,7 @@ export const createSSRApp = ((...args) => {
}

const { mount } = app
app.mount = (containerOrSelector: Element | string): any => {
app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
const container = normalizeContainer(containerOrSelector)
if (container) {
return mount(container, true)
@@ -103,15 +105,28 @@ function injectNativeTagCheck(app: App) {
})
}

function normalizeContainer(container: Element | string): Element | null {
function normalizeContainer(
container: Element | ShadowRoot | string
): Element | null {
if (isString(container)) {
const res = document.querySelector(container)
if (__DEV__ && !res) {
warn(`Failed to mount app: mount target selector returned null.`)
warn(
`Failed to mount app: mount target selector "${container}" returned null.`
)
}
return res
}
return container
if (
__DEV__ &&
container instanceof ShadowRoot &&
container.mode === 'closed'
) {
warn(
`mounting on a ShadowRoot with \`{mode: "closed"}\` may lead to unpredictable bugs`
)
}
return container as any
}

// SFC CSS utilities
6 changes: 3 additions & 3 deletions packages/runtime-test/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/runtime-test",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/runtime-test",
"private": true,
"main": "index.js",
@@ -25,7 +25,7 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-test#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/runtime-core": "3.0.4"
"@vue/shared": "3.0.5",
"@vue/runtime-core": "3.0.5"
}
}
719 changes: 719 additions & 0 deletions packages/server-renderer/__tests__/render.spec.ts

Large diffs are not rendered by default.

622 changes: 0 additions & 622 deletions packages/server-renderer/__tests__/renderToStream.spec.ts

This file was deleted.

621 changes: 0 additions & 621 deletions packages/server-renderer/__tests__/renderToString.spec.ts

This file was deleted.

8 changes: 4 additions & 4 deletions packages/server-renderer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/server-renderer",
"version": "3.0.4",
"version": "3.0.5",
"description": "@vue/server-renderer",
"main": "index.js",
"types": "dist/server-renderer.d.ts",
@@ -28,10 +28,10 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/server-renderer#readme",
"peerDependencies": {
"vue": "3.0.4"
"vue": "3.0.5"
},
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/compiler-ssr": "3.0.4"
"@vue/shared": "3.0.5",
"@vue/compiler-ssr": "3.0.5"
}
}
32 changes: 30 additions & 2 deletions packages/server-renderer/src/helpers/ssrRenderSlot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ComponentInternalInstance, Slots } from 'vue'
import { Props, PushFn, renderVNodeChildren } from '../render'
import { Props, PushFn, renderVNodeChildren, SSRBufferItem } from '../render'

export type SSRSlots = Record<string, SSRSlot>
export type SSRSlot = (
@@ -22,18 +22,46 @@ export function ssrRenderSlot(
const slotFn = slots[slotName]
if (slotFn) {
const scopeId = parentComponent && parentComponent.type.__scopeId
const slotBuffer: SSRBufferItem[] = []
const bufferedPush = (item: SSRBufferItem) => {
slotBuffer.push(item)
}
const ret = slotFn(
slotProps,
push,
bufferedPush,
parentComponent,
scopeId ? ` ${scopeId}-s` : ``
)
if (Array.isArray(ret)) {
// normal slot
renderVNodeChildren(push, ret, parentComponent)
} else {
// ssr slot.
// check if the slot renders all comments, in which case use the fallback
let isEmptySlot = true
for (let i = 0; i < slotBuffer.length; i++) {
if (!isComment(slotBuffer[i])) {
isEmptySlot = false
break
}
}
if (isEmptySlot) {
if (fallbackRenderFn) {
fallbackRenderFn()
}
} else {
for (let i = 0; i < slotBuffer.length; i++) {
push(slotBuffer[i])
}
}
}
} else if (fallbackRenderFn) {
fallbackRenderFn()
}
push(`<!--]-->`)
}

const commentRE = /^<!--.*-->$/
function isComment(item: SSRBufferItem) {
return typeof item === 'string' && commentRE.test(item)
}
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/shared",
"version": "3.0.4",
"version": "3.0.5",
"description": "internal utils shared across @vue packages",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
2 changes: 1 addition & 1 deletion packages/shared/src/patchFlags.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
* if (flag & TEXT) { ... }
* ```
*
* Check the `patchElement` function in './renderer.ts' to see how the
* Check the `patchElement` function in '../../runtime-core/src/renderer.ts' to see how the
* flags are handled during diff.
*/
export const enum PatchFlags {
2 changes: 1 addition & 1 deletion packages/size-check/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/size-check",
"version": "3.0.4",
"version": "3.0.5",
"private": true,
"buildOptions": {
"name": "Vue",
2 changes: 1 addition & 1 deletion packages/template-explorer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/template-explorer",
"version": "3.0.4",
"version": "3.0.5",
"private": true,
"buildOptions": {
"formats": [
206 changes: 103 additions & 103 deletions packages/vue/__tests__/Transition.spec.ts

Large diffs are not rendered by default.

45 changes: 22 additions & 23 deletions packages/vue/__tests__/TransitionGroup.spec.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@ describe('e2e: TransitionGroup', () => {

const duration = 50
const buffer = 5
const transitionDisableProp = `style="transition-property: none;"`

const htmlWhenTransitionStart = () =>
page().evaluate(() => {
@@ -56,8 +55,8 @@ describe('e2e: TransitionGroup', () => {
`<div class="test">a</div>` +
`<div class="test">b</div>` +
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-from">d</div>` +
`<div class="test test-enter-active test-enter-from">e</div>`
`<div class="test test-enter-from test-enter-active">d</div>` +
`<div class="test test-enter-from test-enter-active">e</div>`
)
await nextFrame()
expect(await html('#container')).toBe(
@@ -107,15 +106,15 @@ describe('e2e: TransitionGroup', () => {
)

expect(await htmlWhenTransitionStart()).toBe(
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>a</div>` +
`<div class="test test-leave-from test-leave-active">a</div>` +
`<div class="test">b</div>` +
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>c</div>`
`<div class="test test-leave-from test-leave-active">c</div>`
)
await nextFrame()
expect(await html('#container')).toBe(
`<div class="test test-leave-active test-leave-to" style="">a</div>` +
`<div class="test test-leave-active test-leave-to">a</div>` +
`<div class="test">b</div>` +
`<div class="test test-leave-active test-leave-to" style="">c</div>`
`<div class="test test-leave-active test-leave-to">c</div>`
)
await transitionFinish()
expect(await html('#container')).toBe(`<div class="test">b</div>`)
@@ -151,14 +150,14 @@ describe('e2e: TransitionGroup', () => {
)

expect(await htmlWhenTransitionStart()).toBe(
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>a</div>` +
`<div class="test test-leave-from test-leave-active">a</div>` +
`<div class="test">b</div>` +
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-from">d</div>`
`<div class="test test-enter-from test-enter-active">d</div>`
)
await nextFrame()
expect(await html('#container')).toBe(
`<div class="test test-leave-active test-leave-to" style="">a</div>` +
`<div class="test test-leave-active test-leave-to">a</div>` +
`<div class="test">b</div>` +
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-to">d</div>`
@@ -203,9 +202,9 @@ describe('e2e: TransitionGroup', () => {
})
// appear
expect(appearHtml).toBe(
`<div class="test test-appear-active test-appear-from">a</div>` +
`<div class="test test-appear-active test-appear-from">b</div>` +
`<div class="test test-appear-active test-appear-from">c</div>`
`<div class="test test-appear-from test-appear-active">a</div>` +
`<div class="test test-appear-from test-appear-active">b</div>` +
`<div class="test test-appear-from test-appear-active">c</div>`
)
await nextFrame()
expect(await html('#container')).toBe(
@@ -225,8 +224,8 @@ describe('e2e: TransitionGroup', () => {
`<div class="test">a</div>` +
`<div class="test">b</div>` +
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-from">d</div>` +
`<div class="test test-enter-active test-enter-from">e</div>`
`<div class="test test-enter-from test-enter-active">d</div>` +
`<div class="test test-enter-from test-enter-active">e</div>`
)
await nextFrame()
expect(await html('#container')).toBe(
@@ -276,10 +275,10 @@ describe('e2e: TransitionGroup', () => {
)

expect(await htmlWhenTransitionStart()).toBe(
`<div class="test group-enter-active group-enter-from">d</div>` +
`<div class="test group-enter-from group-enter-active">d</div>` +
`<div class="test">b</div>` +
`<div class="test group-move" style="">a</div>` +
`<div class="test group-leave-active group-leave-from group-move" ${transitionDisableProp}>c</div>`
`<div class="test group-leave-from group-leave-active group-move" style="">c</div>`
)
await nextFrame()
expect(await html('#container')).toBe(
@@ -441,9 +440,9 @@ describe('e2e: TransitionGroup', () => {
expect(onAppearSpy).toBeCalled()
expect(afterAppearSpy).not.toBeCalled()
expect(appearHtml).toBe(
`<div class="test test-appear-active test-appear-from">a</div>` +
`<div class="test test-appear-active test-appear-from">b</div>` +
`<div class="test test-appear-active test-appear-from">c</div>`
`<div class="test test-appear-from test-appear-active">a</div>` +
`<div class="test test-appear-from test-appear-active">b</div>` +
`<div class="test test-appear-from test-appear-active">c</div>`
)
await nextFrame()
expect(afterAppearSpy).not.toBeCalled()
@@ -462,10 +461,10 @@ describe('e2e: TransitionGroup', () => {

// enter + leave
expect(await htmlWhenTransitionStart()).toBe(
`<div class="test test-leave-active test-leave-from" ${transitionDisableProp}>a</div>` +
`<div class="test test-leave-from test-leave-active">a</div>` +
`<div class="test">b</div>` +
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-from">d</div>`
`<div class="test test-enter-from test-enter-active">d</div>`
)
expect(beforeLeaveSpy).toBeCalled()
expect(onLeaveSpy).toBeCalled()
@@ -475,7 +474,7 @@ describe('e2e: TransitionGroup', () => {
expect(afterEnterSpy).not.toBeCalled()
await nextFrame()
expect(await html('#container')).toBe(
`<div class="test test-leave-active test-leave-to" style="">a</div>` +
`<div class="test test-leave-active test-leave-to">a</div>` +
`<div class="test">b</div>` +
`<div class="test">c</div>` +
`<div class="test test-enter-active test-enter-to">d</div>`
2 changes: 1 addition & 1 deletion packages/vue/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -205,7 +205,7 @@ describe('compiler + runtime integration', () => {
createApp(App).mount('#not-exist-id')

expect(
'[Vue warn]: Failed to mount app: mount target selector returned null.'
'[Vue warn]: Failed to mount app: mount target selector "#not-exist-id" returned null.'
).toHaveBeenWarned()
document.querySelector = origin
})
8 changes: 4 additions & 4 deletions packages/vue/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue",
"version": "3.0.4",
"version": "3.0.5",
"description": "vue",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",
@@ -37,9 +37,9 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/vue#readme",
"dependencies": {
"@vue/shared": "3.0.4",
"@vue/compiler-dom": "3.0.4",
"@vue/runtime-dom": "3.0.4"
"@vue/shared": "3.0.5",
"@vue/compiler-dom": "3.0.5",
"@vue/runtime-dom": "3.0.5"
},
"devDependencies": {
"lodash": "^4.17.15",
20 changes: 18 additions & 2 deletions scripts/build.js
Original file line number Diff line number Diff line change
@@ -50,9 +50,25 @@ async function run() {
}

async function buildAll(targets) {
for (const target of targets) {
await build(target)
await runParallel(require('os').cpus().length, targets, build)
}

async function runParallel(maxConcurrency, source, iteratorFn) {
const ret = []
const executing = []
for (const item of source) {
const p = Promise.resolve().then(() => iteratorFn(item, source))
ret.push(p)

if (maxConcurrency <= source.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
executing.push(e)
if (executing.length >= maxConcurrency) {
await Promise.race(executing)
}
}
}
return Promise.all(ret)
}

async function build(target) {
36 changes: 36 additions & 0 deletions test-dts/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
@@ -445,10 +445,18 @@ describe('with mixins', () => {
const MixinD = defineComponent({
mixins: [MixinA],
data() {
//@ts-expect-error computed are not available on data()
expectError<number>(this.dC1)
//@ts-expect-error computed are not available on data()
expectError<string>(this.dC2)

return {
d: 4
}
},
setup(props) {
expectType<string>(props.aP1)
},
computed: {
dC1(): number {
return this.d + this.a
@@ -467,6 +475,34 @@ describe('with mixins', () => {
required: true
}
},

data(vm) {
expectType<number>(vm.a)
expectType<number>(vm.b)
expectType<number>(vm.c)
expectType<number>(vm.d)

// should also expose declared props on `this`
expectType<number>(this.a)
expectType<string>(this.aP1)
expectType<boolean | undefined>(this.aP2)
expectType<number>(this.b)
expectType<any>(this.bP1)
expectType<number>(this.c)
expectType<number>(this.d)

return {}
},

setup(props) {
expectType<string>(props.z)
// props
expectType<string>(props.aP1)
expectType<boolean | undefined>(props.aP2)
expectType<any>(props.bP1)
expectType<any>(props.bP2)
expectType<string>(props.z)
},
render() {
const props = this.$props
// props
22 changes: 18 additions & 4 deletions test-dts/watch.test-d.ts
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ watch(source, (value, oldValue) => {
})

watch([source, source2, source3], (values, oldValues) => {
expectType<(string | number)[]>(values)
expectType<(string | number)[]>(oldValues)
expectType<[string, string, number]>(values)
expectType<[string, string, number]>(oldValues)
})

// const array
@@ -34,8 +34,10 @@ watch(
watch(
[source, source2, source3],
(values, oldValues) => {
expectType<(string | number)[]>(values)
expectType<(string | number | undefined)[]>(oldValues)
expectType<[string, string, number]>(values)
expectType<[string | undefined, string | undefined, number | undefined]>(
oldValues
)
},
{ immediate: true }
)
@@ -61,3 +63,15 @@ watch(nestedRefSource, (v, ov) => {
expectType<{ foo: number }>(v)
expectType<{ foo: number }>(ov)
})

const someRef = ref({ test: 'test' })
const otherRef = ref({ a: 'b' })
watch([someRef, otherRef], values => {
const value1 = values[0]
// no type error
console.log(value1.test)

const value2 = values[1]
// no type error
console.log(value2.a)
})
391 changes: 130 additions & 261 deletions yarn.lock

Large diffs are not rendered by default.