decorate.js (13441B)
1 var toArray = require("./toArray.js"); 2 3 var toPropertyKey = require("./toPropertyKey.js"); 4 5 function _decorate(decorators, factory, superClass, mixins) { 6 var api = _getDecoratorsApi(); 7 8 if (mixins) { 9 for (var i = 0; i < mixins.length; i++) { 10 api = mixins[i](api); 11 } 12 } 13 14 var r = factory(function initialize(O) { 15 api.initializeInstanceElements(O, decorated.elements); 16 }, superClass); 17 var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); 18 api.initializeClassElements(r.F, decorated.elements); 19 return api.runClassFinishers(r.F, decorated.finishers); 20 } 21 22 function _getDecoratorsApi() { 23 _getDecoratorsApi = function _getDecoratorsApi() { 24 return api; 25 }; 26 27 var api = { 28 elementsDefinitionOrder: [["method"], ["field"]], 29 initializeInstanceElements: function initializeInstanceElements(O, elements) { 30 ["method", "field"].forEach(function (kind) { 31 elements.forEach(function (element) { 32 if (element.kind === kind && element.placement === "own") { 33 this.defineClassElement(O, element); 34 } 35 }, this); 36 }, this); 37 }, 38 initializeClassElements: function initializeClassElements(F, elements) { 39 var proto = F.prototype; 40 ["method", "field"].forEach(function (kind) { 41 elements.forEach(function (element) { 42 var placement = element.placement; 43 44 if (element.kind === kind && (placement === "static" || placement === "prototype")) { 45 var receiver = placement === "static" ? F : proto; 46 this.defineClassElement(receiver, element); 47 } 48 }, this); 49 }, this); 50 }, 51 defineClassElement: function defineClassElement(receiver, element) { 52 var descriptor = element.descriptor; 53 54 if (element.kind === "field") { 55 var initializer = element.initializer; 56 descriptor = { 57 enumerable: descriptor.enumerable, 58 writable: descriptor.writable, 59 configurable: descriptor.configurable, 60 value: initializer === void 0 ? void 0 : initializer.call(receiver) 61 }; 62 } 63 64 Object.defineProperty(receiver, element.key, descriptor); 65 }, 66 decorateClass: function decorateClass(elements, decorators) { 67 var newElements = []; 68 var finishers = []; 69 var placements = { 70 "static": [], 71 prototype: [], 72 own: [] 73 }; 74 elements.forEach(function (element) { 75 this.addElementPlacement(element, placements); 76 }, this); 77 elements.forEach(function (element) { 78 if (!_hasDecorators(element)) return newElements.push(element); 79 var elementFinishersExtras = this.decorateElement(element, placements); 80 newElements.push(elementFinishersExtras.element); 81 newElements.push.apply(newElements, elementFinishersExtras.extras); 82 finishers.push.apply(finishers, elementFinishersExtras.finishers); 83 }, this); 84 85 if (!decorators) { 86 return { 87 elements: newElements, 88 finishers: finishers 89 }; 90 } 91 92 var result = this.decorateConstructor(newElements, decorators); 93 finishers.push.apply(finishers, result.finishers); 94 result.finishers = finishers; 95 return result; 96 }, 97 addElementPlacement: function addElementPlacement(element, placements, silent) { 98 var keys = placements[element.placement]; 99 100 if (!silent && keys.indexOf(element.key) !== -1) { 101 throw new TypeError("Duplicated element (" + element.key + ")"); 102 } 103 104 keys.push(element.key); 105 }, 106 decorateElement: function decorateElement(element, placements) { 107 var extras = []; 108 var finishers = []; 109 110 for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) { 111 var keys = placements[element.placement]; 112 keys.splice(keys.indexOf(element.key), 1); 113 var elementObject = this.fromElementDescriptor(element); 114 var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); 115 element = elementFinisherExtras.element; 116 this.addElementPlacement(element, placements); 117 118 if (elementFinisherExtras.finisher) { 119 finishers.push(elementFinisherExtras.finisher); 120 } 121 122 var newExtras = elementFinisherExtras.extras; 123 124 if (newExtras) { 125 for (var j = 0; j < newExtras.length; j++) { 126 this.addElementPlacement(newExtras[j], placements); 127 } 128 129 extras.push.apply(extras, newExtras); 130 } 131 } 132 133 return { 134 element: element, 135 finishers: finishers, 136 extras: extras 137 }; 138 }, 139 decorateConstructor: function decorateConstructor(elements, decorators) { 140 var finishers = []; 141 142 for (var i = decorators.length - 1; i >= 0; i--) { 143 var obj = this.fromClassDescriptor(elements); 144 var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj); 145 146 if (elementsAndFinisher.finisher !== undefined) { 147 finishers.push(elementsAndFinisher.finisher); 148 } 149 150 if (elementsAndFinisher.elements !== undefined) { 151 elements = elementsAndFinisher.elements; 152 153 for (var j = 0; j < elements.length - 1; j++) { 154 for (var k = j + 1; k < elements.length; k++) { 155 if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) { 156 throw new TypeError("Duplicated element (" + elements[j].key + ")"); 157 } 158 } 159 } 160 } 161 } 162 163 return { 164 elements: elements, 165 finishers: finishers 166 }; 167 }, 168 fromElementDescriptor: function fromElementDescriptor(element) { 169 var obj = { 170 kind: element.kind, 171 key: element.key, 172 placement: element.placement, 173 descriptor: element.descriptor 174 }; 175 var desc = { 176 value: "Descriptor", 177 configurable: true 178 }; 179 Object.defineProperty(obj, Symbol.toStringTag, desc); 180 if (element.kind === "field") obj.initializer = element.initializer; 181 return obj; 182 }, 183 toElementDescriptors: function toElementDescriptors(elementObjects) { 184 if (elementObjects === undefined) return; 185 return toArray(elementObjects).map(function (elementObject) { 186 var element = this.toElementDescriptor(elementObject); 187 this.disallowProperty(elementObject, "finisher", "An element descriptor"); 188 this.disallowProperty(elementObject, "extras", "An element descriptor"); 189 return element; 190 }, this); 191 }, 192 toElementDescriptor: function toElementDescriptor(elementObject) { 193 var kind = String(elementObject.kind); 194 195 if (kind !== "method" && kind !== "field") { 196 throw new TypeError('An element descriptor\'s .kind property must be either "method" or' + ' "field", but a decorator created an element descriptor with' + ' .kind "' + kind + '"'); 197 } 198 199 var key = toPropertyKey(elementObject.key); 200 var placement = String(elementObject.placement); 201 202 if (placement !== "static" && placement !== "prototype" && placement !== "own") { 203 throw new TypeError('An element descriptor\'s .placement property must be one of "static",' + ' "prototype" or "own", but a decorator created an element descriptor' + ' with .placement "' + placement + '"'); 204 } 205 206 var descriptor = elementObject.descriptor; 207 this.disallowProperty(elementObject, "elements", "An element descriptor"); 208 var element = { 209 kind: kind, 210 key: key, 211 placement: placement, 212 descriptor: Object.assign({}, descriptor) 213 }; 214 215 if (kind !== "field") { 216 this.disallowProperty(elementObject, "initializer", "A method descriptor"); 217 } else { 218 this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); 219 this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); 220 this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); 221 element.initializer = elementObject.initializer; 222 } 223 224 return element; 225 }, 226 toElementFinisherExtras: function toElementFinisherExtras(elementObject) { 227 var element = this.toElementDescriptor(elementObject); 228 229 var finisher = _optionalCallableProperty(elementObject, "finisher"); 230 231 var extras = this.toElementDescriptors(elementObject.extras); 232 return { 233 element: element, 234 finisher: finisher, 235 extras: extras 236 }; 237 }, 238 fromClassDescriptor: function fromClassDescriptor(elements) { 239 var obj = { 240 kind: "class", 241 elements: elements.map(this.fromElementDescriptor, this) 242 }; 243 var desc = { 244 value: "Descriptor", 245 configurable: true 246 }; 247 Object.defineProperty(obj, Symbol.toStringTag, desc); 248 return obj; 249 }, 250 toClassDescriptor: function toClassDescriptor(obj) { 251 var kind = String(obj.kind); 252 253 if (kind !== "class") { 254 throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"'); 255 } 256 257 this.disallowProperty(obj, "key", "A class descriptor"); 258 this.disallowProperty(obj, "placement", "A class descriptor"); 259 this.disallowProperty(obj, "descriptor", "A class descriptor"); 260 this.disallowProperty(obj, "initializer", "A class descriptor"); 261 this.disallowProperty(obj, "extras", "A class descriptor"); 262 263 var finisher = _optionalCallableProperty(obj, "finisher"); 264 265 var elements = this.toElementDescriptors(obj.elements); 266 return { 267 elements: elements, 268 finisher: finisher 269 }; 270 }, 271 runClassFinishers: function runClassFinishers(constructor, finishers) { 272 for (var i = 0; i < finishers.length; i++) { 273 var newConstructor = (0, finishers[i])(constructor); 274 275 if (newConstructor !== undefined) { 276 if (typeof newConstructor !== "function") { 277 throw new TypeError("Finishers must return a constructor."); 278 } 279 280 constructor = newConstructor; 281 } 282 } 283 284 return constructor; 285 }, 286 disallowProperty: function disallowProperty(obj, name, objectType) { 287 if (obj[name] !== undefined) { 288 throw new TypeError(objectType + " can't have a ." + name + " property."); 289 } 290 } 291 }; 292 return api; 293 } 294 295 function _createElementDescriptor(def) { 296 var key = toPropertyKey(def.key); 297 var descriptor; 298 299 if (def.kind === "method") { 300 descriptor = { 301 value: def.value, 302 writable: true, 303 configurable: true, 304 enumerable: false 305 }; 306 } else if (def.kind === "get") { 307 descriptor = { 308 get: def.value, 309 configurable: true, 310 enumerable: false 311 }; 312 } else if (def.kind === "set") { 313 descriptor = { 314 set: def.value, 315 configurable: true, 316 enumerable: false 317 }; 318 } else if (def.kind === "field") { 319 descriptor = { 320 configurable: true, 321 writable: true, 322 enumerable: true 323 }; 324 } 325 326 var element = { 327 kind: def.kind === "field" ? "field" : "method", 328 key: key, 329 placement: def["static"] ? "static" : def.kind === "field" ? "own" : "prototype", 330 descriptor: descriptor 331 }; 332 if (def.decorators) element.decorators = def.decorators; 333 if (def.kind === "field") element.initializer = def.value; 334 return element; 335 } 336 337 function _coalesceGetterSetter(element, other) { 338 if (element.descriptor.get !== undefined) { 339 other.descriptor.get = element.descriptor.get; 340 } else { 341 other.descriptor.set = element.descriptor.set; 342 } 343 } 344 345 function _coalesceClassElements(elements) { 346 var newElements = []; 347 348 var isSameElement = function isSameElement(other) { 349 return other.kind === "method" && other.key === element.key && other.placement === element.placement; 350 }; 351 352 for (var i = 0; i < elements.length; i++) { 353 var element = elements[i]; 354 var other; 355 356 if (element.kind === "method" && (other = newElements.find(isSameElement))) { 357 if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { 358 if (_hasDecorators(element) || _hasDecorators(other)) { 359 throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated."); 360 } 361 362 other.descriptor = element.descriptor; 363 } else { 364 if (_hasDecorators(element)) { 365 if (_hasDecorators(other)) { 366 throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); 367 } 368 369 other.decorators = element.decorators; 370 } 371 372 _coalesceGetterSetter(element, other); 373 } 374 } else { 375 newElements.push(element); 376 } 377 } 378 379 return newElements; 380 } 381 382 function _hasDecorators(element) { 383 return element.decorators && element.decorators.length; 384 } 385 386 function _isDataDescriptor(desc) { 387 return desc !== undefined && !(desc.value === undefined && desc.writable === undefined); 388 } 389 390 function _optionalCallableProperty(obj, name) { 391 var value = obj[name]; 392 393 if (value !== undefined && typeof value !== "function") { 394 throw new TypeError("Expected '" + name + "' to be a function"); 395 } 396 397 return value; 398 } 399 400 module.exports = _decorate, module.exports.__esModule = true, module.exports["default"] = module.exports;