{"version":3,"file":"no_undefined_children_for_programmatic_components.mjs","sources":["../../src/rules/no_undefined_children_for_programmatic_components.ts"],"sourcesContent":["/**\n * @module @nhtio/eslint-config/rules/no_undefined_children_for_programmatic_components\n */\n\nimport { createRule } from './common'\n\n/**\n * An ESLint rule that disallows explicitly passing undefined as the children argument in calls to Vue's h function.\n */\nconst noUndefinedChildrenForProgrammaticComponents = createRule({\n  name: 'noUndefinedChildrenForProgrammaticComponents',\n  meta: {\n    type: 'problem',\n    docs: {\n      description:\n        \"Disallow explicitly passing undefined as the children argument in calls to Vue's h function, including when a children function returns an array with undefined values.\",\n    },\n    schema: [],\n    messages: {\n      undefinedChildren: 'The children argument of h() must not be set to undefined.',\n      undefinedChildrenFunction:\n        'The children function of h() returns an array containing undefined values.',\n    },\n  },\n  create(context) {\n    // Helper to detect if a node represents 'undefined'\n    function isUndefined(node: any) {\n      return (\n        node &&\n        ((node.type === 'Identifier' && node.name === 'undefined') ||\n          (node.type === 'UnaryExpression' && node.operator === 'void'))\n      )\n    }\n\n    // Check an array literal for any element that is undefined or conditionally returns undefined.\n    function checkArrayForUndefined(arrayNode: any) {\n      for (const element of arrayNode.elements) {\n        if (!element) continue // Skip holes\n        if (isUndefined(element)) {\n          return true\n        }\n        if (element.type === 'ConditionalExpression') {\n          // For patterns like: condition ? h(...) : undefined\n          if (isUndefined(element.alternate)) {\n            return true\n          }\n        }\n      }\n      return false\n    }\n\n    // Analyze a function used as the children argument.\n    // If the function immediately returns an array (or a filtered array), inspect it.\n    function analyzeFunctionReturn(fnNode: any) {\n      let returnedNode = null\n      // Arrow function with an expression body (or implicit return)\n      if (fnNode.type === 'ArrowFunctionExpression' && fnNode.expression) {\n        returnedNode = fnNode.body\n      } else if (\n        fnNode.type === 'ArrowFunctionExpression' ||\n        fnNode.type === 'FunctionExpression'\n      ) {\n        // Look for a single return statement in block bodies.\n        if (fnNode.body && fnNode.body.type === 'BlockStatement') {\n          for (const statement of fnNode.body.body) {\n            if (statement.type === 'ReturnStatement' && statement.argument) {\n              returnedNode = statement.argument\n              break\n            }\n          }\n        }\n      }\n      if (!returnedNode) {\n        return false\n      }\n      // If the returned node is an array literal, inspect it.\n      if (returnedNode.type === 'ArrayExpression') {\n        return checkArrayForUndefined(returnedNode)\n      }\n      // If the returned node is explicitly undefined.\n      if (isUndefined(returnedNode)) {\n        return true\n      }\n      // If it's a call expression on an array literal (e.g. [ ... ].filter(...)), inspect the array literal.\n      if (returnedNode.type === 'CallExpression') {\n        const callee = returnedNode.callee\n        if (\n          callee &&\n          callee.type === 'MemberExpression' &&\n          callee.object &&\n          callee.object.type === 'ArrayExpression'\n        ) {\n          return checkArrayForUndefined(callee.object)\n        }\n      }\n      return false\n    }\n\n    return {\n      CallExpression(node) {\n        // Check if this is a call to \"h\"\n        if (node.callee && node.callee.type === 'Identifier' && node.callee.name === 'h') {\n          // We expect h(tag, props, children)\n          if (node.arguments.length < 3) {\n            return\n          }\n          const childrenArg = node.arguments[2]\n\n          // Direct check: if children is explicitly undefined.\n          if (isUndefined(childrenArg)) {\n            context.report({\n              node: childrenArg,\n              messageId: 'undefinedChildren',\n            })\n            return\n          }\n\n          // If children is an array, check for undefined elements.\n          if (childrenArg.type === 'ArrayExpression') {\n            if (checkArrayForUndefined(childrenArg)) {\n              context.report({\n                node: childrenArg,\n                messageId: 'undefinedChildren',\n              })\n              return\n            }\n          }\n\n          // If children is a function, try to analyze its return value.\n          if (\n            childrenArg.type === 'ArrowFunctionExpression' ||\n            childrenArg.type === 'FunctionExpression'\n          ) {\n            if (analyzeFunctionReturn(childrenArg)) {\n              context.report({\n                node: childrenArg,\n                messageId: 'undefinedChildrenFunction',\n              })\n              return\n            }\n          }\n        }\n      },\n    }\n  },\n  defaultOptions: [],\n})\n\nexport default noUndefinedChildrenForProgrammaticComponents\n"],"names":["noUndefinedChildrenForProgrammaticComponents","createRule","context","isUndefined","node","checkArrayForUndefined","arrayNode","element","analyzeFunctionReturn","fnNode","returnedNode","statement","callee","childrenArg"],"mappings":";AASA,MAAMA,IAA+CC,EAAW;AAAA,EAC9D,MAAM;AAAA,EACN,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aACE;AAAA,IAAA;AAAA,IAEJ,QAAQ,CAAA;AAAA,IACR,UAAU;AAAA,MACR,mBAAmB;AAAA,MACnB,2BACE;AAAA,IAAA;AAAA,EACJ;AAAA,EAEF,OAAOC,GAAS;AAEd,aAASC,EAAYC,GAAW;AAC9B,aACEA,MACEA,EAAK,SAAS,gBAAgBA,EAAK,SAAS,eAC3CA,EAAK,SAAS,qBAAqBA,EAAK,aAAa;AAAA,IAE5D;AAGA,aAASC,EAAuBC,GAAgB;AAC9C,iBAAWC,KAAWD,EAAU;AAC9B,YAAKC,MACDJ,EAAYI,CAAO,KAGnBA,EAAQ,SAAS,2BAEfJ,EAAYI,EAAQ,SAAS;AAC/B,iBAAO;AAIb,aAAO;AAAA,IACT;AAIA,aAASC,EAAsBC,GAAa;AAC1C,UAAIC,IAAe;AAEnB,UAAID,EAAO,SAAS,6BAA6BA,EAAO;AACtD,QAAAC,IAAeD,EAAO;AAAA,gBAEtBA,EAAO,SAAS,6BAChBA,EAAO,SAAS,yBAGZA,EAAO,QAAQA,EAAO,KAAK,SAAS;AACtC,mBAAWE,KAAaF,EAAO,KAAK;AAClC,cAAIE,EAAU,SAAS,qBAAqBA,EAAU,UAAU;AAC9D,YAAAD,IAAeC,EAAU;AACzB;AAAA,UACF;AAAA;AAIN,UAAI,CAACD;AACH,eAAO;AAGT,UAAIA,EAAa,SAAS;AACxB,eAAOL,EAAuBK,CAAY;AAG5C,UAAIP,EAAYO,CAAY;AAC1B,eAAO;AAGT,UAAIA,EAAa,SAAS,kBAAkB;AAC1C,cAAME,IAASF,EAAa;AAC5B,YACEE,KACAA,EAAO,SAAS,sBAChBA,EAAO,UACPA,EAAO,OAAO,SAAS;AAEvB,iBAAOP,EAAuBO,EAAO,MAAM;AAAA,MAE/C;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,eAAeR,GAAM;AAEnB,YAAIA,EAAK,UAAUA,EAAK,OAAO,SAAS,gBAAgBA,EAAK,OAAO,SAAS,KAAK;AAEhF,cAAIA,EAAK,UAAU,SAAS;AAC1B;AAEF,gBAAMS,IAAcT,EAAK,UAAU,CAAC;AAGpC,cAAID,EAAYU,CAAW,GAAG;AAC5B,YAAAX,EAAQ,OAAO;AAAA,cACb,MAAMW;AAAA,cACN,WAAW;AAAA,YAAA,CACZ;AACD;AAAA,UACF;AAGA,cAAIA,EAAY,SAAS,qBACnBR,EAAuBQ,CAAW,GAAG;AACvC,YAAAX,EAAQ,OAAO;AAAA,cACb,MAAMW;AAAA,cACN,WAAW;AAAA,YAAA,CACZ;AACD;AAAA,UACF;AAIF,eACEA,EAAY,SAAS,6BACrBA,EAAY,SAAS,yBAEjBL,EAAsBK,CAAW,GAAG;AACtC,YAAAX,EAAQ,OAAO;AAAA,cACb,MAAMW;AAAA,cACN,WAAW;AAAA,YAAA,CACZ;AACD;AAAA,UACF;AAAA,QAEJ;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AAAA,EACA,gBAAgB,CAAA;AAClB,CAAC;"}