{"record":{"id":"5d5c67ba611c03ab","repo":"oxc-project/oxc","slug":"inline-helpers-are-not-supported-yet","errorCode":null,"errorMessage":"Inline helpers are not supported yet","messagePattern":"Inline helpers are not supported yet","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/oxc_transformer/src/common/helper_loader.rs","lineNumber":321,"sourceCode":"            let existing = ctx.state.helper_loader.loaded_helpers.get(&helper).cloned();\n            if let Some(binding) = existing {\n                return binding.create_read_expression(ctx);\n            }\n\n            // Generate new binding\n            let is_module = ctx.state.source_type.is_module();\n            let flag =\n                if is_module { SymbolFlags::Import } else { SymbolFlags::FunctionScopedVariable };\n            let binding = ctx.generate_uid_in_root_scope(helper.name(), flag);\n\n            ctx.state.module_imports.add_default_import(source, binding.clone(), false);\n            ctx.state.helper_loader.loaded_helpers.insert(helper, binding.clone());\n\n            binding.create_read_expression(ctx)\n        }\n        HelperLoaderMode::External => HelperLoaderStore::transform_for_external_helper(helper, ctx),\n        HelperLoaderMode::Inline => {\n            unreachable!(\"Inline helpers are not supported yet\");\n        }\n    }\n}\n\n// Internal methods\nimpl<'a> HelperLoaderStore<'a> {\n    // Construct string directly in arena without an intermediate temp allocation\n    fn get_runtime_source(&self, helper: Helper, ctx: &TraverseCtx<'a>) -> Str<'a> {\n        Str::from_strs_array_in([&self.module_name, \"/helpers/\", helper.name()], ctx)\n    }\n\n    fn transform_for_external_helper(helper: Helper, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {\n        let helper_var = static_ident!(\"babelHelpers\");\n        let symbol_id = ctx.scoping().find_binding(ctx.current_scope_id(), helper_var);\n        let object = ctx.create_ident_expr(SPAN, helper_var, symbol_id, ReferenceFlags::Read);\n        let property = IdentifierName::new(SPAN, helper.name(), ctx);\n        Expression::new_static_member_expression(SPAN, object, property, false, ctx)\n    }","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_transformer/src/common/helper_loader.rs#L303-L339","documentation":"Diagnostic from oxlint's vue/valid-define-emits rule (crates/oxc_linter/src/rules/vue/valid_define_emits.rs). It fires when `defineEmits()` is called with neither an argument nor a type parameter and the SFC's sibling plain `<script>` block does not provide `emits` on its default export — so no events are declared anywhere. Undeclared events break the component contract, devtools introspection, and Vue's attribute-fallthrough behavior.","triggerScenarios":"A bare `defineEmits()` in `<script setup>` when there is no `export default { emits: ... }` in another script block of the same SFC. Declaring events via array, object, type parameter, or the options block avoids it; `defineEmits(unresolvedVariable)` is not reported because the events cannot be statically known.","commonSituations":"Scaffolding `const emit = defineEmits()` as boilerplate before events are known; refactoring events out of the options API but leaving the macro call empty.","solutions":["Declare the events: `defineEmits(['notify'])`, an object with validators, or a TS call-signature type.","If the component emits nothing, remove the defineEmits call and any emit usages entirely.","Alternatively keep events in the sibling `<script>`'s `export default { emits: [...] }` and leave `defineEmits()` bare — but declaring next to the macro is clearer."],"exampleFix":"// before\nconst emit = defineEmits();\n\n// after\nconst emit = defineEmits(['notify', 'submit']);","handlingStrategy":"validation","validationCode":"// a bare defineEmits() must be accompanied by options emits or removed\nconst m = setupSource.match(/defineEmits\\s*(<[^>]*>)?\\s*\\(([^)]*)\\)/);\nif (m && !m[1] && !m[2].trim() && !optionsBlockHasEmits) {\n  throw new Error('defineEmits() declares no events');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never scaffold `const emit = defineEmits()` without listing events.","If the component emits nothing, delete the macro and any emit calls.","Declare events where they are emitted, next to the macro call."],"tags":["vue","oxlint","lint","script-setup","defineemits","compiler-macro"],"backgroundTag":"vue-define-emits-misuse","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}