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.5
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.6
Choose a head ref

Commits on Dec 30, 2020

  1. Copy the full SHA
    1d46149 View commit details
  2. Copy the full SHA
    c105699 View commit details

Commits on Dec 31, 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
    a2e65ef 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
    ee266af View commit details

Commits on Jan 4, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4bc4c42 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
    c92990e View commit details
  3. Copy the full SHA
    2ea9867 View commit details

Commits on Jan 5, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    09ecaaa 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
    036e9b6 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
    143751d View commit details
  4. Verified

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

Commits on Jan 6, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9126724 View commit details
  2. chore: typo (#2953)

    veaba authored Jan 6, 2021

    Verified

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

Commits on Jan 7, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    be71912 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
    1987f9e View commit details

Commits on Jan 8, 2021

  1. Verified

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

Commits on Jan 12, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d72225b 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
    13fc8ff View commit details

Commits on Jan 13, 2021

  1. Verified

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

Commits on Jan 15, 2021

  1. Copy the full SHA
    fd16f2b View commit details

Commits on Jan 18, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6388ece 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
    4c1500d 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
    cc934cd View commit details

Commits on Jan 19, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    537b7ec 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
    4b0b253 View commit details

Commits on Jan 20, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c52e5d2 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
    12146d6 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
    e79feb0 View commit details

Commits on Jan 21, 2021

  1. Verified

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

Commits on Jan 25, 2021

  1. Verified

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

Commits on Jan 26, 2021

  1. Verified

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

Commits on Jan 29, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d224753 View commit details
  2. Copy the full SHA
    4fecb27 View commit details
  3. Copy the full SHA
    310cb8c View commit details

Commits on Feb 1, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6cc86bf 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
    c69035b 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
    b0dc064 View commit details
  4. Verified

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

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

Commits on Feb 2, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5ccfd9d 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
    d5cce47 View commit details

Commits on Feb 3, 2021

  1. fix(runtime-core): ensure app instance can be garbage collected after…

    … unmount (close #2907) (#2909)
    
    close #2907
    
    Co-authored-by: Thorsten Luenborg <t.luneborg@googlemail.com>
    LinusBorg and Thorsten Luenborg authored Feb 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    60e05ef 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
    18b0c9a View commit details
  3. fix: should prefix ShadowRoot with window. (#2943)

    Otherwise this expression would throw in environments that does not
    support `ShadowRoot` which includes the common mocha testing environment
    setup that uses `jsdom` and `jsdom-global`.
    
    It is because `ShadowRoot` is not an enumerable property on `window`,
    `jsdom-global` fails to expose it on the `global` object.
    
    See the error message at: https://app.circleci.com/pipelines/github/vuejs/vue-cli/779/workflows/17d7d7c4-7605-4588-878a-ddb3a6d37102/jobs/24147
    haoqunjiang authored Feb 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    97d6f1a View commit details
  4. docs(contributing): missing link to Scripts section (#2868)

    Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com>
    Alan Wang and posva authored Feb 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6b0a549 View commit details
  5. fix(runtime-dom): enable set form attr to null on form-elements (#2840)…

    … (#2849)
    
    Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com>
    Co-authored-by: Thorsten Lünborg <t.luenborg@googlemail.com>
    3 people authored Feb 3, 2021

    Verified

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

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

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4ca4666 View commit details
  8. fix: ensure all published packages contan a LICENCE file (close #2650) (

    #2857)
    
    close #2650
    
    Co-authored-by: Thorsten Luenborg <t.luneborg@googlemail.com>
    LinusBorg and Thorsten Luenborg authored Feb 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6a48d23 View commit details
  9. fix(docs): change reference to passed deadline (#2930)

    mention we plan to drop the next suffix in early
    2021 rather than 2020 since that deadline has
    passed.
    
    Fixes N/A
    codymikol authored Feb 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    de7f9d1 View commit details
Showing with 997 additions and 540 deletions.
  1. +1 −0 .github/contributing.md
  2. +51 −1 CHANGELOG.md
  3. +9 −9 README.md
  4. +3 −3 package.json
  5. +2 −2 packages/compiler-core/package.json
  6. +1 −1 packages/compiler-core/src/parse.ts
  7. +3 −3 packages/compiler-core/src/transform.ts
  8. +3 −2 packages/compiler-core/src/transforms/vFor.ts
  9. +5 −5 packages/compiler-dom/package.json
  10. +21 −0 packages/compiler-sfc/LICENSE
  11. +19 −0 packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
  12. +5 −2 packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap
  13. +12 −0 packages/compiler-sfc/__tests__/__snapshots__/templateTransformSrcset.spec.ts.snap
  14. +12 −0 packages/compiler-sfc/__tests__/compileScript.spec.ts
  15. +9 −0 packages/compiler-sfc/__tests__/parse.spec.ts
  16. +4 −2 packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts
  17. +1 −0 packages/compiler-sfc/__tests__/templateTransformSrcset.spec.ts
  18. +8 −8 packages/compiler-sfc/package.json
  19. +27 −18 packages/compiler-sfc/src/compileScript.ts
  20. +23 −18 packages/compiler-sfc/src/compileStyle.ts
  21. +9 −8 packages/compiler-sfc/src/cssVars.ts
  22. +1 −0 packages/compiler-sfc/src/parse.ts
  23. +176 −155 packages/compiler-sfc/src/stylePluginScoped.ts
  24. +16 −8 packages/compiler-sfc/src/stylePluginTrim.ts
  25. +16 −23 packages/compiler-sfc/src/templateTransformAssetUrl.ts
  26. +4 −5 packages/compiler-sfc/src/templateTransformSrcset.ts
  27. +21 −0 packages/compiler-ssr/LICENSE
  28. +3 −3 packages/compiler-ssr/package.json
  29. +10 −8 packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
  30. +2 −2 packages/reactivity/package.json
  31. +5 −2 packages/reactivity/src/baseHandlers.ts
  32. +1 −1 packages/reactivity/src/ref.ts
  33. +2 −2 packages/runtime-core/__tests__/apiCreateApp.spec.ts
  34. +28 −0 packages/runtime-core/__tests__/apiExpose.spec.ts
  35. +4 −4 packages/runtime-core/__tests__/apiInject.spec.ts
  36. +20 −1 packages/runtime-core/__tests__/apiOptions.spec.ts
  37. +21 −1 packages/runtime-core/__tests__/apiWatch.spec.ts
  38. +1 −1 packages/runtime-core/__tests__/componentEmits.spec.ts
  39. +25 −0 packages/runtime-core/__tests__/componentProps.spec.ts
  40. +3 −3 packages/runtime-core/package.json
  41. +2 −2 packages/runtime-core/src/apiAsyncComponent.ts
  42. +2 −1 packages/runtime-core/src/apiCreateApp.ts
  43. +10 −6 packages/runtime-core/src/apiWatch.ts
  44. +7 −8 packages/runtime-core/src/component.ts
  45. +11 −1 packages/runtime-core/src/componentOptions.ts
  46. +4 −2 packages/runtime-core/src/componentProps.ts
  47. +13 −6 packages/runtime-core/src/componentPublicInstance.ts
  48. +5 −1 packages/runtime-core/src/componentRenderUtils.ts
  49. +0 −2 packages/runtime-core/src/components/KeepAlive.ts
  50. +2 −2 packages/runtime-core/src/helpers/useSsrContext.ts
  51. +1 −1 packages/runtime-core/src/hmr.ts
  52. +9 −1 packages/runtime-core/src/renderer.ts
  53. +17 −2 packages/runtime-core/src/vnode.ts
  54. +26 −0 packages/runtime-dom/__tests__/patchEvents.spec.ts
  55. +10 −0 packages/runtime-dom/__tests__/patchProps.spec.ts
  56. +3 −3 packages/runtime-dom/package.json
  57. +1 −1 packages/runtime-dom/src/index.ts
  58. +2 −2 packages/runtime-dom/src/modules/events.ts
  59. +8 −3 packages/runtime-dom/src/patchProp.ts
  60. +2 −0 packages/runtime-dom/types/jsx.d.ts
  61. +3 −3 packages/runtime-test/package.json
  62. +4 −4 packages/server-renderer/package.json
  63. +21 −0 packages/shared/LICENSE
  64. +17 −0 packages/shared/__tests__/normalizeProp.spec.ts
  65. +1 −1 packages/shared/package.json
  66. +1 −1 packages/shared/src/globalsWhitelist.ts
  67. +4 −1 packages/shared/src/normalizeProp.ts
  68. +1 −1 packages/size-check/package.json
  69. +1 −1 packages/template-explorer/package.json
  70. +21 −0 packages/vue/LICENSE
  71. +9 −0 packages/vue/__tests__/index.spec.ts
  72. +4 −4 packages/vue/package.json
  73. +3 −1 packages/vue/src/index.ts
  74. +3 −1 packages/vue/src/runtime.ts
  75. +4 −1 rollup.config.js
  76. +4 −1 test-dts/defineComponent.test-d.tsx
  77. +10 −1 test-dts/ref.test-d.ts
  78. +164 −174 yarn.lock
1 change: 1 addition & 0 deletions .github/contributing.md
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
- [Issue Reporting Guidelines](#issue-reporting-guidelines)
- [Pull Request Guidelines](#pull-request-guidelines)
- [Development Setup](#development-setup)
- [Scripts](#scripts)
- [Project Structure](#project-structure)
- [Contributing Tests](#contributing-tests)
- [Financial Contribution](#financial-contribution)
52 changes: 51 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,56 @@
## [3.0.5](https://github.com/vuejs/vue-next/compare/v3.0.4...v3.0.5) (2020-12-30)
## [3.0.6](https://github.com/vuejs/vue-next/compare/v3.0.5...v3.0.6) (2021-02-24)


### Bug Fixes

* **compiler-core:** do not mark v-for as stable on const bindings ([734c65b](https://github.com/vuejs/vue-next/commit/734c65badd8395a78d7beee1fc960aee418361a0)), closes [vitejs/vite#1956](https://github.com/vitejs/vite/issues/1956)
* **compiler-dom:** ensure global build filename matches the one defined in package.json (close [#3181](https://github.com/vuejs/vue-next/issues/3181)) ([#3185](https://github.com/vuejs/vue-next/issues/3185)) ([96b6433](https://github.com/vuejs/vue-next/commit/96b64335242a99432080aeb879e5c0787207a0de))
* **compiler-dom:** fix cdn entries ([fcb6c89](https://github.com/vuejs/vue-next/commit/fcb6c8920c6ee76f57325a178eb9280d7bae4d7c)), closes [#3181](https://github.com/vuejs/vue-next/issues/3181) [#3185](https://github.com/vuejs/vue-next/issues/3185)
* **compiler-sfc:** compiler blank srcset ([#3005](https://github.com/vuejs/vue-next/issues/3005)) ([9dc816d](https://github.com/vuejs/vue-next/commit/9dc816d63468b0a2fa2b6123959310014e121b58))
* **compiler-sfc:** removeSpecifier issue when removing initial imports (script-setup) ([#2729](https://github.com/vuejs/vue-next/issues/2729)) ([6d762a8](https://github.com/vuejs/vue-next/commit/6d762a84ca0ac9a43eb3d0ab0c7b7b17c35c9836))
* **compiler-sfc:** the empty lang attribute should be treated as no lang specified ([#3051](https://github.com/vuejs/vue-next/issues/3051)) ([6d5b623](https://github.com/vuejs/vue-next/commit/6d5b62351248780663d2612a1f483f7ea9f5e5a2))
* **compiler-sfc:** transformAssetUrls.base should not affect known module requests ([2ea9867](https://github.com/vuejs/vue-next/commit/2ea9867398d19148b32643fa0e6523c95b9ca956))
* **compiler-sfc:** treat const reactive() bindings as mutable ([03360ce](https://github.com/vuejs/vue-next/commit/03360cefa1b7038174fa3c1fc3a04400b4cdbbce))
* **compiler-ssr:** avoid duplicated asset imports merged from component slot client branch ([c69f4ea](https://github.com/vuejs/vue-next/commit/c69f4ea857b7db8d26bbde2f80786c8212d16770)), closes [vitejs/vite#2034](https://github.com/vitejs/vite/issues/2034)
* **devtools:** init devtools in production ([#2906](https://github.com/vuejs/vue-next/issues/2906)) ([4d9bcb7](https://github.com/vuejs/vue-next/commit/4d9bcb768ddc294430aedcf27155aaca292c47bd))
* **devtools:** send instance to devtools when it's mounted instead of created ([4fecb27](https://github.com/vuejs/vue-next/commit/4fecb27f8696fdb8f681948543ea81ea62fe43bf))
* **docs:** change reference to passed deadline ([#2930](https://github.com/vuejs/vue-next/issues/2930)) ([de7f9d1](https://github.com/vuejs/vue-next/commit/de7f9d1efd7fa19a908357d3f3a706c52694d8bd))
* **hmr:** deep clone reused hoisted trees during dev ([5a7a1b8](https://github.com/vuejs/vue-next/commit/5a7a1b8293822219283d6e267496bec02234b0bc)), closes [vitejs/vite#2022](https://github.com/vitejs/vite/issues/2022)
* **runtime-core:** align $parent/$root with the template ref when using expose ([#3158](https://github.com/vuejs/vue-next/issues/3158)) ([f43a3b0](https://github.com/vuejs/vue-next/commit/f43a3b0bebf0837223e7b8f046dad63e34cd323b))
* **runtime-core:** allow overriding properties other than props ([#3105](https://github.com/vuejs/vue-next/issues/3105)) ([73117f6](https://github.com/vuejs/vue-next/commit/73117f6b5b1e36c9400248ed9e815839c49a12c8))
* **runtime-core:** check the DEV_ROOT_FRAGMENT flag correctly in the dev environment ([#2750](https://github.com/vuejs/vue-next/issues/2750)) ([347a879](https://github.com/vuejs/vue-next/commit/347a8798a4c5f0b426f3ac84a01d752d823fb51b))
* **runtime-core:** component methods should override global properties in DEV ([#3074](https://github.com/vuejs/vue-next/issues/3074)) ([2587f36](https://github.com/vuejs/vue-next/commit/2587f36fe311359e2e34f40e8e47d2eebfab7f42))
* **runtime-core:** ensure app instance can be garbage collected after unmount (close [#2907](https://github.com/vuejs/vue-next/issues/2907)) ([#2909](https://github.com/vuejs/vue-next/issues/2909)) ([60e05ef](https://github.com/vuejs/vue-next/commit/60e05eff232c3ddfca1c20e52f72aa36165d8a22))
* **runtime-core:** instanceWatch should pass `this.proxy` to source as the first argument ([#2753](https://github.com/vuejs/vue-next/issues/2753)) ([ec8fd10](https://github.com/vuejs/vue-next/commit/ec8fd10cec61c33c7c8056413a1c609ac90e1215))
* **runtime-dom:** ensure readonly type prop on textarea is handled patched as attribute ([#2888](https://github.com/vuejs/vue-next/issues/2888)) ([c5d147c](https://github.com/vuejs/vue-next/commit/c5d147c57f75ca38cc334bb27b61a8bc153494bd)), closes [#2766](https://github.com/vuejs/vue-next/issues/2766)
* kebab-case events are attached correctly on web components, see [#2841](https://github.com/vuejs/vue-next/issues/2841) ([#2847](https://github.com/vuejs/vue-next/issues/2847)) ([b302cbb](https://github.com/vuejs/vue-next/commit/b302cbbbd3fd512f2b8afbd9c873060a40bf8e62))
* **types:** extract the correct props type for the DateConstructor ([#2676](https://github.com/vuejs/vue-next/issues/2676)) ([48f0d29](https://github.com/vuejs/vue-next/commit/48f0d2944f0f9d2f556e62782fc61985897b2ed4))
* ensure all published packages contan a LICENCE file (close [#2650](https://github.com/vuejs/vue-next/issues/2650)) ([#2857](https://github.com/vuejs/vue-next/issues/2857)) ([6a48d23](https://github.com/vuejs/vue-next/commit/6a48d23749e418b44ba17cd3e85f478484fd7ffe))
* remove superfluous spaces when normalizing class ([#3083](https://github.com/vuejs/vue-next/issues/3083)) ([4b55142](https://github.com/vuejs/vue-next/commit/4b551420fc058c4683219db5d75893f9fc69aa04))
* **runtime-dom:** enable set form attr to null on form-elements ([#2840](https://github.com/vuejs/vue-next/issues/2840)) ([#2849](https://github.com/vuejs/vue-next/issues/2849)) ([f262438](https://github.com/vuejs/vue-next/commit/f2624380731cc32e71523e8c2c98037e98e09319))
* **toRef:** ref created from union typed prop can't be used in watch ([#3048](https://github.com/vuejs/vue-next/issues/3048)) ([4ca4666](https://github.com/vuejs/vue-next/commit/4ca4666d58ee8025570dc14f1c163bdeac9c6012))
* should prefix `ShadowRoot` with `window.` ([#2943](https://github.com/vuejs/vue-next/issues/2943)) ([97d6f1a](https://github.com/vuejs/vue-next/commit/97d6f1a716045123d0e05600e64f11f92f504747))


### Features

* remove useless option in KeepAlive ([#3170](https://github.com/vuejs/vue-next/issues/3170)) ([bd1240c](https://github.com/vuejs/vue-next/commit/bd1240c1270b610c4ffcf6c32e2bbe2c9265020f))
* **compiler-core:** support `BigInt` in template ([#2900](https://github.com/vuejs/vue-next/issues/2900)) ([c9f94fa](https://github.com/vuejs/vue-next/commit/c9f94fa3cfbe8fcd9ea3d49d523dfb282c468369))
* **compiler-sfc:** upgrade to postcss 8 ([#2710](https://github.com/vuejs/vue-next/issues/2710)) ([49bc2e4](https://github.com/vuejs/vue-next/commit/49bc2e4db568d4f9fa2ccfe4e22c792cfc02651a))
* **runtime-core:** improve render context warning ([#2496](https://github.com/vuejs/vue-next/issues/2496)) ([288ae0a](https://github.com/vuejs/vue-next/commit/288ae0a8d9444365ad7438462e072c425150cbf1))
* **runtime-core:** props type support `BigInt` ([#2891](https://github.com/vuejs/vue-next/issues/2891)) ([ffd5288](https://github.com/vuejs/vue-next/commit/ffd52885453d1621e45dff645ff1101e74ea40b2))


### Performance Improvements

* **reactivity:** should not track `__isVue` ([#2940](https://github.com/vuejs/vue-next/issues/2940)) ([dd02cf3](https://github.com/vuejs/vue-next/commit/dd02cf37d5f5a6946bcae01ee70568e38a82c177))



## [3.0.5](https://github.com/vuejs/vue-next/compare/v3.0.4...v3.0.5) (2020-12-30)

**Note:** this release contains a type-only change that requires TypeScript 4.0+, which
may cause build issues in projects still using TS 3.x.
### 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)
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ Please consult the [Migration Guide](https://v3.vuejs.org/guide/migration/introd

## Supporting Libraries

All of our official libraries and tools now support Vue 3, but most of them are still in beta status and distributed under the `next` dist tag on NPM. **We are planning to stabilize and switch all projects to use the `latest` dist tag by end of 2020.**
All of our official libraries and tools now support Vue 3, but most of them are still in beta status and distributed under the `next` dist tag on NPM. **We are planning to stabilize and switch all projects to use the `latest` dist tag in early 2021.**

### Vue CLI

@@ -39,15 +39,15 @@ As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when
Vue Router 4.0 provides Vue 3 support and has a number of breaking changes of its own. Check out its [Migration Guide](https://next.router.vuejs.org/guide/migration/) for full details.

- [![beta](https://img.shields.io/npm/v/vue-router/next.svg)](https://www.npmjs.com/package/vue-router/v/next)
- [Github](https://github.com/vuejs/vue-router-next)
- [GitHub](https://github.com/vuejs/vue-router-next)
- [RFCs](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3Arouter)

### Vuex

Vuex 4.0 provides Vue 3 support with largely the same API as 3.x. The only breaking change is [how the plugin is installed](https://github.com/vuejs/vuex/tree/4.0#breaking-changes).

- [![beta](https://img.shields.io/npm/v/vuex/next.svg)](https://www.npmjs.com/package/vuex/v/next)
- [Github](https://github.com/vuejs/vuex/tree/4.0)
- [GitHub](https://github.com/vuejs/vuex/tree/4.0)

### Devtools Extension

@@ -67,12 +67,12 @@ It is recommended to use [VSCode](https://code.visualstudio.com/) with our offic

| Project | NPM | Repo |
| --------------------- | ----------------------------- | -------------------- |
| @vue/babel-plugin-jsx | [![rc][jsx-badge]][jsx-npm] | [[Github][jsx-code]] |
| eslint-plugin-vue | [![stable][epv-badge]][epv-npm] | [[Github][epv-code]] |
| @vue/test-utils | [![beta][vtu-badge]][vtu-npm] | [[Github][vtu-code]] |
| vue-class-component | [![beta][vcc-badge]][vcc-npm] | [[Github][vcc-code]] |
| vue-loader | [![beta][vl-badge]][vl-npm] | [[Github][vl-code]] |
| rollup-plugin-vue | [![beta][rpv-badge]][rpv-npm] | [[Github][rpv-code]] |
| @vue/babel-plugin-jsx | [![rc][jsx-badge]][jsx-npm] | [[GitHub][jsx-code]] |
| eslint-plugin-vue | [![stable][epv-badge]][epv-npm] | [[GitHub][epv-code]] |
| @vue/test-utils | [![beta][vtu-badge]][vtu-npm] | [[GitHub][vtu-code]] |
| vue-class-component | [![beta][vcc-badge]][vcc-npm] | [[GitHub][vcc-code]] |
| vue-loader | [![beta][vl-badge]][vl-npm] | [[GitHub][vl-code]] |
| rollup-plugin-vue | [![beta][rpv-badge]][rpv-npm] | [[GitHub][rpv-code]] |

[jsx-badge]: https://img.shields.io/npm/v/@vue/babel-plugin-jsx.svg
[jsx-npm]: https://www.npmjs.com/package/@vue/babel-plugin-jsx
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"private": true,
"version": "3.0.5",
"version": "3.0.6",
"workspaces": [
"packages/*"
],
@@ -42,7 +42,7 @@
},
"devDependencies": {
"@babel/types": "^7.12.0",
"@microsoft/api-extractor": "^7.9.15",
"@microsoft/api-extractor": "^7.12.1",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
@@ -74,7 +74,7 @@
"semver": "^7.3.2",
"serve": "^11.3.0",
"ts-jest": "^26.2.0",
"typescript": "^4.0.2",
"typescript": "^4.1.3",
"yorkie": "^2.0.0"
}
}
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.5",
"version": "3.0.6",
"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.5",
"@vue/shared": "3.0.6",
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"estree-walker": "^2.0.1",
2 changes: 1 addition & 1 deletion packages/compiler-core/src/parse.ts
Original file line number Diff line number Diff line change
@@ -924,7 +924,7 @@ function isEnd(
switch (mode) {
case TextModes.DATA:
if (startsWith(s, '</')) {
//TODO: probably bad performance
// TODO: probably bad performance
for (let i = ancestors.length - 1; i >= 0; --i) {
if (startsWithEndTagOpen(s, ancestors[i].tag)) {
return true
6 changes: 3 additions & 3 deletions packages/compiler-core/src/transform.ts
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ export interface TransformContext
components: Set<string>
directives: Set<string>
hoists: (JSChildNode | null)[]
imports: Set<ImportItem>
imports: ImportItem[]
temps: number
cached: number
identifiers: { [name: string]: number | undefined }
@@ -163,7 +163,7 @@ export function createTransformContext(
components: new Set(),
directives: new Set(),
hoists: [],
imports: new Set(),
imports: [],
constantCache: new Map(),
temps: 0,
cached: 0,
@@ -293,7 +293,7 @@ export function transform(root: RootNode, options: TransformOptions) {
root.helpers = [...context.helpers]
root.components = [...context.components]
root.directives = [...context.directives]
root.imports = [...context.imports]
root.imports = context.imports
root.hoists = context.hoists
root.temps = context.temps
root.cached = context.cached
5 changes: 3 additions & 2 deletions packages/compiler-core/src/transforms/vFor.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,8 @@ import {
VNodeCall,
ForRenderListExpression,
BlockCodegenNode,
ForIteratorExpression
ForIteratorExpression,
ConstantTypes
} from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import {
@@ -78,7 +79,7 @@ export const transformFor = createStructuralDirectiveTransform(

const isStableFragment =
forNode.source.type === NodeTypes.SIMPLE_EXPRESSION &&
forNode.source.constType > 0
forNode.source.constType > ConstantTypes.NOT_CONSTANT
const fragmentFlag = isStableFragment
? PatchFlags.STABLE_FRAGMENT
: keyProp
10 changes: 5 additions & 5 deletions packages/compiler-dom/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@vue/compiler-dom",
"version": "3.0.5",
"version": "3.0.6",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",
"types": "dist/compiler-dom.d.ts",
"unpkg": "dist/compiler-dom/global.js",
"jsdelivr": "dist/compiler-dom/global.js",
"unpkg": "dist/compiler-dom.global.js",
"jsdelivr": "dist/compiler-dom.global.js",
"files": [
"index.js",
"dist"
@@ -36,7 +36,7 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-dom#readme",
"dependencies": {
"@vue/shared": "3.0.5",
"@vue/compiler-core": "3.0.5"
"@vue/shared": "3.0.6",
"@vue/compiler-core": "3.0.6"
}
}
21 changes: 21 additions & 0 deletions packages/compiler-sfc/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018-present, Yuxi (Evan) You

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Original file line number Diff line number Diff line change
@@ -164,6 +164,25 @@ return { x }
}"
`;
exports[`SFC compile <script setup> imports should allow defineProps/Emit at the start of imports 1`] = `
"import { ref } from 'vue'
export default {
expose: [],
props: ['foo'],
emits: ['bar'],
setup(__props) {
const r = ref(0)
return { r, ref }
}
}"
`;
exports[`SFC compile <script setup> imports should extract comment for import or type declarations 1`] = `
"import a from 'a' // comment
import b from 'b'
Original file line number Diff line number Diff line change
@@ -72,13 +72,16 @@ export function render(_ctx, _cache) {

exports[`compiler sfc: transform asset url with explicit base 1`] = `
"import { createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
import _imports_0 from 'bar.png'
import _imports_1 from '@theme/bar.png'
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_Fragment, null, [
_createVNode(\\"img\\", { src: \\"/foo/bar.png\\" }),
_createVNode(\\"img\\", { src: \\"/foo/bar.png\\" }),
_createVNode(\\"img\\", { src: \\"bar.png\\" }),
_createVNode(\\"img\\", { src: \\"@theme/bar.png\\" })
_createVNode(\\"img\\", { src: _imports_0 }),
_createVNode(\\"img\\", { src: _imports_1 })
], 64 /* STABLE_FRAGMENT */))
}"
`;
Original file line number Diff line number Diff line change
@@ -16,6 +16,10 @@ const _hoisted_8 = \\"/logo.png\\" + ', ' + _imports_0 + '2x'
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_Fragment, null, [
_createVNode(\\"img\\", {
src: \\"./logo.png\\",
srcset: \\"\\"
}),
_createVNode(\\"img\\", {
src: \\"./logo.png\\",
srcset: _hoisted_1
@@ -69,6 +73,10 @@ exports[`compiler sfc: transform srcset transform srcset w/ base 1`] = `
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_Fragment, null, [
_createVNode(\\"img\\", {
src: \\"./logo.png\\",
srcset: \\"\\"
}),
_createVNode(\\"img\\", {
src: \\"./logo.png\\",
srcset: \\"/foo/logo.png\\"
@@ -137,6 +145,10 @@ const _hoisted_11 = \\"data:image/png;base64,i\\" + '1x, ' + \\"data:image/png;b
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_Fragment, null, [
_createVNode(\\"img\\", {
src: \\"./logo.png\\",
srcset: \\"\\"
}),
_createVNode(\\"img\\", {
src: \\"./logo.png\\",
srcset: _hoisted_1
12 changes: 12 additions & 0 deletions packages/compiler-sfc/__tests__/compileScript.spec.ts
Original file line number Diff line number Diff line change
@@ -141,6 +141,18 @@ const myEmit = defineEmit(['foo', 'bar'])
)
})

// #2740
test('should allow defineProps/Emit at the start of imports', () => {
assertCode(
compile(`<script setup>
import { defineProps, defineEmit, ref } from 'vue'
defineProps(['foo'])
defineEmit(['bar'])
const r = ref(0)
</script>`).content
)
})

test('dedupe between user & helper', () => {
const { content } = compile(`
<script setup>
9 changes: 9 additions & 0 deletions packages/compiler-sfc/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
@@ -139,6 +139,15 @@ h1 { color: red }
expect(descriptor.template!.content).toBe(content)
})

test('treat empty lang attribute as the html', () => {
const content = `<div><template v-if="ok">ok</template></div>`
const { descriptor, errors } = parse(
`<template lang="">${content}</template>`
)
expect(descriptor.template!.content).toBe(content)
expect(errors.length).toBe(0)
})

// #1120
test('alternative template lang should be treated as plain text', () => {
const content = `p(v-if="1 < 2") test`
Original file line number Diff line number Diff line change
@@ -59,13 +59,15 @@ describe('compiler sfc: transform asset url', () => {
test('with explicit base', () => {
const { code } = compileWithAssetUrls(
`<img src="./bar.png"></img>` + // -> /foo/bar.png
`<img src="~bar.png"></img>` + // -> /foo/bar.png
`<img src="bar.png"></img>` + // -> bar.png (untouched)
`<img src="@theme/bar.png"></img>`, // -> @theme/bar.png (untouched)
`<img src="~bar.png"></img>` + // -> still converts to import
`<img src="@theme/bar.png"></img>`, // -> still converts to import
{
base: '/foo'
}
)
expect(code).toMatch(`import _imports_0 from 'bar.png'`)
expect(code).toMatch(`import _imports_1 from '@theme/bar.png'`)
expect(code).toMatchSnapshot()
})

Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ function compileWithSrcset(template: string, options?: AssetURLOptions) {
}

const src = `
<img src="./logo.png" srcset=""/>
<img src="./logo.png" srcset="./logo.png"/>
<img src="./logo.png" srcset="./logo.png 2x"/>
<img src="./logo.png" srcset="./logo.png 2x"/>
16 changes: 8 additions & 8 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.5",
"version": "3.0.6",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"types": "dist/compiler-sfc.d.ts",
@@ -31,23 +31,23 @@
},
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-sfc#readme",
"peerDependencies": {
"vue": "3.0.5"
"vue": "3.0.6"
},
"dependencies": {
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"@vue/compiler-core": "3.0.5",
"@vue/compiler-dom": "3.0.5",
"@vue/compiler-ssr": "3.0.5",
"@vue/shared": "3.0.5",
"@vue/compiler-core": "3.0.6",
"@vue/compiler-dom": "3.0.6",
"@vue/compiler-ssr": "3.0.6",
"@vue/shared": "3.0.6",
"consolidate": "^0.16.0",
"estree-walker": "^2.0.1",
"hash-sum": "^2.0.0",
"lru-cache": "^5.1.1",
"magic-string": "^0.25.7",
"merge-source-map": "^1.1.0",
"postcss": "^7.0.32",
"postcss-modules": "^3.2.2",
"postcss": "^8.1.10",
"postcss-modules": "^4.0.0",
"postcss-selector-parser": "^6.0.4",
"source-map": "^0.6.1"
},
45 changes: 27 additions & 18 deletions packages/compiler-sfc/src/compileScript.ts
Original file line number Diff line number Diff line change
@@ -597,19 +597,23 @@ export function compileScript(

// dedupe imports
let removed = 0
let prev: Node | undefined, next: Node | undefined
const removeSpecifier = (node: Node) => {
const removeSpecifier = (i: number) => {
const removeLeft = i > removed
removed++
const current = node.specifiers[i]
const next = node.specifiers[i + 1]
s.remove(
prev ? prev.end! + startOffset : node.start! + startOffset,
next && !prev ? next.start! + startOffset : node.end! + startOffset
removeLeft
? node.specifiers[i - 1].end! + startOffset
: current.start! + startOffset,
next && !removeLeft
? next.start! + startOffset
: current.end! + startOffset
)
}

for (let i = 0; i < node.specifiers.length; i++) {
const specifier = node.specifiers[i]
prev = node.specifiers[i - 1]
next = node.specifiers[i + 1]
const local = specifier.local.name
const imported =
specifier.type === 'ImportSpecifier' &&
@@ -621,11 +625,11 @@ export function compileScript(
source === 'vue' &&
(imported === DEFINE_PROPS || imported === DEFINE_EMIT)
) {
removeSpecifier(specifier)
removeSpecifier(i)
} else if (existing) {
if (existing.source === source && existing.imported === imported) {
// already imported in <script setup>, dedupe
removeSpecifier(specifier)
removeSpecifier(i)
} else {
error(`different imports aliased to same local name.`, specifier)
}
@@ -739,7 +743,7 @@ export function compileScript(
if (enableRefSugar && Object.keys(refBindings).length) {
for (const node of scriptSetupAst) {
if (node.type !== 'ImportDeclaration') {
walkIdentifiers(node, (id, parent) => {
walkIdentifiers(node, (id, parent, parentStack) => {
if (refBindings[id.name] && !refIdentifiers.has(id)) {
if (isStaticProperty(parent) && parent.shorthand) {
// let binding used in a property shorthand
@@ -1036,12 +1040,15 @@ function walkDeclaration(
)
if (id.type === 'Identifier') {
let bindingType
if (
const userReactiveBinding = userImportAlias['reactive'] || 'reactive'
if (isCallOf(init, userReactiveBinding)) {
// treat reactive() calls as let since it's meant to be mutable
bindingType = BindingTypes.SETUP_LET
} else if (
// if a declaration is a const literal, we can mark it so that
// the generated render fn code doesn't need to unref() it
isDefineCall ||
(isConst &&
canNeverBeRef(init!, userImportAlias['reactive'] || 'reactive'))
(isConst && canNeverBeRef(init!, userReactiveBinding))
) {
bindingType = BindingTypes.SETUP_CONST
} else if (isConst) {
@@ -1337,8 +1344,6 @@ function genRuntimeEmits(emits: Set<string>) {
: ``
}

const parentStack: Node[] = []

/**
* Walk an AST and find identifiers that are variable references.
* This is largely the same logic with `transformExpressions` in compiler-core
@@ -1347,15 +1352,19 @@ const parentStack: Node[] = []
*/
function walkIdentifiers(
root: Node,
onIdentifier: (node: Identifier, parent: Node) => void
onIdentifier: (node: Identifier, parent: Node, parentStack: Node[]) => void
) {
const parentStack: Node[] = []
const knownIds: Record<string, number> = Object.create(null)
;(walk as any)(root, {
enter(node: Node & { scopeIds?: Set<string> }, parent: Node | undefined) {
parent && parentStack.push(parent)
if (node.type === 'Identifier') {
if (!knownIds[node.name] && isRefIdentifier(node, parent!)) {
onIdentifier(node, parent!)
if (
!knownIds[node.name] &&
isRefIdentifier(node, parent!, parentStack)
) {
onIdentifier(node, parent!, parentStack)
}
} else if (isFunction(node)) {
// walk function expressions and add its arguments to known identifiers
@@ -1411,7 +1420,7 @@ function walkIdentifiers(
})
}

function isRefIdentifier(id: Identifier, parent: Node) {
function isRefIdentifier(id: Identifier, parent: Node, parentStack: Node[]) {
// declaration id
if (
(parent.type === 'VariableDeclarator' ||
41 changes: 23 additions & 18 deletions packages/compiler-sfc/src/compileStyle.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import postcss, {
ProcessOptions,
LazyResult,
Result,
ResultMap,
ResultMessage
SourceMap,
Message,
LazyResult
} from 'postcss'
import trimPlugin from './stylePluginTrim'
import scopedPlugin from './stylePluginScoped'
@@ -35,28 +35,33 @@ export interface SFCStyleCompileOptions {
map?: RawSourceMap
}

/**
* Aligns with postcss-modules
* https://github.com/css-modules/postcss-modules
*/
export interface CSSModulesOptions {
scopeBehaviour?: 'global' | 'local'
generateScopedName?:
| string
| ((name: string, filename: string, css: string) => string)
hashPrefix?: string
localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'
exportGlobals?: boolean
globalModulePaths?: string[]
}

export interface SFCAsyncStyleCompileOptions extends SFCStyleCompileOptions {
isAsync?: boolean
// css modules support, note this requires async so that we can get the
// resulting json
modules?: boolean
// maps to postcss-modules options
// https://github.com/css-modules/postcss-modules
modulesOptions?: {
scopeBehaviour?: 'global' | 'local'
globalModulePaths?: string[]
generateScopedName?:
| string
| ((name: string, filename: string, css: string) => string)
hashPrefix?: string
localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'
}
modulesOptions?: CSSModulesOptions
}

export interface SFCStyleCompileResults {
code: string
map: RawSourceMap | undefined
rawResult: LazyResult | Result | undefined
rawResult: Result | LazyResult | undefined
errors: Error[]
modules?: Record<string, string>
dependencies: Set<string>
@@ -149,7 +154,7 @@ export function doCompileStyle(

let result: LazyResult | undefined
let code: string | undefined
let outMap: ResultMap | undefined
let outMap: SourceMap | undefined
// stylus output include plain css. so need remove the repeat item
const dependencies = new Set(
preProcessedSource ? preProcessedSource.dependencies : []
@@ -162,7 +167,7 @@ export function doCompileStyle(
errors.push(...preProcessedSource.errors)
}

const recordPlainCssDependencies = (messages: ResultMessage[]) => {
const recordPlainCssDependencies = (messages: Message[]) => {
messages.forEach(msg => {
if (msg.type === 'dependency') {
// postcss output path is absolute position path
@@ -226,7 +231,7 @@ function preprocess(

return preprocessor(
options.source,
options.map,
options.inMap || options.map,
{
filename: options.filename,
...options.preprocessOptions
17 changes: 9 additions & 8 deletions packages/compiler-sfc/src/cssVars.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import {
BindingMetadata
} from '@vue/compiler-dom'
import { SFCDescriptor } from './parse'
import postcss, { Root } from 'postcss'
import { PluginCreator } from 'postcss'
import hash from 'hash-sum'

export const CSS_VARS_HELPER = `useCssVars`
@@ -49,20 +49,21 @@ export interface CssVarsPluginOptions {
isProd: boolean
}

export const cssVarsPlugin = postcss.plugin<CssVarsPluginOptions>(
'vue-scoped',
opts => (root: Root) => {
const { id, isProd } = opts!
root.walkDecls(decl => {
export const cssVarsPlugin: PluginCreator<CssVarsPluginOptions> = opts => {
const { id, isProd } = opts!
return {
postcssPlugin: 'vue-sfc-vars',
Declaration(decl) {
// rewrite CSS variables
if (cssVarRE.test(decl.value)) {
decl.value = decl.value.replace(cssVarRE, (_, $1, $2, $3) => {
return `var(--${genVarName(id, $1 || $2 || $3, isProd)})`
})
}
})
}
}
)
}
cssVarsPlugin.postcss = true

export function genCssVarsCode(
vars: string[],
1 change: 1 addition & 0 deletions packages/compiler-sfc/src/parse.ts
Original file line number Diff line number Diff line change
@@ -121,6 +121,7 @@ export function parse(
p.type === NodeTypes.ATTRIBUTE &&
p.name === 'lang' &&
p.value &&
p.value.content &&
p.value.content !== 'html'
))
) {
331 changes: 176 additions & 155 deletions packages/compiler-sfc/src/stylePluginScoped.ts
Original file line number Diff line number Diff line change
@@ -1,181 +1,202 @@
import postcss, { Root } from 'postcss'
import selectorParser, { Node, Selector } from 'postcss-selector-parser'
import { PluginCreator, Rule } from 'postcss'
import selectorParser from 'postcss-selector-parser'
import { warn } from './warn'

const animationNameRE = /^(-\w+-)?animation-name$/
const animationRE = /^(-\w+-)?animation$/

export default postcss.plugin('vue-scoped', (id: any) => (root: Root) => {
const scopedPlugin: PluginCreator<string> = (id = '') => {
const keyframes = Object.create(null)
const shortId = id.replace(/^data-v-/, '')

root.each(function rewriteSelectors(node) {
if (node.type !== 'rule') {
// handle media queries
if (node.type === 'atrule') {
if (node.name === 'media' || node.name === 'supports') {
node.each(rewriteSelectors)
} else if (/-?keyframes$/.test(node.name)) {
// register keyframes
keyframes[node.params] = node.params = node.params + '-' + shortId
}
return {
postcssPlugin: 'vue-sfc-scoped',
Rule(rule) {
processRule(id, rule)
},
AtRule(node) {
if (
/-?keyframes$/.test(node.name) &&
!node.params.endsWith(`-${shortId}`)
) {
// register keyframes
keyframes[node.params] = node.params = node.params + '-' + shortId
}
return
}

node.selector = selectorParser(selectors => {
function rewriteSelector(selector: Selector, slotted?: boolean) {
let node: Node | null = null
let shouldInject = true
// find the last child node to insert attribute selector
selector.each(n => {
// DEPRECATED ">>>" and "/deep/" combinator
if (
n.type === 'combinator' &&
(n.value === '>>>' || n.value === '/deep/')
) {
n.value = ' '
n.spaces.before = n.spaces.after = ''
warn(
`the >>> and /deep/ combinators have been deprecated. ` +
`Use :deep() instead.`
)
return false
},
OnceExit(root) {
if (Object.keys(keyframes).length) {
// If keyframes are found in this <style>, find and rewrite animation names
// in declarations.
// Caveat: this only works for keyframes and animation rules in the same
// <style> element.
// individual animation-name declaration
root.walkDecls(decl => {
if (animationNameRE.test(decl.prop)) {
decl.value = decl.value
.split(',')
.map(v => keyframes[v.trim()] || v.trim())
.join(',')
}

if (n.type === 'pseudo') {
const { value } = n
// deep: inject [id] attribute at the node before the ::v-deep
// combinator.
if (value === ':deep' || value === '::v-deep') {
if (n.nodes.length) {
// .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar
// replace the current node with ::v-deep's inner selector
let last: Selector['nodes'][0] = n
n.nodes[0].each(ss => {
selector.insertAfter(last, ss)
last = ss
})
// insert a space combinator before if it doesn't already have one
const prev = selector.at(selector.index(n) - 1)
if (!prev || !isSpaceCombinator(prev)) {
selector.insertAfter(
n,
selectorParser.combinator({
value: ' '
})
)
}
selector.removeChild(n)
} else {
// DEPRECATED usage
// .foo ::v-deep .bar -> .foo[xxxxxxx] .bar
warn(
`::v-deep usage as a combinator has ` +
`been deprecated. Use :deep(<inner-selector>) instead.`
)
const prev = selector.at(selector.index(n) - 1)
if (prev && isSpaceCombinator(prev)) {
selector.removeChild(prev)
// shorthand
if (animationRE.test(decl.prop)) {
decl.value = decl.value
.split(',')
.map(v => {
const vals = v.trim().split(/\s+/)
const i = vals.findIndex(val => keyframes[val])
if (i !== -1) {
vals.splice(i, 1, keyframes[vals[i]])
return vals.join(' ')
} else {
return v
}
selector.removeChild(n)
}
return false
}

// slot: use selector inside `::v-slotted` and inject [id + '-s']
// instead.
// ::v-slotted(.foo) -> .foo[xxxxxxx-s]
if (value === ':slotted' || value === '::v-slotted') {
rewriteSelector(n.nodes[0], true /* slotted */)
let last: Selector['nodes'][0] = n
n.nodes[0].each(ss => {
selector.insertAfter(last, ss)
last = ss
})
// selector.insertAfter(n, n.nodes[0])
selector.removeChild(n)
// since slotted attribute already scopes the selector there's no
// need for the non-slot attribute.
shouldInject = false
return false
}

// global: replace with inner selector and do not inject [id].
// ::v-global(.foo) -> .foo
if (value === ':global' || value === '::v-global') {
selectors.insertAfter(selector, n.nodes[0])
selectors.removeChild(selector)
return false
}
}

if (n.type !== 'pseudo' && n.type !== 'combinator') {
node = n
.join(',')
}
})
}
}
}
}

if (node) {
;(node as Node).spaces.after = ''
} else {
// For deep selectors & standalone pseudo selectors,
// the attribute selectors are prepended rather than appended.
// So all leading spaces must be eliminated to avoid problems.
selector.first.spaces.before = ''
}
const processedRules = new WeakSet<Rule>()

function processRule(id: string, rule: Rule) {
if (processedRules.has(rule)) {
return
}
processedRules.add(rule)
rule.selector = selectorParser(selectorRoot => {
selectorRoot.each(selector => {
rewriteSelector(id, selector, selectorRoot)
})
}).processSync(rule.selector)
}

function rewriteSelector(
id: string,
selector: selectorParser.Selector,
selectorRoot: selectorParser.Root,
slotted = false
) {
let node: selectorParser.Node | null = null
let shouldInject = true
// find the last child node to insert attribute selector
selector.each(n => {
// DEPRECATED ">>>" and "/deep/" combinator
if (
n.type === 'combinator' &&
(n.value === '>>>' || n.value === '/deep/')
) {
n.value = ' '
n.spaces.before = n.spaces.after = ''
warn(
`the >>> and /deep/ combinators have been deprecated. ` +
`Use :deep() instead.`
)
return false
}

if (shouldInject) {
const idToAdd = slotted ? id + '-s' : id
selector.insertAfter(
// If node is null it means we need to inject [id] at the start
// insertAfter can handle `null` here
node as any,
selectorParser.attribute({
attribute: idToAdd,
value: idToAdd,
raws: {},
quoteMark: `"`
})
if (n.type === 'pseudo') {
const { value } = n
// deep: inject [id] attribute at the node before the ::v-deep
// combinator.
if (value === ':deep' || value === '::v-deep') {
if (n.nodes.length) {
// .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar
// replace the current node with ::v-deep's inner selector
let last: selectorParser.Selector['nodes'][0] = n
n.nodes[0].each(ss => {
selector.insertAfter(last, ss)
last = ss
})
// insert a space combinator before if it doesn't already have one
const prev = selector.at(selector.index(n) - 1)
if (!prev || !isSpaceCombinator(prev)) {
selector.insertAfter(
n,
selectorParser.combinator({
value: ' '
})
)
}
selector.removeChild(n)
} else {
// DEPRECATED usage
// .foo ::v-deep .bar -> .foo[xxxxxxx] .bar
warn(
`::v-deep usage as a combinator has ` +
`been deprecated. Use :deep(<inner-selector>) instead.`
)
const prev = selector.at(selector.index(n) - 1)
if (prev && isSpaceCombinator(prev)) {
selector.removeChild(prev)
}
selector.removeChild(n)
}
return false
}
selectors.each(selector => rewriteSelector(selector))
}).processSync(node.selector)
})

if (Object.keys(keyframes).length) {
// If keyframes are found in this <style>, find and rewrite animation names
// in declarations.
// Caveat: this only works for keyframes and animation rules in the same
// <style> element.
// individual animation-name declaration
root.walkDecls(decl => {
if (animationNameRE.test(decl.prop)) {
decl.value = decl.value
.split(',')
.map(v => keyframes[v.trim()] || v.trim())
.join(',')
// slot: use selector inside `::v-slotted` and inject [id + '-s']
// instead.
// ::v-slotted(.foo) -> .foo[xxxxxxx-s]
if (value === ':slotted' || value === '::v-slotted') {
rewriteSelector(id, n.nodes[0], selectorRoot, true /* slotted */)
let last: selectorParser.Selector['nodes'][0] = n
n.nodes[0].each(ss => {
selector.insertAfter(last, ss)
last = ss
})
// selector.insertAfter(n, n.nodes[0])
selector.removeChild(n)
// since slotted attribute already scopes the selector there's no
// need for the non-slot attribute.
shouldInject = false
return false
}
// shorthand
if (animationRE.test(decl.prop)) {
decl.value = decl.value
.split(',')
.map(v => {
const vals = v.trim().split(/\s+/)
const i = vals.findIndex(val => keyframes[val])
if (i !== -1) {
vals.splice(i, 1, keyframes[vals[i]])
return vals.join(' ')
} else {
return v
}
})
.join(',')

// global: replace with inner selector and do not inject [id].
// ::v-global(.foo) -> .foo
if (value === ':global' || value === '::v-global') {
selectorRoot.insertAfter(selector, n.nodes[0])
selectorRoot.removeChild(selector)
return false
}
})
}

if (n.type !== 'pseudo' && n.type !== 'combinator') {
node = n
}
})

if (node) {
;(node as selectorParser.Node).spaces.after = ''
} else {
// For deep selectors & standalone pseudo selectors,
// the attribute selectors are prepended rather than appended.
// So all leading spaces must be eliminated to avoid problems.
selector.first.spaces.before = ''
}
})

function isSpaceCombinator(node: Node) {
if (shouldInject) {
const idToAdd = slotted ? id + '-s' : id
selector.insertAfter(
// If node is null it means we need to inject [id] at the start
// insertAfter can handle `null` here
node as any,
selectorParser.attribute({
attribute: idToAdd,
value: idToAdd,
raws: {},
quoteMark: `"`
})
)
}
}

function isSpaceCombinator(node: selectorParser.Node) {
return node.type === 'combinator' && /^\s+$/.test(node.value)
}

scopedPlugin.postcss = true
export default scopedPlugin
24 changes: 16 additions & 8 deletions packages/compiler-sfc/src/stylePluginTrim.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import postcss, { Root } from 'postcss'
import { PluginCreator } from 'postcss'

export default postcss.plugin('trim', () => (css: Root) => {
css.walk(({ type, raws }) => {
if (type === 'rule' || type === 'atrule') {
if (raws.before) raws.before = '\n'
if (raws.after) raws.after = '\n'
const trimPlugin: PluginCreator<{}> = () => {
return {
postcssPlugin: 'vue-sfc-trim',
Once(root) {
root.walk(({ type, raws }) => {
if (type === 'rule' || type === 'atrule') {
if (raws.before) raws.before = '\n'
if ('after' in raws && raws.after) raws.after = '\n'
}
})
}
})
})
}
}

trimPlugin.postcss = true
export default trimPlugin
39 changes: 16 additions & 23 deletions packages/compiler-sfc/src/templateTransformAssetUrl.ts
Original file line number Diff line number Diff line change
@@ -113,26 +113,20 @@ export const transformAssetUrl: NodeTransform = (
}

const url = parseUrl(attr.value.content)
if (options.base) {
// explicit base - directly rewrite the url into absolute url
// does not apply to absolute urls or urls that start with `@`
// since they are aliases
if (
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 || '/'
if (options.base && attr.value.content[0] === '.') {
// explicit base - directly rewrite relative urls into absolute url
// to avoid generating extra imports
// 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 =
host +
(path.posix || path).join(basePath, url.path + (url.hash || ''))
}
// when packaged in the browser, path will be using the posix-
// only version provided by rollup-plugin-node-builtins.
attr.value.content =
host +
(path.posix || path).join(basePath, url.path + (url.hash || ''))
return
}

@@ -159,19 +153,18 @@ function getImportsExpressionExp(
context: TransformContext
): ExpressionNode {
if (path) {
const importsArray = Array.from(context.imports)
const existing = importsArray.find(i => i.path === path)
const existing = context.imports.find(i => i.path === path)
if (existing) {
return existing.exp as ExpressionNode
}
const name = `_imports_${importsArray.length}`
const name = `_imports_${context.imports.length}`
const exp = createSimpleExpression(
name,
false,
loc,
ConstantTypes.CAN_HOIST
)
context.imports.add({ exp, path })
context.imports.push({ exp, path })
if (hash && path) {
return context.hoist(
createSimpleExpression(
9 changes: 4 additions & 5 deletions packages/compiler-sfc/src/templateTransformSrcset.ts
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ export const transformSrcset: NodeTransform = (
if (attr.name === 'srcset' && attr.type === NodeTypes.ATTRIBUTE) {
if (!attr.value) return
const value = attr.value.content

if (!value) return
const imageCandidates: ImageCandidate[] = value.split(',').map(s => {
// The attribute value arrives here with all whitespace, except
// normal spaces, represented by escape sequences
@@ -99,8 +99,7 @@ export const transformSrcset: NodeTransform = (
const { path } = parseUrl(url)
let exp: SimpleExpressionNode
if (path) {
const importsArray = Array.from(context.imports)
const existingImportsIndex = importsArray.findIndex(
const existingImportsIndex = context.imports.findIndex(
i => i.path === path
)
if (existingImportsIndex > -1) {
@@ -112,12 +111,12 @@ export const transformSrcset: NodeTransform = (
)
} else {
exp = createSimpleExpression(
`_imports_${importsArray.length}`,
`_imports_${context.imports.length}`,
false,
attr.loc,
ConstantTypes.CAN_HOIST
)
context.imports.add({ exp, path })
context.imports.push({ exp, path })
}
compoundExpression.children.push(exp)
}
21 changes: 21 additions & 0 deletions packages/compiler-ssr/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018-present, Yuxi (Evan) You

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
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.5",
"version": "3.0.6",
"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.5",
"@vue/compiler-dom": "3.0.5"
"@vue/shared": "3.0.6",
"@vue/compiler-dom": "3.0.6"
}
}
18 changes: 10 additions & 8 deletions packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
Original file line number Diff line number Diff line change
@@ -289,14 +289,16 @@ function subTransform(
childContext.identifiers = { ...parentContext.identifiers }
// traverse
traverseNode(childRoot, childContext)
// merge helpers/components/directives/imports into parent context
;(['helpers', 'components', 'directives', 'imports'] as const).forEach(
key => {
childContext[key].forEach((value: any) => {
;(parentContext[key] as any).add(value)
})
}
)
// merge helpers/components/directives into parent context
;(['helpers', 'components', 'directives'] as const).forEach(key => {
childContext[key].forEach((value: any) => {
;(parentContext[key] as any).add(value)
})
})
// imports/hoists are not merged because:
// - imports are only used for asset urls and should be consistent between
// node/client branches
// - hoists are not enabled for the client branch here
}

function clone(v: any): any {
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.5",
"version": "3.0.6",
"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.5"
"@vue/shared": "3.0.6"
}
}
7 changes: 5 additions & 2 deletions packages/reactivity/src/baseHandlers.ts
Original file line number Diff line number Diff line change
@@ -22,10 +22,13 @@ import {
hasChanged,
isArray,
isIntegerKey,
extend
extend,
makeMap
} from '@vue/shared'
import { isRef } from './ref'

const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`)

const builtInSymbols = new Set(
Object.getOwnPropertyNames(Symbol)
.map(key => (Symbol as any)[key])
@@ -93,7 +96,7 @@ function createGetter(isReadonly = false, shallow = false) {
if (
isSymbol(key)
? builtInSymbols.has(key as symbol)
: key === `__proto__` || key === `__v_isRef`
: isNonTrackableKeys(key)
) {
return res
}
2 changes: 1 addition & 1 deletion packages/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ export interface Ref<T = any> {
_shallow?: boolean
}

export type ToRef<T> = T extends Ref ? T : Ref<UnwrapRef<T>>
export type ToRef<T> = [T] extends [Ref] ? T : Ref<UnwrapRef<T>>
export type ToRefs<T = any> = {
// #2687: somehow using ToRef<T[K]> here turns the resulting type into
// a union of multiple Ref<*> types instead of a single Ref<* | *> type.
4 changes: 2 additions & 2 deletions packages/runtime-core/__tests__/apiCreateApp.spec.ts
Original file line number Diff line number Diff line change
@@ -60,12 +60,12 @@ describe('api: createApp', () => {
const app = createApp(Comp)

// warning
app.unmount(root)
app.unmount()
expect(`that is not mounted`).toHaveBeenWarned()

app.mount(root)

app.unmount(root)
app.unmount()
expect(serializeInner(root)).toBe(``)
})

28 changes: 28 additions & 0 deletions packages/runtime-core/__tests__/apiExpose.spec.ts
Original file line number Diff line number Diff line change
@@ -141,4 +141,32 @@ describe('api: expose', () => {
expect(childRef.value).toBeTruthy()
expect(childRef.value.foo).toBe(1)
})

test('with $parent/$root', () => {
const Child = defineComponent({
render() {
expect((this.$parent! as any).foo).toBe(1)
expect((this.$parent! as any).bar).toBe(undefined)
expect((this.$root! as any).foo).toBe(1)
expect((this.$root! as any).bar).toBe(undefined)
}
})

const Parent = defineComponent({
expose: [],
setup(_, { expose }) {
expose({
foo: 1
})
return {
bar: 2
}
},
render() {
return h(Child)
}
})
const root = nodeOps.createElement('div')
render(h(Parent), root)
})
})
8 changes: 4 additions & 4 deletions packages/runtime-core/__tests__/apiInject.spec.ts
Original file line number Diff line number Diff line change
@@ -139,7 +139,7 @@ describe('api: provide/inject', () => {

const Consumer = {
setup() {
const count = inject('count') as Ref<number>
const count = inject<Ref<number>>('count')!
return () => count.value
}
}
@@ -169,7 +169,7 @@ describe('api: provide/inject', () => {

const Consumer = {
setup() {
const count = inject('count') as Ref<number>
const count = inject<Ref<number>>('count')!
// should not work
count.value++
return () => count.value
@@ -206,7 +206,7 @@ describe('api: provide/inject', () => {

const Consumer = {
setup() {
const state = inject('state') as typeof rootState
const state = inject<typeof rootState>('state')!
return () => state.count
}
}
@@ -236,7 +236,7 @@ describe('api: provide/inject', () => {

const Consumer = {
setup() {
const state = inject('state') as typeof rootState
const state = inject<typeof rootState>('state')!
// should not work
state.count++
return () => state.count
21 changes: 20 additions & 1 deletion packages/runtime-core/__tests__/apiOptions.spec.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,8 @@ import {
nextTick,
renderToString,
ref,
defineComponent
defineComponent,
createApp
} from '@vue/runtime-test'

describe('api: options', () => {
@@ -105,6 +106,24 @@ describe('api: options', () => {
expect(serializeInner(root)).toBe(`<div>2</div>`)
})

test('component’s own methods have higher priority than global properties', async () => {
const app = createApp({
methods: {
foo() {
return 'foo'
}
},
render() {
return this.foo()
}
})
app.config.globalProperties.foo = () => 'bar'

const root = nodeOps.createElement('div')
app.mount(root)
expect(serializeInner(root)).toBe(`foo`)
})

test('watch', async () => {
function returnThis(this: any) {
return this
22 changes: 21 additions & 1 deletion packages/runtime-core/__tests__/apiWatch.spec.ts
Original file line number Diff line number Diff line change
@@ -15,7 +15,8 @@ import {
nodeOps,
serializeInner,
TestElement,
h
h,
createApp
} from '@vue/runtime-test'
import {
ITERATE_KEY,
@@ -857,4 +858,23 @@ describe('api: watch', () => {

expect(instance!.effects![0].active).toBe(false)
})

test('this.$watch should pass `this.proxy` to watch source as the first argument ', () => {
let instance: any
const source = jest.fn()

const Comp = defineComponent({
render() {},
created(this: any) {
instance = this
this.$watch(source, function() {})
}
})

const root = nodeOps.createElement('div')
createApp(Comp).mount(root)

expect(instance).toBeDefined()
expect(source).toHaveBeenCalledWith(instance)
})
})
2 changes: 1 addition & 1 deletion packages/runtime-core/__tests__/componentEmits.spec.ts
Original file line number Diff line number Diff line change
@@ -140,7 +140,7 @@ describe('component: emit', () => {
})
render(h(Foo), nodeOps.createElement('div'))
expect(
`Component emitted event "bar" but it is neither declared`
`Component emitted event "foo" but it is neither declared`
).not.toHaveBeenWarned()
})

25 changes: 25 additions & 0 deletions packages/runtime-core/__tests__/componentProps.spec.ts
Original file line number Diff line number Diff line change
@@ -295,6 +295,10 @@ describe('component props', () => {
;(instance!.proxy as any).foo = 2
}).toThrow(TypeError)
expect(`Attempting to mutate prop "foo"`).toHaveBeenWarned()
// should not throw when overriding properties other than props
expect(() => {
;(instance!.proxy as any).hasOwnProperty = () => {}
}).not.toThrow(TypeError)
})

test('merging props from mixins and extends', () => {
@@ -378,4 +382,25 @@ describe('component props', () => {
expect(setupProps).toMatchObject(props)
expect(renderProxy.$props).toMatchObject(props)
})

test('props type support BigInt', () => {
const Comp = {
props: {
foo: BigInt
},
render(this: any) {
return h('div', [this.foo])
}
}

const root = nodeOps.createElement('div')
render(
h(Comp, {
foo: BigInt(BigInt(100000111)) + BigInt(2000000000) * BigInt(30000000)
}),
root
)

expect(serializeInner(root)).toMatch('<div>60000000100000111</div>')
})
})
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.5",
"version": "3.0.6",
"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.5",
"@vue/reactivity": "3.0.5"
"@vue/shared": "3.0.6",
"@vue/reactivity": "3.0.6"
}
}
4 changes: 2 additions & 2 deletions packages/runtime-core/src/apiAsyncComponent.ts
Original file line number Diff line number Diff line change
@@ -47,8 +47,8 @@ export function defineAsyncComponent<

const {
loader,
loadingComponent: loadingComponent,
errorComponent: errorComponent,
loadingComponent,
errorComponent,
delay = 200,
timeout, // undefined = never times out
suspensible = true,
3 changes: 2 additions & 1 deletion packages/runtime-core/src/apiCreateApp.ts
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ export interface App<HostElement = any> {
rootContainer: HostElement | string,
isHydrate?: boolean
): ComponentPublicInstance
unmount(rootContainer: HostElement | string): void
unmount(): void
provide<T>(key: InjectionKey<T> | string, value: T): this

// internal, but we need to expose these for the server-renderer and devtools
@@ -272,6 +272,7 @@ export function createAppAPI<HostElement>(
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
devtoolsUnmountApp(app)
}
delete app._container.__vue_app__
} else if (__DEV__) {
warn(`Cannot unmount an app that is not mounted.`)
}
16 changes: 10 additions & 6 deletions packages/runtime-core/src/apiWatch.ts
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ const INITIAL_WATCHER_VALUE = {}

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

// overload #1: array of multiple sources + cb
// overload: array of multiple sources + cb
export function watch<
T extends MultiWatchSources,
Immediate extends Readonly<boolean> = false
@@ -90,7 +90,7 @@ export function watch<
options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #2 for multiple sources w/ `as const`
// overload: multiple sources w/ `as const`
// watch([foo, bar] as const, () => {})
// somehow [...T] breaks when the type is readonly
export function watch<
@@ -102,14 +102,14 @@ export function watch<
options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #2: single source + cb
// overload: single source + cb
export function watch<T, Immediate extends Readonly<boolean> = false>(
source: WatchSource<T>,
cb: WatchCallback<T, Immediate extends true ? (T | undefined) : T>,
options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #3: watching reactive object w/ cb
// overload: watching reactive object w/ cb
export function watch<
T extends object,
Immediate extends Readonly<boolean> = false
@@ -181,7 +181,9 @@ function doWatch(
} else if (isReactive(s)) {
return traverse(s)
} else if (isFunction(s)) {
return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER)
return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER, [
instance && (instance.proxy as any)
])
} else {
__DEV__ && warnInvalidSource(s)
}
@@ -190,7 +192,9 @@ function doWatch(
if (cb) {
// getter with cb
getter = () =>
callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER)
callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER, [
instance && (instance.proxy as any)
])
} else {
// no cb -> simple effect
getter = () => {
15 changes: 7 additions & 8 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
@@ -56,7 +56,6 @@ import {
markAttrsAccessed
} from './componentRenderUtils'
import { startMeasure, endMeasure } from './profiling'
import { devtoolsComponentAdded } from './devtools'

export type Data = Record<string, unknown>

@@ -261,7 +260,7 @@ export interface ComponentInternalInstance {
*/
directives: Record<string, Directive> | null
/**
* reoslved props options
* resolved props options
* @internal
*/
propsOptions: NormalizedPropsOptions
@@ -486,10 +485,6 @@ export function createComponentInstance(
instance.root = parent ? parent.root : instance
instance.emit = emit.bind(null, instance)

if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
devtoolsComponentAdded(instance)
}

return instance
}

@@ -515,6 +510,10 @@ export function validateComponentName(name: string, config: AppConfig) {
}
}

export function isStatefulComponent(instance: ComponentInternalInstance) {
return instance.vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT
}

export let isInSSRComponentSetup = false

export function setupComponent(
@@ -523,8 +522,8 @@ export function setupComponent(
) {
isInSSRComponentSetup = isSSR

const { props, children, shapeFlag } = instance.vnode
const isStateful = shapeFlag & ShapeFlags.STATEFUL_COMPONENT
const { props, children } = instance.vnode
const isStateful = isStatefulComponent(instance)
initProps(instance, props, isStateful, isSSR)
initSlots(instance, children)

12 changes: 11 additions & 1 deletion packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
@@ -604,7 +604,17 @@ export function applyOptions(
for (const key in methods) {
const methodHandler = (methods as MethodOptions)[key]
if (isFunction(methodHandler)) {
ctx[key] = methodHandler.bind(publicThis)
// In dev mode, we use the `createRenderContext` function to define methods to the proxy target,
// and those are read-only but reconfigurable, so it needs to be redefined here
if (__DEV__) {
Object.defineProperty(ctx, key, {
value: methodHandler.bind(publicThis),
configurable: true,
enumerable: false
})
} else {
ctx[key] = methodHandler.bind(publicThis)
}
if (__DEV__) {
checkDuplicateProperties!(OptionTypes.METHODS, key)
}
6 changes: 4 additions & 2 deletions packages/runtime-core/src/componentProps.ts
Original file line number Diff line number Diff line change
@@ -97,7 +97,9 @@ type InferPropType<T> = T extends null
? Record<string, any>
: T extends BooleanConstructor | { type: BooleanConstructor }
? boolean
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T
: T extends DateConstructor | { type: DateConstructor }
? Date
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T

export type ExtractPropTypes<O> = O extends object
? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
@@ -510,7 +512,7 @@ function validateProp(
}

const isSimpleType = /*#__PURE__*/ makeMap(
'String,Number,Boolean,Function,Symbol'
'String,Number,Boolean,Function,Symbol,BigInt'
)

type AssertionResult = {
19 changes: 13 additions & 6 deletions packages/runtime-core/src/componentPublicInstance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ComponentInternalInstance, Data } from './component'
import {
ComponentInternalInstance,
Data,
isStatefulComponent
} from './component'
import { nextTick, queueJob } from './scheduler'
import { instanceWatch, WatchOptions, WatchStopHandle } from './apiWatch'
import {
@@ -207,8 +211,11 @@ type PublicPropertiesMap = Record<string, (i: ComponentInternalInstance) => any>
*/
const getPublicInstance = (
i: ComponentInternalInstance | null
): ComponentPublicInstance | null =>
i && (i.proxy ? i.proxy : getPublicInstance(i.parent))
): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null => {
if (!i) return null
if (isStatefulComponent(i)) return i.exposed ? i.exposed : i.proxy
return getPublicInstance(i.parent)
}

const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
$: i => i,
@@ -219,7 +226,7 @@ const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
$slots: i => (__DEV__ ? shallowReadonly(i.slots) : i.slots),
$refs: i => (__DEV__ ? shallowReadonly(i.refs) : i.refs),
$parent: i => getPublicInstance(i.parent),
$root: i => i.root && i.root.proxy,
$root: i => getPublicInstance(i.root),
$emit: i => i.emit,
$options: i => (__FEATURE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),
$forceUpdate: i => () => queueJob(i.update),
@@ -349,7 +356,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
)} must be accessed via $data because it starts with a reserved ` +
`character ("$" or "_") and is not proxied on the render context.`
)
} else {
} else if (instance === currentRenderingInstance) {
warn(
`Property ${JSON.stringify(key)} was accessed during render ` +
`but is not defined on instance.`
@@ -368,7 +375,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
setupState[key] = value
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
data[key] = value
} else if (key in instance.props) {
} else if (hasOwn(instance.props, key)) {
__DEV__ &&
warn(
`Attempting to mutate prop "${key}". Props are readonly.`,
6 changes: 5 additions & 1 deletion packages/runtime-core/src/componentRenderUtils.ts
Original file line number Diff line number Diff line change
@@ -119,7 +119,11 @@ export function renderComponentRoot(
// to have comments along side the root element which makes it a fragment
let root = result
let setRoot: ((root: VNode) => void) | undefined = undefined
if (__DEV__ && result.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT) {
if (
__DEV__ &&
result.patchFlag > 0 &&
result.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
) {
;[root, setRoot] = getChildRoot(result)
}

2 changes: 0 additions & 2 deletions packages/runtime-core/src/components/KeepAlive.ts
Original file line number Diff line number Diff line change
@@ -70,8 +70,6 @@ const KeepAliveImpl = {
// would prevent it from being tree-shaken.
__isKeepAlive: true,

inheritRef: true,

props: {
include: [String, RegExp, Array],
exclude: [String, RegExp, Array],
4 changes: 2 additions & 2 deletions packages/runtime-core/src/helpers/useSsrContext.ts
Original file line number Diff line number Diff line change
@@ -9,11 +9,11 @@ export const useSSRContext = <T = Record<string, any>>() => {
if (!ctx) {
warn(
`Server rendering context not provided. Make sure to only call ` +
`useSsrContext() conditionally in the server build.`
`useSSRContext() conditionally in the server build.`
)
}
return ctx
} else if (__DEV__) {
warn(`useSsrContext() is not supported in the global build.`)
warn(`useSSRContext() is not supported in the global build.`)
}
}
2 changes: 1 addition & 1 deletion packages/runtime-core/src/hmr.ts
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ function createRecord(
warn(
`HMR API usage is out of date.\n` +
`Please upgrade vue-loader/vite/rollup-plugin-vue or other relevant ` +
`depdendency that handles Vue SFC compilation.`
`dependency that handles Vue SFC compilation.`
)
component = {}
}
10 changes: 9 additions & 1 deletion packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
@@ -72,7 +72,11 @@ import { createHydrationFunctions, RootHydrateFunction } from './hydration'
import { invokeDirectiveHook } from './directives'
import { startMeasure, endMeasure } from './profiling'
import { ComponentPublicInstance } from './componentPublicInstance'
import { devtoolsComponentRemoved, devtoolsComponentUpdated } from './devtools'
import {
devtoolsComponentAdded,
devtoolsComponentRemoved,
devtoolsComponentUpdated
} from './devtools'
import { initFeatureFlags } from './featureFlags'
import { isAsyncWrapper } from './apiAsyncComponent'

@@ -1412,6 +1416,10 @@ function baseCreateRenderer(
}
instance.isMounted = true

if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
devtoolsComponentAdded(instance)
}

// #2458: deference mount-only object parameters to prevent memleaks
initialVNode = container = anchor = null as any
} else {
19 changes: 17 additions & 2 deletions packages/runtime-core/src/vnode.ts
Original file line number Diff line number Diff line change
@@ -459,7 +459,7 @@ export function cloneVNode<T, U>(
): VNode<T, U> {
// This is intentionally NOT using spread or extend to avoid the runtime
// key enumeration cost.
const { props, ref, patchFlag } = vnode
const { props, ref, patchFlag, children } = vnode
const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props
return {
__v_isVNode: true,
@@ -479,7 +479,10 @@ export function cloneVNode<T, U>(
: normalizeRef(extraProps)
: ref,
scopeId: vnode.scopeId,
children: vnode.children,
children:
__DEV__ && patchFlag === PatchFlags.HOISTED && isArray(children)
? (children as VNode[]).map(deepCloneVNode)
: children,
target: vnode.target,
targetAnchor: vnode.targetAnchor,
staticCount: vnode.staticCount,
@@ -513,6 +516,18 @@ export function cloneVNode<T, U>(
}
}

/**
* Dev only, for HMR of hoisted vnodes reused in v-for
* https://github.com/vitejs/vite/issues/2022
*/
function deepCloneVNode(vnode: VNode): VNode {
const cloned = cloneVNode(vnode)
if (isArray(vnode.children)) {
cloned.children = (vnode.children as VNode[]).map(deepCloneVNode)
}
return cloned
}

/**
* @private
*/
26 changes: 26 additions & 0 deletions packages/runtime-dom/__tests__/patchEvents.spec.ts
Original file line number Diff line number Diff line change
@@ -153,4 +153,30 @@ describe(`runtime-dom: events patching`, () => {
expect(prevFn).toHaveBeenCalledTimes(2)
expect(nextFn).toHaveBeenCalledTimes(4)
})

// #2841
test('should patch event correctly in web-components', async () => {
class TestElement extends HTMLElement {
constructor() {
super()
}
}
window.customElements.define('test-element', TestElement)
const testElement = document.createElement('test-element', {
is: 'test-element'
})
const fn1 = jest.fn()
const fn2 = jest.fn()

// in webComponents, @foo-bar will patch prop 'onFooBar'
// and @foobar will patch prop 'onFoobar'

patchProp(testElement, 'onFooBar', null, fn1)
testElement.dispatchEvent(new CustomEvent('foo-bar'))
expect(fn1).toHaveBeenCalledTimes(1)

patchProp(testElement, 'onFoobar', null, fn2)
testElement.dispatchEvent(new CustomEvent('foobar'))
expect(fn2).toHaveBeenCalledTimes(1)
})
})
10 changes: 10 additions & 0 deletions packages/runtime-dom/__tests__/patchProps.spec.ts
Original file line number Diff line number Diff line change
@@ -145,5 +145,15 @@ describe('runtime-dom: props patching', () => {
// non existant element
expect(el.form).toBe(null)
expect(el.getAttribute('form')).toBe('foo')
// remove attribute
patchProp(el, 'form', 'foo', null)
expect(el.getAttribute('form')).toBe(null)
})

test('readonly type prop on textarea', () => {
const el = document.createElement('textarea')
// just to verify that it doesn't throw when i.e. switching a dynamic :is from an 'input' to a 'textarea'
// see https://github.com/vuejs/vue-next/issues/2766
patchProp(el, 'type', 'text', 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.5",
"version": "3.0.6",
"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.5",
"@vue/runtime-core": "3.0.5",
"@vue/shared": "3.0.6",
"@vue/runtime-core": "3.0.6",
"csstype": "^2.6.8"
}
}
2 changes: 1 addition & 1 deletion packages/runtime-dom/src/index.ts
Original file line number Diff line number Diff line change
@@ -119,7 +119,7 @@ function normalizeContainer(
}
if (
__DEV__ &&
container instanceof ShadowRoot &&
container instanceof window.ShadowRoot &&
container.mode === 'closed'
) {
warn(
4 changes: 2 additions & 2 deletions packages/runtime-dom/src/modules/events.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isArray } from '@vue/shared'
import { hyphenate, isArray } from '@vue/shared'
import {
ComponentInternalInstance,
callWithAsyncErrorHandling
@@ -96,7 +96,7 @@ function parseName(name: string): [string, EventListenerOptions | undefined] {
options
}
}
return [name.slice(2).toLowerCase(), options]
return [hyphenate(name.slice(2)), options]
}

function createInvoker(
11 changes: 8 additions & 3 deletions packages/runtime-dom/src/patchProp.ts
Original file line number Diff line number Diff line change
@@ -93,9 +93,9 @@ function shouldSetAsProp(
return false
}

// #1787 form as an attribute must be a string, while it accepts an Element as
// a prop
if (key === 'form' && typeof value === 'string') {
// #1787, #2840 form property on form elements is readonly and must be set as
// attribute.
if (key === 'form') {
return false
}

@@ -104,6 +104,11 @@ function shouldSetAsProp(
return false
}

// #2766 <textarea type> must be set as attribute
if (key === 'type' && el.tagName === 'TEXTAREA') {
return false
}

// native onclick with string value, must be set as attribute
if (nativeOnRE.test(key) && isString(value)) {
return false
2 changes: 2 additions & 0 deletions packages/runtime-dom/types/jsx.d.ts
Original file line number Diff line number Diff line change
@@ -1214,6 +1214,8 @@ export interface Events {

// focus events
onFocus: FocusEvent
onFocusin: FocusEvent
onFocusout: FocusEvent
onBlur: FocusEvent

// form events
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.5",
"version": "3.0.6",
"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.5",
"@vue/runtime-core": "3.0.5"
"@vue/shared": "3.0.6",
"@vue/runtime-core": "3.0.6"
}
}
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.5",
"version": "3.0.6",
"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.5"
"vue": "3.0.6"
},
"dependencies": {
"@vue/shared": "3.0.5",
"@vue/compiler-ssr": "3.0.5"
"@vue/shared": "3.0.6",
"@vue/compiler-ssr": "3.0.6"
}
}
21 changes: 21 additions & 0 deletions packages/shared/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018-present, Yuxi (Evan) You

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
17 changes: 17 additions & 0 deletions packages/shared/__tests__/normalizeProp.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { normalizeClass } from '../src'

describe('normalizeClass', () => {
test('handles string correctly', () => {
expect(normalizeClass('foo')).toEqual('foo')
})

test('handles array correctly', () => {
expect(normalizeClass(['foo', undefined, true, false, 'bar'])).toEqual('foo bar')
})

test('handles object correctly', () => {
expect(normalizeClass({ foo: true, bar: false, baz: true })).toEqual(
'foo baz'
)
})
})
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.5",
"version": "3.0.6",
"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/globalsWhitelist.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@ import { makeMap } from './makeMap'
const GLOBALS_WHITE_LISTED =
'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl'
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt'

export const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED)
5 changes: 4 additions & 1 deletion packages/shared/src/normalizeProp.ts
Original file line number Diff line number Diff line change
@@ -62,7 +62,10 @@ export function normalizeClass(value: unknown): string {
res = value
} else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
res += normalizeClass(value[i]) + ' '
const normalized = normalizeClass(value[i])
if (normalized) {
res += normalized + ' '
}
}
} else if (isObject(value)) {
for (const name in value) {
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.5",
"version": "3.0.6",
"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.5",
"version": "3.0.6",
"private": true,
"buildOptions": {
"formats": [
21 changes: 21 additions & 0 deletions packages/vue/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018-present, Yuxi (Evan) You

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
9 changes: 9 additions & 0 deletions packages/vue/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -292,4 +292,13 @@ describe('compiler + runtime integration', () => {
createApp(App).mount(container)
expect(EMPTY_ARR.length).toBe(0)
})

test('BigInt support', () => {
const app = createApp({
template: `<div>{{ BigInt(BigInt(100000111)) + BigInt(2000000000n) * 30000000n }}</div>`
})
const root = document.createElement('div')
app.mount(root)
expect(root.innerHTML).toBe('<div>60000000100000111</div>')
})
})
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.5",
"version": "3.0.6",
"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.5",
"@vue/compiler-dom": "3.0.5",
"@vue/runtime-dom": "3.0.5"
"@vue/shared": "3.0.6",
"@vue/compiler-dom": "3.0.6",
"@vue/runtime-dom": "3.0.6"
},
"devDependencies": {
"lodash": "^4.17.15",
4 changes: 3 additions & 1 deletion packages/vue/src/index.ts
Original file line number Diff line number Diff line change
@@ -7,7 +7,9 @@ import * as runtimeDom from '@vue/runtime-dom'
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
import { InternalRenderFunction } from 'packages/runtime-core/src/component'

__DEV__ && initDev()
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
initDev()
}

const compileCache: Record<string, RenderFunction> = Object.create(null)

4 changes: 3 additions & 1 deletion packages/vue/src/runtime.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,9 @@
import { initDev } from './dev'
import { warn } from '@vue/runtime-dom'

__DEV__ && initDev()
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
initDev()
}

export * from '@vue/runtime-dom'

5 changes: 4 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
@@ -235,7 +235,10 @@ function createReplacePlugin(
replacements[key] = process.env[key]
}
})
return replace(replacements)
return replace({
values: replacements,
preventAssignment: true
})
}

function createProductionConfig(format) {
5 changes: 4 additions & 1 deletion test-dts/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ describe('with object props', () => {
ggg: 'foo' | 'bar'
ffff: (a: number, b: string) => { a: boolean }
validated?: string
date?: Date
}

type GT = string & { __brand: unknown }
@@ -103,7 +104,8 @@ describe('with object props', () => {
type: String,
// validator requires explicit annotation
validator: (val: unknown) => val !== ''
}
},
date: Date
},
setup(props) {
// type assertion. See https://github.com/SamVerschueren/tsd
@@ -125,6 +127,7 @@ describe('with object props', () => {
expectType<ExpectedProps['ggg']>(props.ggg)
expectType<ExpectedProps['ffff']>(props.ffff)
expectType<ExpectedProps['validated']>(props.validated)
expectType<ExpectedProps['date']>(props.date)

// @ts-expect-error props should be readonly
expectError((props.a = 1))
11 changes: 10 additions & 1 deletion test-dts/ref.test-d.ts
Original file line number Diff line number Diff line change
@@ -9,7 +9,8 @@ import {
proxyRefs,
toRef,
toRefs,
ToRefs
ToRefs,
watch
} from './index'

function plainType(arg: number | Ref<number>) {
@@ -165,6 +166,14 @@ const obj = {
expectType<Ref<number>>(toRef(obj, 'a'))
expectType<Ref<number>>(toRef(obj, 'b'))

const objWithUnionProp: { a: string | number } = {
a: 1
}

watch(toRef(objWithUnionProp, 'a'), value => {
expectType<string | number>(value)
})

// toRefs
const objRefs = toRefs(obj)
expectType<{
338 changes: 164 additions & 174 deletions yarn.lock

Large diffs are not rendered by default.