Skip to content

Commit 7496807

Browse files
ubugeeeiclaude
andauthored
fix: misskey parse error (#85)
* chore: add elk, misskey, npmx, vuefes submodules for testing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add Program parsing fallback for multi-statement event handlers in transform phase The transform phase's rewrite_expression lacked a Program parsing fallback for multi-statement expressions (e.g., `quoteId = null; renoteTargetNote = null;`). This caused SetupRef .value suffixes to be missing in template event handlers with semicolons. Fixes misskey MkPostForm.vue parse error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: format test code with rustfmt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove unused imports across workspace Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fmt --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 62681ab commit 7496807

18 files changed

Lines changed: 113 additions & 20 deletions

File tree

.gitmodules

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
[submodule "e2e/elk"]
1+
[submodule "tests/_fixtures/_git/elk"]
22
path = tests/_fixtures/_git/elk
33
url = https://github.com/elk-zone/elk
4-
[submodule "e2e/misskey"]
4+
[submodule "tests/_fixtures/_git/misskey"]
55
path = tests/_fixtures/_git/misskey
66
url = https://github.com/misskey-dev/misskey
7-
[submodule "e2e/npmx.dev"]
7+
[submodule "tests/_fixtures/_git/npmx.dev"]
88
path = tests/_fixtures/_git/npmx.dev
99
url = https://github.com/npmx-dev/npmx.dev
10-
[submodule "e2e/_git/vuefes-2025"]
10+
[submodule "tests/_fixtures/_git/vuefes-2025"]
1111
path = tests/_fixtures/_git/vuefes-2025
1212
url = https://github.com/vuejs-jp/vuefes-2025-website.git

crates/vize_atelier_core/src/runtime_helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub fn get_vnode_block_helper(ssr: bool, is_component: bool) -> RuntimeHelper {
7070

7171
#[cfg(test)]
7272
mod tests {
73-
use super::{get_vnode_block_helper, get_vnode_helper, RuntimeHelper, RuntimeHelpers};
73+
use super::{RuntimeHelper, RuntimeHelpers};
7474

7575
#[test]
7676
fn test_helpers() {

crates/vize_atelier_core/src/transforms/hoist_static.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ pub fn count_dynamic_children(children: &[TemplateChildNode<'_>]) -> usize {
477477

478478
#[cfg(test)]
479479
mod tests {
480-
use super::{get_static_type, is_static_node, StaticType};
480+
use super::{get_static_type, is_static_node};
481481
use crate::ast::{PropNode, TemplateChildNode};
482482
use crate::parser::parse;
483483
use bumpalo::Bump;

crates/vize_atelier_core/src/transforms/transform_expression/rewrite.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,50 @@ pub(crate) fn rewrite_expression(
9595
}
9696
}
9797
Err(_) => {
98-
// Parse failed - fallback to simple identifier check
98+
// Expression parsing failed - try parsing as a program (multi-statement handlers)
99+
let oxc_allocator2 = OxcAllocator::default();
100+
let parser2 = Parser::new(&oxc_allocator2, &js_content, source_type);
101+
let parse_result2 = parser2.parse();
102+
103+
if parse_result2.errors.is_empty() {
104+
// Successfully parsed as program - walk the AST and collect identifiers
105+
let mut collector = IdentifierCollector::new(ctx, &js_content);
106+
collector.visit_program(&parse_result2.program);
107+
108+
let used_unref = collector.used_unref;
109+
110+
let mut all_rewrites: Vec<(usize, String, String)> = collector
111+
.rewrites
112+
.into_iter()
113+
.map(|(pos, prefix)| (pos, prefix, String::default()))
114+
.collect();
115+
116+
for (pos, suffix) in collector.suffix_rewrites {
117+
all_rewrites.push((pos, String::default(), suffix));
118+
}
119+
120+
all_rewrites.sort_by(|a, b| b.0.cmp(&a.0));
121+
122+
let mut result = js_content.clone();
123+
for (pos, prefix, suffix) in all_rewrites {
124+
// No offset adjustment needed - program parsing has no wrapping parens
125+
if pos <= result.len() {
126+
if !suffix.is_empty() {
127+
result.insert_str(pos, &suffix);
128+
}
129+
if !prefix.is_empty() {
130+
result.insert_str(pos, &prefix);
131+
}
132+
}
133+
}
134+
135+
return RewriteResult {
136+
code: result,
137+
used_unref,
138+
};
139+
}
140+
141+
// Program parsing also failed - fallback to simple identifier check
99142
let code: String = if is_simple_identifier(&js_content) {
100143
if let Some(prefix) = get_identifier_prefix(&js_content, ctx) {
101144
let mut s = String::with_capacity(prefix.len() + js_content.len());

crates/vize_atelier_dom/src/lib.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,48 @@ mod tests {
181181
// Empty div generates minimal code
182182
assert!(!result.code.is_empty());
183183
}
184+
185+
#[test]
186+
fn test_event_handler_setup_ref_value() {
187+
use vize_atelier_core::options::BindingType;
188+
use vize_carton::FxHashMap;
189+
190+
let allocator = Bump::new();
191+
let mut bindings_map = FxHashMap::default();
192+
bindings_map.insert("quoteId".into(), BindingType::SetupRef);
193+
bindings_map.insert("renoteTargetNote".into(), BindingType::SetupRef);
194+
let binding_metadata = vize_atelier_core::options::BindingMetadata {
195+
bindings: bindings_map,
196+
props_aliases: FxHashMap::default(),
197+
is_script_setup: true,
198+
};
199+
200+
let opts = DomCompilerOptions {
201+
mode: CodegenMode::Module,
202+
prefix_identifiers: true,
203+
inline: true,
204+
cache_handlers: true,
205+
binding_metadata: Some(binding_metadata),
206+
..Default::default()
207+
};
208+
let template = r#"<button @click="quoteId = null; renoteTargetNote = null;">x</button>"#;
209+
let (_, errors, result) = compile_template_with_options(&allocator, template, opts);
210+
211+
eprintln!(
212+
"=== Template Output ===\npreamble:\n{}\ncode:\n{}",
213+
result.preamble, result.code
214+
);
215+
assert!(errors.is_empty(), "Errors: {:?}", errors);
216+
let full = format!("{}\n{}", result.preamble, result.code);
217+
assert!(
218+
full.contains("quoteId.value"),
219+
"quoteId should have .value in assignment. Got:\n{}",
220+
full
221+
);
222+
assert!(
223+
full.contains("renoteTargetNote.value"),
224+
"renoteTargetNote should have .value in assignment. Got:\n{}",
225+
full
226+
);
227+
}
184228
}

crates/vize_atelier_dom/src/transforms/v_model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ mod tests {
188188
use vize_atelier_core::{
189189
ElementNode, ExpressionNode, SimpleExpressionNode, SourceLocation,
190190
};
191-
use vize_carton::{cstr, Box, Bump};
191+
use vize_carton::{Box, Bump};
192192

193193
let allocator = Bump::new();
194194
let element = ElementNode::new(&allocator, "input", SourceLocation::STUB);

crates/vize_atelier_dom/src/transforms/v_show.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn generate_show_directive(dir: &DirectiveNode<'_>) -> String {
3333
mod tests {
3434
use super::{generate_show_directive, generate_show_style, is_v_show, RuntimeHelper, V_SHOW};
3535
use vize_atelier_core::{DirectiveNode, ExpressionNode, SimpleExpressionNode, SourceLocation};
36-
use vize_carton::{cstr, Box, Bump};
36+
use vize_carton::{Box, Bump};
3737

3838
fn create_show_directive<'a>(allocator: &'a Bump, exp: &str) -> DirectiveNode<'a> {
3939
let mut dir = DirectiveNode::new(allocator, "show", SourceLocation::STUB);

crates/vize_atelier_dom/src/transforms/v_text.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub fn generate_text_children(dir: &DirectiveNode<'_>) -> Option<String> {
3737
mod tests {
3838
use super::{generate_text_children, generate_text_content, is_v_text};
3939
use vize_atelier_core::{DirectiveNode, ExpressionNode, SimpleExpressionNode, SourceLocation};
40-
use vize_carton::{cstr, Box, Bump};
40+
use vize_carton::{Box, Bump};
4141

4242
fn create_test_directive<'a>(allocator: &'a Bump, name: &str, exp: &str) -> DirectiveNode<'a> {
4343
let mut dir = DirectiveNode::new(allocator, name, SourceLocation::STUB);

crates/vize_atelier_sfc/src/compile/tests.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ const editDashboard = ref()
236236
"Multi-statement handler should use block body ($event: any) => {{ ... }}. Got:\n{}",
237237
result.code
238238
);
239+
240+
// SetupRef assignment in template event handler should add .value
241+
assert!(
242+
result.code.contains("editDashboard.value"),
243+
"SetupRef assignment in event handler should add .value. Got:\n{}",
244+
result.code
245+
);
239246
}
240247

241248
#[test]

crates/vize_atelier_ssr/src/transforms/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ pub fn get_v_text_exp<'a>(el: &'a ElementNode<'a>) -> Option<&'a ExpressionNode<
8686

8787
#[cfg(test)]
8888
mod tests {
89-
use super::{
90-
get_v_html_exp, get_v_model_exp, get_v_show_exp, has_v_html, has_v_model, has_v_show,
91-
has_v_text,
92-
};
89+
use super::{get_v_model_exp, get_v_show_exp, has_v_html, has_v_model, has_v_show, has_v_text};
9390
use vize_atelier_core::ast::{
9491
DirectiveNode, ElementNode, ExpressionNode, PropNode, SimpleExpressionNode, SourceLocation,
9592
};

0 commit comments

Comments
 (0)