Skip to content

Commit 717a6ac

Browse files
committed
fix(compiler-rs): move context.slots to block.slots for nested slots
1 parent 7332859 commit 717a6ac

File tree

7 files changed

+60
-32
lines changed

7 files changed

+60
-32
lines changed

packages/compiler-rs/src/ir/index.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub struct BlockIRNode<'a> {
7070
pub effect: Vec<IREffect<'a>>,
7171
pub operation: Vec<OperationNode<'a>>,
7272
pub returns: Vec<i32>,
73+
pub slots: Vec<IRSlots<'a>>,
7374
pub props: Option<SimpleExpressionNode<'a>>,
7475
}
7576
impl<'a> BlockIRNode<'a> {
@@ -80,6 +81,7 @@ impl<'a> BlockIRNode<'a> {
8081
effect: Vec::new(),
8182
operation: Vec::new(),
8283
returns: Vec::new(),
84+
slots: Vec::new(),
8385
props: None,
8486
}
8587
}

packages/compiler-rs/src/transform.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,9 @@ use crate::compile::Template;
3131
use crate::generate::CodegenContext;
3232
use crate::traverse::jsx::JsxTraverse;
3333
use crate::{
34-
ir::{
35-
component::IRSlots,
36-
index::{
37-
BlockIRNode, DynamicFlag, IRDynamicInfo, IREffect, Modifiers, OperationNode, RootIRNode,
38-
RootNode, SimpleExpressionNode,
39-
},
34+
ir::index::{
35+
BlockIRNode, DynamicFlag, IRDynamicInfo, IREffect, Modifiers, OperationNode, RootIRNode,
36+
RootNode, SimpleExpressionNode,
4037
},
4138
transform::{
4239
transform_children::transform_children, transform_element::transform_element,
@@ -125,8 +122,6 @@ pub struct TransformContext<'a> {
125122
pub in_v_once: RefCell<bool>,
126123
pub in_v_for: RefCell<i32>,
127124

128-
pub slots: RefCell<Vec<IRSlots<'a>>>,
129-
130125
pub seen: Rc<RefCell<HashSet<u32>>>,
131126

132127
global_id: RefCell<i32>,
@@ -146,7 +141,6 @@ impl<'a> TransformContext<'a> {
146141
children_template: RefCell::new(Vec::new()),
147142
in_v_once: RefCell::new(false),
148143
in_v_for: RefCell::new(0),
149-
slots: RefCell::new(Vec::new()),
150144
seen: Rc::new(RefCell::new(HashSet::new())),
151145
global_id: RefCell::new(0),
152146
node: RefCell::new(Either::A(RootNode::new(allocator))),
@@ -164,7 +158,6 @@ impl<'a> TransformContext<'a> {
164158
*self.block.borrow_mut() = mem::take(&mut ir.block);
165159
*self.ir.borrow_mut() = ir;
166160
*self.index.borrow_mut() = 0;
167-
*self.slots.borrow_mut() = vec![];
168161
*self.template.borrow_mut() = String::new();
169162
*self.children_template.borrow_mut() = vec![];
170163
*self.in_v_once.borrow_mut() = false;
@@ -280,18 +273,12 @@ impl<'a> TransformContext<'a> {
280273
context_block: &'a mut BlockIRNode<'a>,
281274
ir: BlockIRNode<'a>,
282275
is_v_for: bool,
283-
exclude_slots: bool,
284276
) -> Box<dyn FnOnce() -> BlockIRNode<'a> + 'a> {
285277
let block = mem::take(&mut *context_block);
286278
let template = mem::take(&mut *self.template.borrow_mut());
287279
let children_template = mem::take(&mut *self.children_template.borrow_mut());
288-
let mut slots = None;
289280

290281
*context_block = ir;
291-
if !exclude_slots {
292-
slots = Some(mem::take(&mut *self.slots.borrow_mut()));
293-
}
294-
295282
if is_v_for {
296283
*self.in_v_for.borrow_mut() += 1;
297284
}
@@ -303,9 +290,6 @@ impl<'a> TransformContext<'a> {
303290
*context_block = block;
304291
*self.template.borrow_mut() = template;
305292
*self.children_template.borrow_mut() = children_template;
306-
if !exclude_slots && let Some(slots) = slots {
307-
*self.slots.borrow_mut() = slots;
308-
}
309293
if is_v_for {
310294
*self.in_v_for.borrow_mut() -= 1;
311295
}
@@ -363,7 +347,6 @@ impl<'a> TransformContext<'a> {
363347
unsafe { &mut *_context_block },
364348
block,
365349
is_v_for.unwrap_or(false),
366-
false,
367350
);
368351
self.reference(&mut context_block.dynamic);
369352
exit_block

packages/compiler-rs/src/transform/transform_element.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{cell::RefCell, rc::Rc};
1+
use std::{cell::RefCell, mem, rc::Rc};
22

33
use napi::{
44
Either,
@@ -239,7 +239,7 @@ pub fn transform_component_element<'a>(
239239
},
240240
asset,
241241
root: single_root && *context.in_v_for.borrow() == 0,
242-
slots: context.slots.take(),
242+
slots: mem::take(&mut context_block.slots),
243243
once: *context.in_v_once.borrow(),
244244
parent: None,
245245
anchor: None,

packages/compiler-rs/src/transform/v_slot.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::mem;
2+
13
use indexmap::IndexMap;
24
use napi::{Either, bindgen_prelude::Either4};
35
use oxc_ast::ast::{JSXChild, JSXElement};
@@ -84,10 +86,11 @@ fn transform_component_slot<'a>(
8486
})
8587
.count();
8688

87-
let exit_block = create_slot_block(exp, context, context_block, false);
89+
let context_block = context_block as *mut BlockIRNode;
90+
let exit_block = create_slot_block(exp, context, unsafe { &mut *context_block });
8891

8992
Box::new(move || {
90-
let mut slots = context.slots.take();
93+
let mut slots = mem::take(&mut unsafe { &mut *context_block }.slots);
9194

9295
let block = exit_block();
9396
let has_other_slots = !slots.is_empty();
@@ -105,10 +108,10 @@ fn transform_component_slot<'a>(
105108
);
106109
} else {
107110
register_slot(&mut slots, arg, block);
108-
*context.slots.borrow_mut() = slots;
111+
unsafe { &mut *context_block }.slots = slots;
109112
}
110113
} else if has_other_slots {
111-
*context.slots.borrow_mut() = slots
114+
unsafe { &mut *context_block }.slots = slots
112115
}
113116
})
114117
}
@@ -120,11 +123,12 @@ fn transform_template_slot<'a>(
120123
context: &'a TransformContext<'a>,
121124
context_block: &'a mut BlockIRNode<'a>,
122125
) -> Box<dyn FnOnce() + 'a> {
126+
let _context_block = context_block as *mut BlockIRNode;
123127
let dynamic = &mut context_block.dynamic;
124128
dynamic.flags |= DynamicFlag::NonTemplate as i32;
125129

126130
let DirectiveNode { arg, exp, .. } = dir;
127-
let exit_block = create_slot_block(exp, context, context_block, true);
131+
let exit_block = create_slot_block(exp, context, context_block);
128132

129133
let v_for = find_prop_mut(unsafe { &mut *node }, Either::A(String::from("v-for")));
130134
let for_parse_result = if let Some(v_for) = v_for {
@@ -141,7 +145,7 @@ fn transform_template_slot<'a>(
141145
let v_else_dir = v_else.map(|v_else| resolve_directive(v_else, context));
142146

143147
Box::new(move || {
144-
let slots = &mut context.slots.borrow_mut();
148+
let slots = &mut unsafe { &mut *_context_block }.slots;
145149
let block = exit_block();
146150
if v_if_dir.is_none() && v_else_dir.is_none() && for_parse_result.is_none() {
147151
let slot_name = if let Some(arg) = &arg {
@@ -268,10 +272,9 @@ fn create_slot_block<'a>(
268272
props: Option<SimpleExpressionNode<'a>>,
269273
context: &'a TransformContext<'a>,
270274
context_block: &'a mut BlockIRNode<'a>,
271-
exclude_slots: bool,
272275
) -> Box<dyn FnOnce() -> BlockIRNode<'a> + 'a> {
273276
let mut block = BlockIRNode::new();
274277
block.props = props;
275278

276-
(context.enter_block(context_block, block, false, exclude_slots)) as _
279+
(context.enter_block(context_block, block, false)) as _
277280
}

packages/compiler-rs/src/transform/v_slots.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
pub unsafe fn transform_v_slots<'a>(
1818
context_node: *mut ContextNode<'a>,
1919
context: &'a TransformContext<'a>,
20-
_: &'a mut BlockIRNode<'a>,
20+
context_block: &'a mut BlockIRNode<'a>,
2121
_: &'a mut ContextNode<'a>,
2222
) -> Option<Box<dyn FnOnce() + 'a>> {
2323
let Either::B(JSXChild::Element(node)) = (unsafe { &mut *context_node }) else {
@@ -41,7 +41,7 @@ pub unsafe fn transform_v_slots<'a>(
4141
let slots =
4242
SimpleExpressionNode::new(Either3::A(value.expression.to_expression_mut()), context);
4343
Some(Box::new(move || {
44-
*context.slots.borrow_mut() = vec![Either4::D(IRSlotsExpression {
44+
context_block.slots = vec![Either4::D(IRSlotsExpression {
4545
slot_type: IRSlotType::EXPRESSION,
4646
slots,
4747
})];
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
source: tests/v_slot.rs
3+
expression: code
4+
---
5+
import { createComponent as _createComponent } from "vue-jsx-vapor";
6+
import { template as _template } from "vue";
7+
const t0 = _template("foo");
8+
(() => {
9+
const n10 = _createComponent(Comp, null, {
10+
left: () => {
11+
const n1 = t0();
12+
return n1;
13+
},
14+
right: () => {
15+
const n6 = _createComponent(Comp, null, { left: () => {
16+
const n5 = t0();
17+
return n5;
18+
} });
19+
return n6;
20+
}
21+
}, true);
22+
return n10;
23+
})();

packages/compiler-rs/tests/v_slot.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ fn on_component_named_slot() {
3434
assert!(code.contains("{ foo: _slotProps0.foo }"));
3535
}
3636

37+
#[test]
38+
fn on_component_named_slot_multiple() {
39+
let code = transform(
40+
"<Comp>
41+
<template v-slot:left>
42+
foo
43+
</template>
44+
<template v-slot:right>
45+
<Comp v-slot:left>foo</Comp>
46+
</template>
47+
</Comp>",
48+
None,
49+
)
50+
.code;
51+
assert_snapshot!(code);
52+
}
53+
3754
#[test]
3855
fn on_component_dynamically_named_slot() {
3956
let code = transform("<Comp v-slot:$named$={{ foo }}>{ foo + bar }</Comp>", None).code;

0 commit comments

Comments
 (0)