UNPKG

@alterior/annotations

Version:
74 lines 2.57 kB
import { getParameterNames } from '@alterior/common'; import { Annotation } from './annotations'; /** * Mutators are a way to define "mutation decorators" which in some way change the value * of the elements they are applied to, as opposed to "annotation decorators", which primarily * attach metadata. * * Create a mutator with Mutator.create(). */ export class Mutator { /** * Low-level method to ceate a new mutation decorator (mutator) based on the given function. * Use `Mutator.define()` instead. */ static create(mutator, options) { return Annotation.decorator(Object.assign({}, options || {}, { factory: (target, ...args) => { let paramNames; let orig = target.propertyDescriptor.value; if (typeof orig === 'function') { paramNames = getParameterNames(target.propertyDescriptor.value); } mutator(target, ...args); let replacement = target.propertyDescriptor.value; if (orig !== replacement && paramNames !== undefined && !Object.hasOwn(replacement, '__parameterNames')) { Object.defineProperty(replacement, '__parameterNames', { value: paramNames }); } } })); } /** * Define a new mutation decorator (mutator). * This should be called and returned from a * function definition. For example: * ``` function Name() { return Mutator.define({ invoke(site) { // ... } }) } ``` * * The `invoke()` function takes a DecoratorSite object which describes the particular * invocation that is being run, and importantly, access to the property descriptor * for the property being defined. If you wish to completely replace (or wrap) the * default value of the property or method you are replacing, set the `value` * property of the property descriptor with `site.propertyDescriptor.value` * * For example: * ``` export function RunTwice() { return Mutator.create( site => { let prop = site.propertyDescriptor; let original = prop.value; let replacement = function(...args) { original.apply(this, args); original.apply(this, args); } prop.value = replacement; } ) * ``` */ static define(definition) { return this.create(definition.invoke, definition.options)(); } } //# sourceMappingURL=mutator.js.map