From a13fc5a6f94bab2fd14c6f2a827188cf0d29917a Mon Sep 17 00:00:00 2001 From: Gleb Ivanov Date: Mon, 19 Feb 2018 18:49:00 +0400 Subject: [PATCH 1/6] Added reflection support --- dist/vue-class-component.common.js | 28 ++++++++++++++++++++++-- dist/vue-class-component.js | 35 +++++++++++++++++++++++++----- dist/vue-class-component.min.js | 2 +- package-lock.json | 6 +++++ package.json | 3 +++ src/component.ts | 20 +++++++++++++++-- src/reflect.ts | 29 +++++++++++++++++++++++++ test/test.ts | 20 +++++++++++++++++ 8 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 src/reflect.ts diff --git a/dist/vue-class-component.common.js b/dist/vue-class-component.common.js index 6b1763c..478cc13 100644 --- a/dist/vue-class-component.common.js +++ b/dist/vue-class-component.common.js @@ -9,8 +9,25 @@ Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } +require('reflect-metadata'); var Vue = _interopDefault(require('vue')); +function copyReflectionMetadata(from, to, reflectionMap) { + shallowCopy(from.prototype, to.prototype, reflectionMap.instance); + shallowCopy(from, to, reflectionMap.static); +} +function shallowCopy(from, to, propertyKeys) { + var _loop_1 = function (propertyKey) { + propertyKeys[propertyKey].forEach(function (metadataKey) { + var metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey); + Reflect.defineMetadata(metadataKey, metadata, to, propertyKey); + }); + }; + for (var propertyKey in propertyKeys) { + _loop_1(propertyKey); + } +} + var hasProto = { __proto__: [] } instanceof Array; function createDecorator(factory) { return function (target, key, index) { @@ -105,6 +122,10 @@ var $internalHooks = [ ]; function componentFactory(Component, options) { if (options === void 0) { options = {}; } + var reflectionMap = { + instance: {}, + static: {} + }; options.name = options.name || Component._componentTag || Component.name; // prototype props. var proto = Component.prototype; @@ -112,6 +133,7 @@ function componentFactory(Component, options) { if (key === 'constructor') { return; } + reflectionMap.instance[key] = Reflect.getOwnMetadataKeys(proto, key); // hooks if ($internalHooks.indexOf(key) > -1) { options[key] = proto[key]; @@ -147,7 +169,8 @@ function componentFactory(Component, options) { ? superProto.constructor : Vue; var Extended = Super.extend(options); - forwardStaticMembers(Extended, Component, Super); + forwardStaticMembersAndCollectReflection(Extended, Component, Super, reflectionMap); + copyReflectionMetadata(Component, Extended, reflectionMap); return Extended; } var reservedPropertyNames = [ @@ -165,13 +188,14 @@ var reservedPropertyNames = [ 'directive', 'filter' ]; -function forwardStaticMembers(Extended, Original, Super) { +function forwardStaticMembersAndCollectReflection(Extended, Original, Super, reflectionMap) { // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable Object.getOwnPropertyNames(Original).forEach(function (key) { // `prototype` should not be overwritten if (key === 'prototype') { return; } + reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key); // Some browsers does not allow reconfigure built-in properties var extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key); if (extendedDescriptor && !extendedDescriptor.configurable) { diff --git a/dist/vue-class-component.js b/dist/vue-class-component.js index 6a22752..9cfbc01 100644 --- a/dist/vue-class-component.js +++ b/dist/vue-class-component.js @@ -4,13 +4,29 @@ * @license MIT */ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) : - typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) : - (factory((global.VueClassComponent = {}),global.Vue)); -}(this, (function (exports,Vue) { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('reflect-metadata'), require('vue')) : + typeof define === 'function' && define.amd ? define(['exports', 'reflect-metadata', 'vue'], factory) : + (factory((global.VueClassComponent = {}),null,global.Vue)); +}(this, (function (exports,reflectMetadata,Vue) { 'use strict'; Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue; +function copyReflectionMetadata(from, to, reflectionMap) { + shallowCopy(from.prototype, to.prototype, reflectionMap.instance); + shallowCopy(from, to, reflectionMap.static); +} +function shallowCopy(from, to, propertyKeys) { + var _loop_1 = function (propertyKey) { + propertyKeys[propertyKey].forEach(function (metadataKey) { + var metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey); + Reflect.defineMetadata(metadataKey, metadata, to, propertyKey); + }); + }; + for (var propertyKey in propertyKeys) { + _loop_1(propertyKey); + } +} + var hasProto = { __proto__: [] } instanceof Array; function createDecorator(factory) { return function (target, key, index) { @@ -105,6 +121,10 @@ var $internalHooks = [ ]; function componentFactory(Component, options) { if (options === void 0) { options = {}; } + var reflectionMap = { + instance: {}, + static: {} + }; options.name = options.name || Component._componentTag || Component.name; // prototype props. var proto = Component.prototype; @@ -112,6 +132,7 @@ function componentFactory(Component, options) { if (key === 'constructor') { return; } + reflectionMap.instance[key] = Reflect.getOwnMetadataKeys(proto, key); // hooks if ($internalHooks.indexOf(key) > -1) { options[key] = proto[key]; @@ -147,7 +168,8 @@ function componentFactory(Component, options) { ? superProto.constructor : Vue; var Extended = Super.extend(options); - forwardStaticMembers(Extended, Component, Super); + forwardStaticMembersAndCollectReflection(Extended, Component, Super, reflectionMap); + copyReflectionMetadata(Component, Extended, reflectionMap); return Extended; } var reservedPropertyNames = [ @@ -165,13 +187,14 @@ var reservedPropertyNames = [ 'directive', 'filter' ]; -function forwardStaticMembers(Extended, Original, Super) { +function forwardStaticMembersAndCollectReflection(Extended, Original, Super, reflectionMap) { // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable Object.getOwnPropertyNames(Original).forEach(function (key) { // `prototype` should not be overwritten if (key === 'prototype') { return; } + reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key); // Some browsers does not allow reconfigure built-in properties var extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key); if (extendedDescriptor && !extendedDescriptor.configurable) { diff --git a/dist/vue-class-component.min.js b/dist/vue-class-component.min.js index 4dbf8b4..0ce2e17 100644 --- a/dist/vue-class-component.min.js +++ b/dist/vue-class-component.min.js @@ -3,4 +3,4 @@ * (c) 2015-present Evan You * @license MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],t):t(e.VueClassComponent={},e.Vue)}(this,function(e,t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var r={__proto__:[]}instanceof Array;var o=["data","beforeCreate","created","beforeMount","mounted","beforeDestroy","destroyed","beforeUpdate","updated","activated","deactivated","render","errorCaptured"];function n(e,n){void 0===n&&(n={}),n.name=n.name||e._componentTag||e.name;var i=e.prototype;Object.getOwnPropertyNames(i).forEach(function(e){if("constructor"!==e)if(o.indexOf(e)>-1)n[e]=i[e];else{var t=Object.getOwnPropertyDescriptor(i,e);"function"==typeof t.value?(n.methods||(n.methods={}))[e]=t.value:(t.get||t.set)&&((n.computed||(n.computed={}))[e]={get:t.get,set:t.set})}}),(n.mixins||(n.mixins=[])).push({data:function(){return function(e,t){var r=t.prototype._init;t.prototype._init=function(){var t=this,r=Object.getOwnPropertyNames(e);if(e.$options.props)for(var o in e.$options.props)e.hasOwnProperty(o)||r.push(o);r.forEach(function(r){"_"!==r.charAt(0)&&Object.defineProperty(t,r,{get:function(){return e[r]},set:function(t){return e[r]=t},configurable:!0})})};var o=new t;t.prototype._init=r;var n={};return Object.keys(o).forEach(function(e){void 0!==o[e]&&(n[e]=o[e])}),n}(this,e)}});var c=e.__decorators__;c&&(c.forEach(function(e){return e(n)}),delete e.__decorators__);var u,a,f,p=Object.getPrototypeOf(e.prototype),s=p instanceof t?p.constructor:t,d=s.extend(n);return u=d,a=e,f=s,Object.getOwnPropertyNames(a).forEach(function(e){if("prototype"!==e){var t=Object.getOwnPropertyDescriptor(u,e);if(!t||t.configurable){var o,n,i=Object.getOwnPropertyDescriptor(a,e);if(!r){if("cid"===e)return;var c=Object.getOwnPropertyDescriptor(f,e);if(o=i.value,n=typeof o,null!=o&&("object"===n||"function"===n)&&c&&c.value===i.value)return}Object.defineProperty(u,e,i)}}}),d}function i(e){return"function"==typeof e?n(e):function(t){return n(t,e)}}!function(e){(i||(i={})).registerHooks=function(e){o.push.apply(o,e)}}();var c=i;e.default=c,e.createDecorator=function(e){return function(t,r,o){var n="function"==typeof t?t:t.constructor;n.__decorators__||(n.__decorators__=[]),"number"!=typeof o&&(o=void 0),n.__decorators__.push(function(t){return e(t,r,o)})}},e.mixins=function(){for(var e=[],r=0;r-1)t[e]=i[e];else{var r=Object.getOwnPropertyDescriptor(i,e);"function"==typeof r.value?(t.methods||(t.methods={}))[e]=r.value:(r.get||r.set)&&((t.computed||(t.computed={}))[e]={get:r.get,set:r.set})}}),(t.mixins||(t.mixins=[])).push({data:function(){return function(e,t){var r=t.prototype._init;t.prototype._init=function(){var t=this,r=Object.getOwnPropertyNames(e);if(e.$options.props)for(var o in e.$options.props)e.hasOwnProperty(o)||r.push(o);r.forEach(function(r){"_"!==r.charAt(0)&&Object.defineProperty(t,r,{get:function(){return e[r]},set:function(t){return e[r]=t},configurable:!0})})};var o=new t;t.prototype._init=r;var n={};return Object.keys(o).forEach(function(e){void 0!==o[e]&&(n[e]=o[e])}),n}(this,e)}});var f=e.__decorators__;f&&(f.forEach(function(e){return e(t)}),delete e.__decorators__);var u,p,s,d,y,v,_,l=Object.getPrototypeOf(e.prototype),O=l instanceof r?l.constructor:r,m=O.extend(t);return u=m,p=e,s=O,d=c,Object.getOwnPropertyNames(p).forEach(function(e){if("prototype"!==e){d.static[e]=Reflect.getOwnMetadataKeys(p,e);var t=Object.getOwnPropertyDescriptor(u,e);if(!t||t.configurable){var r,o,a=Object.getOwnPropertyDescriptor(p,e);if(!n){if("cid"===e)return;var c=Object.getOwnPropertyDescriptor(s,e);if(r=a.value,o=typeof r,null!=r&&("object"===o||"function"===o)&&c&&c.value===a.value)return}Object.defineProperty(u,e,a)}}}),v=m,_=c,o((y=e).prototype,v.prototype,_.instance),o(y,v,_.static),m}function i(e){return"function"==typeof e?c(e):function(t){return c(t,e)}}!function(e){(i||(i={})).registerHooks=function(e){a.push.apply(a,e)}}();var f=i;e.default=f,e.createDecorator=function(e){return function(t,r,o){var n="function"==typeof t?t:t.constructor;n.__decorators__||(n.__decorators__=[]),"number"!=typeof o&&(o=void 0),n.__decorators__.push(function(t){return e(t,r,o)})}},e.mixins=function(){for(var e=[],t=0;t, options: ComponentOptions = {} ): VueClass { + const reflectionMap: ReflectionMap = { + instance: {}, + static: {} + }; + options.name = options.name || (Component as any)._componentTag || (Component as any).name // prototype props. const proto = Component.prototype @@ -30,6 +37,7 @@ export function componentFactory ( if (key === 'constructor') { return } + reflectionMap.instance[key] = Reflect.getOwnMetadataKeys(proto, key); // hooks if ($internalHooks.indexOf(key) > -1) { options[key] = proto[key] @@ -69,7 +77,8 @@ export function componentFactory ( : Vue const Extended = Super.extend(options) - forwardStaticMembers(Extended, Component, Super) + forwardStaticMembersAndCollectReflection(Extended, Component, Super, reflectionMap) + copyReflectionMetadata(Component, Extended, reflectionMap) return Extended } @@ -93,7 +102,12 @@ const reservedPropertyNames = [ 'filter' ] -function forwardStaticMembers (Extended: typeof Vue, Original: typeof Vue, Super: typeof Vue): void { +function forwardStaticMembersAndCollectReflection ( + Extended: typeof Vue, + Original: typeof Vue, + Super: typeof Vue, + reflectionMap: ReflectionMap +): void { // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable Object.getOwnPropertyNames(Original).forEach(key => { // `prototype` should not be overwritten @@ -101,6 +115,8 @@ function forwardStaticMembers (Extended: typeof Vue, Original: typeof Vue, Super return } + reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key); + // Some browsers does not allow reconfigure built-in properties const extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key) if (extendedDescriptor && !extendedDescriptor.configurable) { diff --git a/src/reflect.ts b/src/reflect.ts new file mode 100644 index 0000000..f13fe8a --- /dev/null +++ b/src/reflect.ts @@ -0,0 +1,29 @@ +import { VueConstructor } from 'vue' +import 'reflect-metadata' + +export type StringToArrayMap = { + [key: string]: Array +} + +export type ReflectionMap = { + instance: StringToArrayMap, + static: StringToArrayMap +} + +export function copyReflectionMetadata( + from: VueConstructor, + to: VueConstructor, + reflectionMap: ReflectionMap +) { + shallowCopy(from.prototype, to.prototype, reflectionMap.instance); + shallowCopy(from, to, reflectionMap.static); +} + +function shallowCopy(from: VueConstructor, to: VueConstructor, propertyKeys: StringToArrayMap) { + for (const propertyKey in propertyKeys) { + propertyKeys[propertyKey].forEach((metadataKey) => { + const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) + Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) + }) + } +} diff --git a/test/test.ts b/test/test.ts index 9ff686c..cb11b87 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,3 +1,4 @@ +import 'reflect-metadata'; import Component, { createDecorator, mixins } from '../lib' import { expect } from 'chai' import * as td from 'testdouble' @@ -369,4 +370,23 @@ describe('vue-class-component', () => { expect(vm.valueA).to.equal('hi') expect(vm.valueB).to.equal(456) }) + + it('copies reflection metadata', function () { + @Component + class Test extends Vue { + @Reflect.metadata('worksStatic', true) + static staticValue: string = 'staticValue'; + + @Reflect.metadata('worksMethod', true) + test(): void { } + + @Reflect.metadata('worksAccessor', true) + get testAccessor(): boolean { return true; } + set testAccessor(value: boolean) { void(value) } + } + + expect(Reflect.getOwnMetadata('worksStatic', Test, 'staticValue')).to.equal(true); + expect(Reflect.getOwnMetadata('worksMethod', Test.prototype, 'test')).to.equal(true); + expect(Reflect.getOwnMetadata('worksAccessor', Test.prototype, 'testAccessor')).to.equal(true); + }) }) From cdd63663b115e78037b15841e841b8e3f3ef36d3 Mon Sep 17 00:00:00 2001 From: Gleb Ivanov Date: Mon, 19 Feb 2018 21:42:11 +0400 Subject: [PATCH 2/6] fixed review issues --- dist/vue-class-component.common.js | 28 ++---------------------- dist/vue-class-component.js | 35 +++++------------------------- dist/vue-class-component.min.js | 2 +- package.json | 5 ++--- src/component.ts | 20 ++++++++++++----- src/globals.d.ts | 27 ++++++++++++++++++++++- src/reflect.ts | 33 +++++++++++++++------------- test/test.ts | 26 +++++++++++----------- 8 files changed, 82 insertions(+), 94 deletions(-) diff --git a/dist/vue-class-component.common.js b/dist/vue-class-component.common.js index 478cc13..6b1763c 100644 --- a/dist/vue-class-component.common.js +++ b/dist/vue-class-component.common.js @@ -9,25 +9,8 @@ Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } -require('reflect-metadata'); var Vue = _interopDefault(require('vue')); -function copyReflectionMetadata(from, to, reflectionMap) { - shallowCopy(from.prototype, to.prototype, reflectionMap.instance); - shallowCopy(from, to, reflectionMap.static); -} -function shallowCopy(from, to, propertyKeys) { - var _loop_1 = function (propertyKey) { - propertyKeys[propertyKey].forEach(function (metadataKey) { - var metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey); - Reflect.defineMetadata(metadataKey, metadata, to, propertyKey); - }); - }; - for (var propertyKey in propertyKeys) { - _loop_1(propertyKey); - } -} - var hasProto = { __proto__: [] } instanceof Array; function createDecorator(factory) { return function (target, key, index) { @@ -122,10 +105,6 @@ var $internalHooks = [ ]; function componentFactory(Component, options) { if (options === void 0) { options = {}; } - var reflectionMap = { - instance: {}, - static: {} - }; options.name = options.name || Component._componentTag || Component.name; // prototype props. var proto = Component.prototype; @@ -133,7 +112,6 @@ function componentFactory(Component, options) { if (key === 'constructor') { return; } - reflectionMap.instance[key] = Reflect.getOwnMetadataKeys(proto, key); // hooks if ($internalHooks.indexOf(key) > -1) { options[key] = proto[key]; @@ -169,8 +147,7 @@ function componentFactory(Component, options) { ? superProto.constructor : Vue; var Extended = Super.extend(options); - forwardStaticMembersAndCollectReflection(Extended, Component, Super, reflectionMap); - copyReflectionMetadata(Component, Extended, reflectionMap); + forwardStaticMembers(Extended, Component, Super); return Extended; } var reservedPropertyNames = [ @@ -188,14 +165,13 @@ var reservedPropertyNames = [ 'directive', 'filter' ]; -function forwardStaticMembersAndCollectReflection(Extended, Original, Super, reflectionMap) { +function forwardStaticMembers(Extended, Original, Super) { // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable Object.getOwnPropertyNames(Original).forEach(function (key) { // `prototype` should not be overwritten if (key === 'prototype') { return; } - reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key); // Some browsers does not allow reconfigure built-in properties var extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key); if (extendedDescriptor && !extendedDescriptor.configurable) { diff --git a/dist/vue-class-component.js b/dist/vue-class-component.js index 9cfbc01..6a22752 100644 --- a/dist/vue-class-component.js +++ b/dist/vue-class-component.js @@ -4,29 +4,13 @@ * @license MIT */ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('reflect-metadata'), require('vue')) : - typeof define === 'function' && define.amd ? define(['exports', 'reflect-metadata', 'vue'], factory) : - (factory((global.VueClassComponent = {}),null,global.Vue)); -}(this, (function (exports,reflectMetadata,Vue) { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) : + typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) : + (factory((global.VueClassComponent = {}),global.Vue)); +}(this, (function (exports,Vue) { 'use strict'; Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue; -function copyReflectionMetadata(from, to, reflectionMap) { - shallowCopy(from.prototype, to.prototype, reflectionMap.instance); - shallowCopy(from, to, reflectionMap.static); -} -function shallowCopy(from, to, propertyKeys) { - var _loop_1 = function (propertyKey) { - propertyKeys[propertyKey].forEach(function (metadataKey) { - var metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey); - Reflect.defineMetadata(metadataKey, metadata, to, propertyKey); - }); - }; - for (var propertyKey in propertyKeys) { - _loop_1(propertyKey); - } -} - var hasProto = { __proto__: [] } instanceof Array; function createDecorator(factory) { return function (target, key, index) { @@ -121,10 +105,6 @@ var $internalHooks = [ ]; function componentFactory(Component, options) { if (options === void 0) { options = {}; } - var reflectionMap = { - instance: {}, - static: {} - }; options.name = options.name || Component._componentTag || Component.name; // prototype props. var proto = Component.prototype; @@ -132,7 +112,6 @@ function componentFactory(Component, options) { if (key === 'constructor') { return; } - reflectionMap.instance[key] = Reflect.getOwnMetadataKeys(proto, key); // hooks if ($internalHooks.indexOf(key) > -1) { options[key] = proto[key]; @@ -168,8 +147,7 @@ function componentFactory(Component, options) { ? superProto.constructor : Vue; var Extended = Super.extend(options); - forwardStaticMembersAndCollectReflection(Extended, Component, Super, reflectionMap); - copyReflectionMetadata(Component, Extended, reflectionMap); + forwardStaticMembers(Extended, Component, Super); return Extended; } var reservedPropertyNames = [ @@ -187,14 +165,13 @@ var reservedPropertyNames = [ 'directive', 'filter' ]; -function forwardStaticMembersAndCollectReflection(Extended, Original, Super, reflectionMap) { +function forwardStaticMembers(Extended, Original, Super) { // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable Object.getOwnPropertyNames(Original).forEach(function (key) { // `prototype` should not be overwritten if (key === 'prototype') { return; } - reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key); // Some browsers does not allow reconfigure built-in properties var extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key); if (extendedDescriptor && !extendedDescriptor.configurable) { diff --git a/dist/vue-class-component.min.js b/dist/vue-class-component.min.js index 0ce2e17..4dbf8b4 100644 --- a/dist/vue-class-component.min.js +++ b/dist/vue-class-component.min.js @@ -3,4 +3,4 @@ * (c) 2015-present Evan You * @license MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("reflect-metadata"),require("vue")):"function"==typeof define&&define.amd?define(["exports","reflect-metadata","vue"],t):t(e.VueClassComponent={},null,e.Vue)}(this,function(e,t,r){"use strict";function o(e,t,r){var o=function(o){r[o].forEach(function(r){var n=Reflect.getOwnMetadata(r,e,o);Reflect.defineMetadata(r,n,t,o)})};for(var n in r)o(n)}r=r&&r.hasOwnProperty("default")?r.default:r;var n={__proto__:[]}instanceof Array;var a=["data","beforeCreate","created","beforeMount","mounted","beforeDestroy","destroyed","beforeUpdate","updated","activated","deactivated","render","errorCaptured"];function c(e,t){void 0===t&&(t={});var c={instance:{},static:{}};t.name=t.name||e._componentTag||e.name;var i=e.prototype;Object.getOwnPropertyNames(i).forEach(function(e){if("constructor"!==e)if(c.instance[e]=Reflect.getOwnMetadataKeys(i,e),a.indexOf(e)>-1)t[e]=i[e];else{var r=Object.getOwnPropertyDescriptor(i,e);"function"==typeof r.value?(t.methods||(t.methods={}))[e]=r.value:(r.get||r.set)&&((t.computed||(t.computed={}))[e]={get:r.get,set:r.set})}}),(t.mixins||(t.mixins=[])).push({data:function(){return function(e,t){var r=t.prototype._init;t.prototype._init=function(){var t=this,r=Object.getOwnPropertyNames(e);if(e.$options.props)for(var o in e.$options.props)e.hasOwnProperty(o)||r.push(o);r.forEach(function(r){"_"!==r.charAt(0)&&Object.defineProperty(t,r,{get:function(){return e[r]},set:function(t){return e[r]=t},configurable:!0})})};var o=new t;t.prototype._init=r;var n={};return Object.keys(o).forEach(function(e){void 0!==o[e]&&(n[e]=o[e])}),n}(this,e)}});var f=e.__decorators__;f&&(f.forEach(function(e){return e(t)}),delete e.__decorators__);var u,p,s,d,y,v,_,l=Object.getPrototypeOf(e.prototype),O=l instanceof r?l.constructor:r,m=O.extend(t);return u=m,p=e,s=O,d=c,Object.getOwnPropertyNames(p).forEach(function(e){if("prototype"!==e){d.static[e]=Reflect.getOwnMetadataKeys(p,e);var t=Object.getOwnPropertyDescriptor(u,e);if(!t||t.configurable){var r,o,a=Object.getOwnPropertyDescriptor(p,e);if(!n){if("cid"===e)return;var c=Object.getOwnPropertyDescriptor(s,e);if(r=a.value,o=typeof r,null!=r&&("object"===o||"function"===o)&&c&&c.value===a.value)return}Object.defineProperty(u,e,a)}}}),v=m,_=c,o((y=e).prototype,v.prototype,_.instance),o(y,v,_.static),m}function i(e){return"function"==typeof e?c(e):function(t){return c(t,e)}}!function(e){(i||(i={})).registerHooks=function(e){a.push.apply(a,e)}}();var f=i;e.default=f,e.createDecorator=function(e){return function(t,r,o){var n="function"==typeof t?t:t.constructor;n.__decorators__||(n.__decorators__=[]),"number"!=typeof o&&(o=void 0),n.__decorators__.push(function(t){return e(t,r,o)})}},e.mixins=function(){for(var e=[],t=0;t-1)n[e]=i[e];else{var t=Object.getOwnPropertyDescriptor(i,e);"function"==typeof t.value?(n.methods||(n.methods={}))[e]=t.value:(t.get||t.set)&&((n.computed||(n.computed={}))[e]={get:t.get,set:t.set})}}),(n.mixins||(n.mixins=[])).push({data:function(){return function(e,t){var r=t.prototype._init;t.prototype._init=function(){var t=this,r=Object.getOwnPropertyNames(e);if(e.$options.props)for(var o in e.$options.props)e.hasOwnProperty(o)||r.push(o);r.forEach(function(r){"_"!==r.charAt(0)&&Object.defineProperty(t,r,{get:function(){return e[r]},set:function(t){return e[r]=t},configurable:!0})})};var o=new t;t.prototype._init=r;var n={};return Object.keys(o).forEach(function(e){void 0!==o[e]&&(n[e]=o[e])}),n}(this,e)}});var c=e.__decorators__;c&&(c.forEach(function(e){return e(n)}),delete e.__decorators__);var u,a,f,p=Object.getPrototypeOf(e.prototype),s=p instanceof t?p.constructor:t,d=s.extend(n);return u=d,a=e,f=s,Object.getOwnPropertyNames(a).forEach(function(e){if("prototype"!==e){var t=Object.getOwnPropertyDescriptor(u,e);if(!t||t.configurable){var o,n,i=Object.getOwnPropertyDescriptor(a,e);if(!r){if("cid"===e)return;var c=Object.getOwnPropertyDescriptor(f,e);if(o=i.value,n=typeof o,null!=o&&("object"===n||"function"===n)&&c&&c.value===i.value)return}Object.defineProperty(u,e,i)}}}),d}function i(e){return"function"==typeof e?n(e):function(t){return n(t,e)}}!function(e){(i||(i={})).registerHooks=function(e){o.push.apply(o,e)}}();var c=i;e.default=c,e.createDecorator=function(e){return function(t,r,o){var n="function"==typeof t?t:t.constructor;n.__decorators__||(n.__decorators__=[]),"number"!=typeof o&&(o=void 0),n.__decorators__.push(function(t){return e(t,r,o)})}},e.mixins=function(){for(var e=[],r=0;r -1) { options[key] = proto[key] @@ -78,7 +81,10 @@ export function componentFactory ( const Extended = Super.extend(options) forwardStaticMembersAndCollectReflection(Extended, Component, Super, reflectionMap) - copyReflectionMetadata(Component, Extended, reflectionMap) + + if (reflectionIsSupported()) { + copyReflectionMetadata(Component, Extended, reflectionMap) + } return Extended } @@ -115,7 +121,9 @@ function forwardStaticMembersAndCollectReflection ( return } - reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key); + if (reflectionIsSupported()) { + reflectionMap.static[key] = Reflect.getOwnMetadataKeys(Original, key) + } // Some browsers does not allow reconfigure built-in properties const extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key) diff --git a/src/globals.d.ts b/src/globals.d.ts index 89a7ede..eca4ca2 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -3,8 +3,33 @@ * should not expose to userland */ +declare namespace Reflect { + function decorate(decorators: ClassDecorator[], target: Function): Function + function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: Object, propertyKey: string | symbol, attributes?: PropertyDescriptor): PropertyDescriptor + function metadata(metadataKey: any, metadataValue: any): { + (target: Function): void + (target: Object, propertyKey: string | symbol): void + } + function defineMetadata(metadataKey: any, metadataValue: any, target: Object): void + function defineMetadata(metadataKey: any, metadataValue: any, target: Object, propertyKey: string | symbol): void + function hasMetadata(metadataKey: any, target: Object): boolean + function hasMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): boolean + function hasOwnMetadata(metadataKey: any, target: Object): boolean + function hasOwnMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): boolean + function getMetadata(metadataKey: any, target: Object): any + function getMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): any + function getOwnMetadata(metadataKey: any, target: Object): any + function getOwnMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): any + function getMetadataKeys(target: Object): any[] + function getMetadataKeys(target: Object, propertyKey: string | symbol): any[] + function getOwnMetadataKeys(target: Object): any[] + function getOwnMetadataKeys(target: Object, propertyKey: string | symbol): any[] + function deleteMetadata(metadataKey: any, target: Object): boolean + function deleteMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): boolean + } + declare const process: { env: { NODE_ENV: string } -} \ No newline at end of file +} diff --git a/src/reflect.ts b/src/reflect.ts index f13fe8a..808181e 100644 --- a/src/reflect.ts +++ b/src/reflect.ts @@ -1,29 +1,32 @@ import { VueConstructor } from 'vue' -import 'reflect-metadata' export type StringToArrayMap = { - [key: string]: Array + [key: string]: Array } export type ReflectionMap = { - instance: StringToArrayMap, - static: StringToArrayMap + instance: StringToArrayMap, + static: StringToArrayMap +} + +export function reflectionIsSupported() { + return (Reflect && Reflect.defineMetadata) !== undefined } export function copyReflectionMetadata( - from: VueConstructor, - to: VueConstructor, - reflectionMap: ReflectionMap + from: VueConstructor, + to: VueConstructor, + reflectionMap: ReflectionMap ) { - shallowCopy(from.prototype, to.prototype, reflectionMap.instance); - shallowCopy(from, to, reflectionMap.static); + shallowCopy(from.prototype, to.prototype, reflectionMap.instance) + shallowCopy(from, to, reflectionMap.static) } function shallowCopy(from: VueConstructor, to: VueConstructor, propertyKeys: StringToArrayMap) { - for (const propertyKey in propertyKeys) { - propertyKeys[propertyKey].forEach((metadataKey) => { - const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) - Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) - }) - } + for (const propertyKey in propertyKeys) { + propertyKeys[propertyKey].forEach((metadataKey) => { + const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) + Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) + }) + } } diff --git a/test/test.ts b/test/test.ts index cb11b87..b09ccd9 100644 --- a/test/test.ts +++ b/test/test.ts @@ -372,21 +372,21 @@ describe('vue-class-component', () => { }) it('copies reflection metadata', function () { - @Component - class Test extends Vue { - @Reflect.metadata('worksStatic', true) - static staticValue: string = 'staticValue'; + @Component + class Test extends Vue { + @Reflect.metadata('worksStatic', true) + static staticValue: string = 'staticValue' - @Reflect.metadata('worksMethod', true) - test(): void { } + @Reflect.metadata('worksMethod', true) + test(): void { } - @Reflect.metadata('worksAccessor', true) - get testAccessor(): boolean { return true; } - set testAccessor(value: boolean) { void(value) } - } + @Reflect.metadata('worksAccessor', true) + get testAccessor(): boolean { return true } + set testAccessor(value: boolean) { void(value) } + } - expect(Reflect.getOwnMetadata('worksStatic', Test, 'staticValue')).to.equal(true); - expect(Reflect.getOwnMetadata('worksMethod', Test.prototype, 'test')).to.equal(true); - expect(Reflect.getOwnMetadata('worksAccessor', Test.prototype, 'testAccessor')).to.equal(true); + expect(Reflect.getOwnMetadata('worksStatic', Test, 'staticValue')).to.equal(true) + expect(Reflect.getOwnMetadata('worksMethod', Test.prototype, 'test')).to.equal(true) + expect(Reflect.getOwnMetadata('worksAccessor', Test.prototype, 'testAccessor')).to.equal(true) }) }) From 07eff38aa3f82d9e0426a1ebdfcf134556d8a6da Mon Sep 17 00:00:00 2001 From: Gleb Ivanov Date: Mon, 19 Feb 2018 21:44:28 +0400 Subject: [PATCH 3/6] fixed review issues --- src/component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/component.ts b/src/component.ts index 847f2f1..0ce28c9 100644 --- a/src/component.ts +++ b/src/component.ts @@ -109,10 +109,10 @@ const reservedPropertyNames = [ ] function forwardStaticMembersAndCollectReflection ( - Extended: typeof Vue, - Original: typeof Vue, - Super: typeof Vue, - reflectionMap: ReflectionMap + Extended: typeof Vue, + Original: typeof Vue, + Super: typeof Vue, + reflectionMap: ReflectionMap ): void { // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable Object.getOwnPropertyNames(Original).forEach(key => { From 49e9c90f2550e9198079f3a770aa4879ed8e8a77 Mon Sep 17 00:00:00 2001 From: Gleb Ivanov Date: Tue, 20 Feb 2018 22:23:53 +0400 Subject: [PATCH 4/6] fixed corner case with constructor --- src/component.ts | 6 +++++- src/reflect.ts | 11 +++++++++-- test/test.ts | 7 +++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/component.ts b/src/component.ts index 0ce28c9..c07063b 100644 --- a/src/component.ts +++ b/src/component.ts @@ -26,9 +26,13 @@ export function componentFactory ( ): VueClass { const reflectionMap: ReflectionMap = { instance: {}, - static: {} + static: {}, + constructor: [] } + if (reflectionIsSupported()) { + reflectionMap.constructor = Reflect.getOwnMetadataKeys(Component) + } options.name = options.name || (Component as any)._componentTag || (Component as any).name // prototype props. const proto = Component.prototype diff --git a/src/reflect.ts b/src/reflect.ts index 808181e..46975a0 100644 --- a/src/reflect.ts +++ b/src/reflect.ts @@ -5,6 +5,7 @@ export type StringToArrayMap = { } export type ReflectionMap = { + constructor: Array, instance: StringToArrayMap, static: StringToArrayMap } @@ -20,13 +21,19 @@ export function copyReflectionMetadata( ) { shallowCopy(from.prototype, to.prototype, reflectionMap.instance) shallowCopy(from, to, reflectionMap.static) + shallowCopy(from, to, {'constructor': reflectionMap.constructor}) } function shallowCopy(from: VueConstructor, to: VueConstructor, propertyKeys: StringToArrayMap) { for (const propertyKey in propertyKeys) { propertyKeys[propertyKey].forEach((metadataKey) => { - const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) - Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) + if (propertyKey == 'constructor') { + const metadata = Reflect.getOwnMetadata(metadataKey, from) + Reflect.defineMetadata(metadataKey, metadata, to) + } else { + const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) + Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) + } }) } } diff --git a/test/test.ts b/test/test.ts index b09ccd9..5a758c7 100644 --- a/test/test.ts +++ b/test/test.ts @@ -372,8 +372,14 @@ describe('vue-class-component', () => { }) it('copies reflection metadata', function () { + const trickyDecorator = (proto: Vue, _: string) => + Reflect.defineMetadata('worksConstructor', true, proto.constructor); + @Component class Test extends Vue { + @trickyDecorator + trickyCase: string = 'trickyCase' + @Reflect.metadata('worksStatic', true) static staticValue: string = 'staticValue' @@ -385,6 +391,7 @@ describe('vue-class-component', () => { set testAccessor(value: boolean) { void(value) } } + expect(Reflect.getOwnMetadata('worksConstructor', Test)).to.equal(true) expect(Reflect.getOwnMetadata('worksStatic', Test, 'staticValue')).to.equal(true) expect(Reflect.getOwnMetadata('worksMethod', Test.prototype, 'test')).to.equal(true) expect(Reflect.getOwnMetadata('worksAccessor', Test.prototype, 'testAccessor')).to.equal(true) From 614b008c72b921efb75d880d816f7a6f597ecd9b Mon Sep 17 00:00:00 2001 From: Gleb Ivanov Date: Tue, 20 Feb 2018 22:27:00 +0400 Subject: [PATCH 5/6] fixed codestyle --- src/reflect.ts | 8 ++++---- test/test.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/reflect.ts b/src/reflect.ts index 46975a0..67e3918 100644 --- a/src/reflect.ts +++ b/src/reflect.ts @@ -28,11 +28,11 @@ function shallowCopy(from: VueConstructor, to: VueConstructor, propertyKeys: Str for (const propertyKey in propertyKeys) { propertyKeys[propertyKey].forEach((metadataKey) => { if (propertyKey == 'constructor') { - const metadata = Reflect.getOwnMetadata(metadataKey, from) - Reflect.defineMetadata(metadataKey, metadata, to) + const metadata = Reflect.getOwnMetadata(metadataKey, from) + Reflect.defineMetadata(metadataKey, metadata, to) } else { - const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) - Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) + const metadata = Reflect.getOwnMetadata(metadataKey, from, propertyKey) + Reflect.defineMetadata(metadataKey, metadata, to, propertyKey) } }) } diff --git a/test/test.ts b/test/test.ts index 5a758c7..1edf71f 100644 --- a/test/test.ts +++ b/test/test.ts @@ -373,7 +373,7 @@ describe('vue-class-component', () => { it('copies reflection metadata', function () { const trickyDecorator = (proto: Vue, _: string) => - Reflect.defineMetadata('worksConstructor', true, proto.constructor); + Reflect.defineMetadata('worksConstructor', true, proto.constructor) @Component class Test extends Vue { From a362138240b17ed004aac0542616707d94437263 Mon Sep 17 00:00:00 2001 From: Gleb Ivanov Date: Fri, 2 Mar 2018 10:38:27 +0400 Subject: [PATCH 6/6] fixed codestyle in test.ts and reflect.ts to match project codestyle --- src/reflect.ts | 6 +++--- test/test.ts | 22 +++++++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/reflect.ts b/src/reflect.ts index 67e3918..56b7a27 100644 --- a/src/reflect.ts +++ b/src/reflect.ts @@ -10,11 +10,11 @@ export type ReflectionMap = { static: StringToArrayMap } -export function reflectionIsSupported() { +export function reflectionIsSupported () { return (Reflect && Reflect.defineMetadata) !== undefined } -export function copyReflectionMetadata( +export function copyReflectionMetadata ( from: VueConstructor, to: VueConstructor, reflectionMap: ReflectionMap @@ -24,7 +24,7 @@ export function copyReflectionMetadata( shallowCopy(from, to, {'constructor': reflectionMap.constructor}) } -function shallowCopy(from: VueConstructor, to: VueConstructor, propertyKeys: StringToArrayMap) { +function shallowCopy (from: VueConstructor, to: VueConstructor, propertyKeys: StringToArrayMap) { for (const propertyKey in propertyKeys) { propertyKeys[propertyKey].forEach((metadataKey) => { if (propertyKey == 'constructor') { diff --git a/test/test.ts b/test/test.ts index 1edf71f..8fb1557 100644 --- a/test/test.ts +++ b/test/test.ts @@ -372,23 +372,27 @@ describe('vue-class-component', () => { }) it('copies reflection metadata', function () { - const trickyDecorator = (proto: Vue, _: string) => - Reflect.defineMetadata('worksConstructor', true, proto.constructor) - @Component + @Reflect.metadata('worksConstructor', true) class Test extends Vue { - @trickyDecorator - trickyCase: string = 'trickyCase' - @Reflect.metadata('worksStatic', true) static staticValue: string = 'staticValue' + private _test: boolean = false; + @Reflect.metadata('worksMethod', true) - test(): void { } + test (): void { + void 0 + } @Reflect.metadata('worksAccessor', true) - get testAccessor(): boolean { return true } - set testAccessor(value: boolean) { void(value) } + get testAccessor (): boolean { + return this._test + } + + set testAccessor (value: boolean) { + this._test = value + } } expect(Reflect.getOwnMetadata('worksConstructor', Test)).to.equal(true) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy