From 60d6f2f748382c63317540b73ba79354c0129871 Mon Sep 17 00:00:00 2001 From: Hiroki Osame Date: Wed, 17 May 2023 23:56:55 +0900 Subject: [PATCH] fix: compatibility with vue 2.7 provide --- dist/proxi.cjs.js | 2 +- dist/proxi.esm.js | 2 +- dist/proxi.js | 2 +- package.json | 2 +- src/utils.js | 22 +++++++++++++--- test/proxi.unit.test.js | 56 ++++++++++++++++++++++++++++++++++++++++- 6 files changed, 78 insertions(+), 8 deletions(-) diff --git a/dist/proxi.cjs.js b/dist/proxi.cjs.js index 71a04f3..39ea2c5 100644 --- a/dist/proxi.cjs.js +++ b/dist/proxi.cjs.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var r=require("vue"),t=Object.prototype.hasOwnProperty,e=function(r,e){return t.call(r,e)},n=/-(\w)/g,i={functional:!0,props:{proxiKey:{type:[Symbol,String],required:!0}},render:function(t,e){var n=e.props.proxiKey;if(n){var i=e.data;!function(t,e,n){t._provided||(t._provided={}),t._provided[e]?Object.assign(t._provided[e],n):t._provided[e]=r.observable(n)}(e.parent,n,{data:i})}return e.slots().default}},o="_proxi_",u=Object.freeze({}),c={class:void 0,listeners:u,attrs:u,props:u};exports.ProxiInject=function(r){var t,i=void 0===r?{}:r,u=i.from,s=i.props,a=void 0===s?[]:s;return{inject:(t={},t[o]={from:u,default:void 0},t),created:function(){var r=(this[o]||{}).data;if(r)for(var t in r.on)e(r.on,t)&&this.$on(t,r.on[t])},computed:a.reduce((function(r,t){return r[t]=function(){return this.$$.props[t]},r}),{$$:function(){var r=(this[o]||{}).data,t=Object.create(c);return r?Object.assign(t,{class:r.staticClass||r.class?[r.staticClass,r.class]:void 0,listeners:r.on},function(r,t){var i={};for(var o in t)if(e(t,o)){var u=o.replace(n,(function(r,t){return t?t.toUpperCase():""})),c=t[o];r.includes(u)&&(i[u]=c,delete t[o])}return{attrs:t,props:i}}(a,Object.assign({},r.attrs))):t}})}},exports.default=i; +"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var r=require("vue"),t=Object.prototype.hasOwnProperty,e=function(r,e){return t.call(r,e)},n=/-(\w)/g,i={functional:!0,props:{proxiKey:{type:[Symbol,String],required:!0}},render:function(t,n){var i=n.props.proxiKey;if(i){var o=n.data;!function(t,n,i){if(t._provided){var o=t._provided,u=t.$parent&&t.$parent._provided;o===u&&(t._provided=Object.create(u))}else t._provided={};var s=t._provided[n];if(s)for(var c in i)e(i,c)&&r.set(s,c,i[c]);else t._provided[n]=r.observable(i)}(n.parent,i,{data:o})}return n.slots().default}},o="_proxi_",u=Object.freeze({}),s={class:void 0,listeners:u,attrs:u,props:u};exports.ProxiInject=function(r){var t,i=void 0===r?{}:r,u=i.from,c=i.props,a=void 0===c?[]:c;return{inject:(t={},t[o]={from:u,default:void 0},t),created:function(){var r=(this[o]||{}).data;if(r)for(var t in r.on)e(r.on,t)&&this.$on(t,r.on[t])},computed:a.reduce((function(r,t){return r[t]=function(){return this.$$.props[t]},r}),{$$:function(){var r=(this[o]||{}).data,t=Object.create(s);return r?Object.assign(t,{class:r.staticClass||r.class?[r.staticClass,r.class]:void 0,listeners:r.on},function(r,t){var i={};for(var o in t)if(e(t,o)){var u=o.replace(n,(function(r,t){return t?t.toUpperCase():""})),s=t[o];r.includes(u)&&(i[u]=s,delete t[o])}return{attrs:t,props:i}}(a,Object.assign({},r.attrs))):t}})}},exports.default=i; diff --git a/dist/proxi.esm.js b/dist/proxi.esm.js index eca84e1..8858f04 100644 --- a/dist/proxi.esm.js +++ b/dist/proxi.esm.js @@ -1 +1 @@ -import r from"vue";var t=Object.prototype.hasOwnProperty,n=function(r,n){return t.call(r,n)},e=/-(\w)/g,i={functional:!0,props:{proxiKey:{type:[Symbol,String],required:!0}},render:function(t,n){var e=n.props.proxiKey;if(e){var i=n.data;!function(t,n,e){t._provided||(t._provided={}),t._provided[n]?Object.assign(t._provided[n],e):t._provided[n]=r.observable(e)}(n.parent,e,{data:i})}return n.slots().default}},o="_proxi_",u=Object.freeze({}),c={class:void 0,listeners:u,attrs:u,props:u},a=function(r){var t,i=void 0===r?{}:r,u=i.from,a=i.props,f=void 0===a?[]:a;return{inject:(t={},t[o]={from:u,default:void 0},t),created:function(){var r=(this[o]||{}).data;if(r)for(var t in r.on)n(r.on,t)&&this.$on(t,r.on[t])},computed:f.reduce((function(r,t){return r[t]=function(){return this.$$.props[t]},r}),{$$:function(){var r=(this[o]||{}).data,t=Object.create(c);return r?Object.assign(t,{class:r.staticClass||r.class?[r.staticClass,r.class]:void 0,listeners:r.on},function(r,t){var i={};for(var o in t)if(n(t,o)){var u=o.replace(e,(function(r,t){return t?t.toUpperCase():""})),c=t[o];r.includes(u)&&(i[u]=c,delete t[o])}return{attrs:t,props:i}}(f,Object.assign({},r.attrs))):t}})}};export{a as ProxiInject,i as default}; +import r from"vue";var t=Object.prototype.hasOwnProperty,e=function(r,e){return t.call(r,e)},n=/-(\w)/g,i={functional:!0,props:{proxiKey:{type:[Symbol,String],required:!0}},render:function(t,n){var i=n.props.proxiKey;if(i){var o=n.data;!function(t,n,i){if(t._provided){var o=t._provided,a=t.$parent&&t.$parent._provided;o===a&&(t._provided=Object.create(a))}else t._provided={};var u=t._provided[n];if(u)for(var f in i)e(i,f)&&r.set(u,f,i[f]);else t._provided[n]=r.observable(i)}(n.parent,i,{data:o})}return n.slots().default}},o="_proxi_",a=Object.freeze({}),u={class:void 0,listeners:a,attrs:a,props:a},f=function(r){var t,i=void 0===r?{}:r,a=i.from,f=i.props,c=void 0===f?[]:f;return{inject:(t={},t[o]={from:a,default:void 0},t),created:function(){var r=(this[o]||{}).data;if(r)for(var t in r.on)e(r.on,t)&&this.$on(t,r.on[t])},computed:c.reduce((function(r,t){return r[t]=function(){return this.$$.props[t]},r}),{$$:function(){var r=(this[o]||{}).data,t=Object.create(u);return r?Object.assign(t,{class:r.staticClass||r.class?[r.staticClass,r.class]:void 0,listeners:r.on},function(r,t){var i={};for(var o in t)if(e(t,o)){var a=o.replace(n,(function(r,t){return t?t.toUpperCase():""})),u=t[o];r.includes(a)&&(i[a]=u,delete t[o])}return{attrs:t,props:i}}(c,Object.assign({},r.attrs))):t}})}};export{f as ProxiInject,i as default}; diff --git a/dist/proxi.js b/dist/proxi.js index aba853e..bad3f95 100644 --- a/dist/proxi.js +++ b/dist/proxi.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Proxi={},e.Vue)}(this,(function(e,t){"use strict";var n=Object.prototype.hasOwnProperty,r=function(e,t){return n.call(e,t)},i=/-(\w)/g,o={functional:!0,props:{proxiKey:{type:[Symbol,String],required:!0}},render:function(e,n){var r=n.props.proxiKey;if(r){var i=n.data;!function(e,n,r){e._provided||(e._provided={}),e._provided[n]?Object.assign(e._provided[n],r):e._provided[n]=t.observable(r)}(n.parent,r,{data:i})}return n.slots().default}},u="_proxi_",f=Object.freeze({}),c={class:void 0,listeners:f,attrs:f,props:f};e.ProxiInject=function(e){var t,n=void 0===e?{}:e,o=n.from,f=n.props,s=void 0===f?[]:f;return{inject:(t={},t[u]={from:o,default:void 0},t),created:function(){var e=(this[u]||{}).data;if(e)for(var t in e.on)r(e.on,t)&&this.$on(t,e.on[t])},computed:s.reduce((function(e,t){return e[t]=function(){return this.$$.props[t]},e}),{$$:function(){var e=(this[u]||{}).data,t=Object.create(c);return e?Object.assign(t,{class:e.staticClass||e.class?[e.staticClass,e.class]:void 0,listeners:e.on},function(e,t){var n={};for(var o in t)if(r(t,o)){var u=o.replace(i,(function(e,t){return t?t.toUpperCase():""})),f=t[o];e.includes(u)&&(n[u]=f,delete t[o])}return{attrs:t,props:n}}(s,Object.assign({},e.attrs))):t}})}},e.default=o,Object.defineProperty(e,"__esModule",{value:!0})})); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Proxi={},e.Vue)}(this,(function(e,t){"use strict";var r=Object.prototype.hasOwnProperty,n=function(e,t){return r.call(e,t)},i=/-(\w)/g,o={functional:!0,props:{proxiKey:{type:[Symbol,String],required:!0}},render:function(e,r){var i=r.props.proxiKey;if(i){var o=r.data;!function(e,r,i){if(e._provided){var o=e._provided,f=e.$parent&&e.$parent._provided;o===f&&(e._provided=Object.create(f))}else e._provided={};var u=e._provided[r];if(u)for(var s in i)n(i,s)&&t.set(u,s,i[s]);else e._provided[r]=t.observable(i)}(r.parent,i,{data:o})}return r.slots().default}},f="_proxi_",u=Object.freeze({}),s={class:void 0,listeners:u,attrs:u,props:u};e.ProxiInject=function(e){var t,r=void 0===e?{}:e,o=r.from,u=r.props,c=void 0===u?[]:u;return{inject:(t={},t[f]={from:o,default:void 0},t),created:function(){var e=(this[f]||{}).data;if(e)for(var t in e.on)n(e.on,t)&&this.$on(t,e.on[t])},computed:c.reduce((function(e,t){return e[t]=function(){return this.$$.props[t]},e}),{$$:function(){var e=(this[f]||{}).data,t=Object.create(s);return e?Object.assign(t,{class:e.staticClass||e.class?[e.staticClass,e.class]:void 0,listeners:e.on},function(e,t){var r={};for(var o in t)if(n(t,o)){var f=o.replace(i,(function(e,t){return t?t.toUpperCase():""})),u=t[o];e.includes(f)&&(r[f]=u,delete t[o])}return{attrs:t,props:r}}(c,Object.assign({},e.attrs))):t}})}},e.default=o,Object.defineProperty(e,"__esModule",{value:!0})})); diff --git a/package.json b/package.json index 5e5c402..aa4a2e0 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "lint-staged": { "*.{js,ts,vue}": [ "eslint --cache", - "pnpm test" + "vitest related --run" ] }, "devDependencies": { diff --git a/src/utils.js b/src/utils.js index 0a77aef..0adf05d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -9,12 +9,28 @@ const camelizeRE = /-(\w)/g; export const camelize = string => string.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); export const initProvide = (parent, key, object) => { - if (!parent._provided) { + /** + * New behavior introduced in 2.7.0 to always use the parent provide + * if not specified by the component. + * https://github.com/vuejs/vue/blob/v2.7.0/src/v3/apiInject.ts#L26 + */ + if (parent._provided) { + const provides = parent._provided; + const parentProvides = parent.$parent && parent.$parent._provided; + if (provides === parentProvides) { + parent._provided = Object.create(parentProvides); + } + } else { parent._provided = {}; } - if (parent._provided[key]) { - Object.assign(parent._provided[key], object); + const providedEntry = parent._provided[key]; + if (providedEntry) { + for (const prop in object) { + if (hasOwn(object, prop)) { + Vue.set(providedEntry, prop, object[prop]); + } + } } else { parent._provided[key] = Vue.observable(object); } diff --git a/test/proxi.unit.test.js b/test/proxi.unit.test.js index 9e1a4b4..3343c2f 100644 --- a/test/proxi.unit.test.js +++ b/test/proxi.unit.test.js @@ -6,7 +6,7 @@ import { } from 'vitest'; import Vue from 'vue'; import { mount } from '@vue/test-utils'; -import Proxi, { ProxiInject } from '..'; +import Proxi, { ProxiInject } from '../src/index.js'; describe('Error handling - Proxi', () => { test('No key - empty', () => { @@ -580,4 +580,58 @@ describe('Proxi', () => { expect(child2.attributes('some-attr')).toBe('321'); expect(child2.text()).toBe('Child 100'); }); + + test('Shared parent Vue 2.7 bug', async () => { + const key = Symbol('key'); + + const Child = { + mixins: [ + ProxiInject({ + from: key, + }), + ], + template: '
', + }; + + const Parent = { + template: ` + + + + `, + components: { + Proxi, + }, + data() { + return { key }; + }, + }; + + const usage = { + template: ` +
+ + + + + + +
+ `, + components: { + Parent, + Child, + }, + }; + + const wrapper = mount(usage); + + await Vue.nextTick(); + + const html = wrapper.html().replaceAll(/\n|\s{2,}/g, ''); + expect(html).toBe('
'); + }); });