1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var isFunction = require("lodash/isFunction");
|
4 | var common_1 = require("./common");
|
5 | var utils_1 = require("../utils");
|
6 | var InternalDecoratorFactory = (function () {
|
7 | function InternalDecoratorFactory() {
|
8 | }
|
9 | InternalDecoratorFactory.prototype.createDecorator = function (config) {
|
10 | var _this = this;
|
11 | var applicator = config.applicator, optionalParams = config.optionalParams;
|
12 | return function () {
|
13 | var args = [];
|
14 | for (var _i = 0; _i < arguments.length; _i++) {
|
15 | args[_i] = arguments[_i];
|
16 | }
|
17 | var params = args;
|
18 | var decorator = function (target, name, _descriptor) {
|
19 | var descriptor = _this._resolveDescriptor(target, name, _descriptor);
|
20 | var value = descriptor.value, get = descriptor.get, set = descriptor.set;
|
21 | // If this decorator is being applied after an instance decorator we simply ignore it
|
22 | // as we can't apply it correctly.
|
23 | if (!common_1.InstanceChainMap.has([target, name])) {
|
24 | if (isFunction(value)) {
|
25 | descriptor.value = utils_1.copyMetadata(applicator.apply({ config: config, target: target, value: value, args: params }), value);
|
26 | }
|
27 | else if (isFunction(get) && config.getter) {
|
28 | descriptor.get = utils_1.copyMetadata(applicator.apply({ config: config, target: target, value: get, args: params }), get);
|
29 | }
|
30 | else if (isFunction(set) && config.setter) {
|
31 | descriptor.set = utils_1.copyMetadata(applicator.apply({ config: config, target: target, value: set, args: params }), set);
|
32 | }
|
33 | }
|
34 | return descriptor;
|
35 | };
|
36 | if (optionalParams && utils_1.isMethodOrPropertyDecoratorArgs.apply(void 0, args)) {
|
37 | params = [];
|
38 | return decorator(args[0], args[1], args[2]);
|
39 | }
|
40 | return decorator;
|
41 | };
|
42 | };
|
43 | InternalDecoratorFactory.prototype.createInstanceDecorator = function (config) {
|
44 | var _this = this;
|
45 | var applicator = config.applicator, bound = config.bound, optionalParams = config.optionalParams;
|
46 | return function () {
|
47 | var args = [];
|
48 | for (var _i = 0; _i < arguments.length; _i++) {
|
49 | args[_i] = arguments[_i];
|
50 | }
|
51 | var params = args;
|
52 | var decorator = function (target, name, _descriptor) {
|
53 | var descriptor = _this._resolveDescriptor(target, name, _descriptor);
|
54 | var value = descriptor.value, writable = descriptor.writable, enumerable = descriptor.enumerable, configurable = descriptor.configurable, get = descriptor.get, set = descriptor.set;
|
55 | var isFirstInstance = !common_1.InstanceChainMap.has([target, name]);
|
56 | var chainData = common_1.InstanceChainMap.get([target, name]) || { fns: [], properties: [] };
|
57 | var isGetter = isFirstInstance && isFunction(get);
|
58 | var isSetter = isFirstInstance && isFunction(set);
|
59 | var isMethod = isFirstInstance && isFunction(value);
|
60 | var isProperty = isFirstInstance && !isGetter && !isSetter && !isMethod;
|
61 | var baseValue = isGetter ? get : isMethod ? value : undefined;
|
62 | chainData.properties.push(name);
|
63 | chainData.fns.push(function (fn, instance, context) {
|
64 | if (!_this._isApplicable(context, config)) {
|
65 | return fn;
|
66 | }
|
67 | if (bound) {
|
68 | fn = utils_1.bind(fn, instance);
|
69 | }
|
70 | return utils_1.copyMetadata(applicator.apply({ args: params, target: target, instance: instance, value: fn, config: config }), fn);
|
71 | });
|
72 | common_1.InstanceChainMap.set([target, name], chainData);
|
73 | if (!isFirstInstance) {
|
74 | return descriptor;
|
75 | }
|
76 | chainData.isSetter = isSetter;
|
77 | chainData.isGetter = isGetter;
|
78 | chainData.isMethod = isMethod;
|
79 | chainData.isProperty = isProperty;
|
80 | var applyChain = function (fn, context, instance) {
|
81 | return chainData.fns.reduce(function (result, next) { return next(result, instance, context); }, fn);
|
82 | };
|
83 | var applyDecorator = function (instance) {
|
84 | var getter = get || undefined;
|
85 | var setter = set || undefined;
|
86 | if (isGetter || isSetter) {
|
87 |
|
88 | if (isGetter) {
|
89 | getter = applyChain(get, { value: get, getter: true }, instance);
|
90 | }
|
91 | if (isSetter) {
|
92 | setter = applyChain(set, { value: set, setter: true }, instance);
|
93 | }
|
94 | Object.defineProperty(instance, name, {
|
95 | enumerable: enumerable,
|
96 | configurable: configurable,
|
97 | get: getter,
|
98 | set: setter
|
99 | });
|
100 | }
|
101 | else if (isMethod || isProperty) {
|
102 | var newFn = isMethod
|
103 | ? applyChain(value, { value: value, method: true }, instance)
|
104 | : applyChain(value, { value: value, property: true }, instance);
|
105 | Object.defineProperty(instance, name, {
|
106 | writable: writable,
|
107 | enumerable: enumerable,
|
108 | configurable: configurable,
|
109 | value: newFn
|
110 | });
|
111 | }
|
112 | };
|
113 | if (isMethod || isProperty) {
|
114 | delete descriptor.value;
|
115 | delete descriptor.writable;
|
116 | }
|
117 | descriptor.get = function () {
|
118 |
|
119 |
|
120 | if (utils_1.isPrototypeAccess(this, target)) {
|
121 | return baseValue;
|
122 | }
|
123 | applyDecorator(this);
|
124 | var descriptor = Object.getOwnPropertyDescriptor(this, name);
|
125 | if (descriptor.get) {
|
126 | return descriptor.get.call(this);
|
127 | }
|
128 | return descriptor.value;
|
129 | };
|
130 | descriptor.set = function (value) {
|
131 | applyDecorator(this);
|
132 | var descriptor = Object.getOwnPropertyDescriptor(this, name);
|
133 | if (descriptor.set) {
|
134 | descriptor.set.call(this, value);
|
135 | }
|
136 | else if (isProperty || isMethod) {
|
137 | this[name] = value;
|
138 | }
|
139 | };
|
140 | return descriptor;
|
141 | };
|
142 | if (optionalParams && utils_1.isMethodOrPropertyDecoratorArgs.apply(void 0, args)) {
|
143 | params = [];
|
144 | return decorator(args[0], args[1], args[2]);
|
145 | }
|
146 | return decorator;
|
147 | };
|
148 | };
|
149 | InternalDecoratorFactory.prototype._isApplicable = function (context, config) {
|
150 | return !Boolean(context.getter && !config.getter
|
151 | || context.setter && !config.setter
|
152 | || context.method && !config.method
|
153 | || context.property && !config.property);
|
154 | };
|
155 | InternalDecoratorFactory.prototype._resolveDescriptor = function (target, name, descriptor) {
|
156 | if (descriptor) {
|
157 | return descriptor;
|
158 | }
|
159 | return Object.getOwnPropertyDescriptor(target, name) || {};
|
160 | };
|
161 | return InternalDecoratorFactory;
|
162 | }());
|
163 | exports.InternalDecoratorFactory = InternalDecoratorFactory;
|
164 | exports.DecoratorFactory = new InternalDecoratorFactory();
|
165 |
|
\ | No newline at end of file |