UNPKG

8.42 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var isFunction = require("lodash/isFunction");
4var common_1 = require("./common");
5var utils_1 = require("../utils");
6var 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 // If we have a getter apply the decorators to the getter and assign it to the instance.
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 // Check for direct access on the prototype.
119 // MyClass.prototype.fn <-- This should not apply the decorator.
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}());
163exports.InternalDecoratorFactory = InternalDecoratorFactory;
164exports.DecoratorFactory = new InternalDecoratorFactory();
165//# sourceMappingURL=DecoratorFactory.js.map
\No newline at end of file