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