use crate::write::{LinkSink, Writer};
use vize_l0::Span;
use vize_l2::lang::js::VueSetup;
pub const COMPONENT_BINDING: &str = "_sfc_main";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SetupEmitErrorKind {
MissingBinding,
GeneratedBindingCollision,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SetupEmitError {
pub span: Span,
pub kind: SetupEmitErrorKind,
}
pub fn emit_setup<L: LinkSink>(
setup: &VueSetup<'_, '_, '_, '_>,
) -> Result<Writer<L>, SetupEmitError> {
let fail = |span, kind| SetupEmitError { span, kind };
for binding in setup.bindings() {
let declaration = binding
.declaration()
.ok_or_else(|| fail(setup.source().span(), SetupEmitErrorKind::MissingBinding))?;
if matches!(declaration.name.as_str(), "Object" | "__value" | "__v_raw") {
return Err(fail(
declaration.span,
SetupEmitErrorKind::GeneratedBindingCollision,
));
}
}
let mut writer = Writer::default();
writer.push("const _sfc_main = {\n setup(__props, { expose: __expose }) {\n __expose();\n");
let source = setup.source();
writer.push_linked(source.source(), source.span());
writer.push("\n;\n const __returned__ = {\n");
for binding in setup.bindings() {
let declaration = binding
.declaration()
.ok_or_else(|| fail(source.span(), SetupEmitErrorKind::MissingBinding))?;
let name = declaration.name.as_str();
let span = declaration.span;
writer.push(" get ");
writer.push_named(name, span, name);
writer.push("() { return ");
writer.push_named(name, span, name);
writer.push(" },\n set ");
writer.push_named(name, span, name);
writer.push("(__value) { ");
writer.push_named(name, span, name);
writer.push(" = __value },\n");
}
writer.push(" };\n Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true });\n return __returned__;\n }\n}\n");
Ok(writer)
}