decorators.js
1 import { printType } from '@bablr/agast-helpers/print'; 2 import * as sym from './symbols.js'; 3 4 export const AllowEmpty = (desc, context) => { 5 context.addInitializer(function () { 6 let emptyables = this.emptyables; 7 8 if (!emptyables) { 9 emptyables = this.emptyables = new Set(); 10 } 11 12 emptyables.add(context.name); 13 }); 14 }; 15 16 export const CoveredBy = (type) => { 17 return (desc, context) => { 18 if (!/^[a-zA-Z]+$/.test(printType(type))) throw new Error(); 19 20 context.addInitializer(function () { 21 let covers = this.covers; 22 23 if (!covers) { 24 covers = this.covers = new Map(); 25 } 26 27 let coveredTypes = covers.get(type); 28 29 if (!coveredTypes) { 30 coveredTypes = new Set(); 31 covers.set(type, coveredTypes); 32 } 33 34 coveredTypes.add(context.name); 35 }); 36 }; 37 }; 38 39 export const InjectFrom = (obj) => (_stub, context) => { 40 if (!Object.hasOwn(obj, context.name)) { 41 throw new Error('Bad injection'); 42 } 43 44 return obj[context.name]; 45 }; 46 47 export const Node = (desc, context) => { 48 return CoveredBy(sym.node)(desc, context); 49 }; 50 51 export const Attributes = (attributes) => (desc, context) => { 52 context.addInitializer(function () { 53 this.attributes = this.attributes || new Map(); 54 this.attributes.set(context.name, attributes); 55 }); 56 }; 57 58 export const UnboundAttributes = (attributes) => (desc, context) => { 59 context.addInitializer(function () { 60 this.unboundAttributes = this.unboundAttributes || new Map(); 61 this.unboundAttributes.set(context.name, attributes); 62 }); 63 };