Skip to content

Commit f4316bb

Browse files
authored
jsgen: fix optional callback parameter and improve examples (fix #24325) (#24336)
1 parent 32be45d commit f4316bb

File tree

2 files changed

+141
-14
lines changed

2 files changed

+141
-14
lines changed

vlib/v/gen/js/js.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,8 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
19451945

19461946
if field.has_default_expr {
19471947
g.expr(field.default_expr)
1948+
} else if field.typ.has_flag(.option) {
1949+
g.write('none__')
19481950
} else {
19491951
g.write('${g.to_js_typ_val(field.typ)}')
19501952
}

vlib/v/gen/js/tests/callback.v

Lines changed: 139 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,163 @@
1-
struct FooParams {
2-
name string
3-
update fn (name string) @[required]
1+
// Test 1: Basic callbacks with struct fields
2+
struct FooProps {
3+
name string
4+
update fn (name string) @[required] // Required callback
5+
optional_cb ?fn () // Optional callback
46
}
57

6-
fn foo(params FooParams) {
8+
fn foo(params FooProps) {
79
params.update(params.name)
10+
if params.optional_cb != none {
11+
params.optional_cb()
12+
}
13+
}
14+
15+
// Test 2: Callbacks with return values
16+
struct CalculateProps {
17+
operation fn (a int, b int) int @[required]
18+
}
19+
20+
fn calculate(a int, b int, calc CalculateProps) int {
21+
return calc.operation(a, b)
22+
}
23+
24+
// Test 3: Callbacks in arrays
25+
fn map_array(arr []int, mapper fn (int) int) []int {
26+
mut result := []int{cap: arr.len}
27+
for item in arr {
28+
result << mapper(item)
29+
}
30+
return result
31+
}
32+
33+
// Test 4: Nested callbacks
34+
fn execute_with_callback(data string, processor fn (string, fn (string) string) string, formatter fn (string) string) string {
35+
return processor(data, formatter)
36+
}
37+
38+
// Test 5: Callback with mutable reference
39+
struct Counter {
40+
mut:
41+
count int
42+
}
43+
44+
fn with_counter(mut c Counter, callback fn (mut c Counter)) {
45+
callback(mut c)
846
}
947

1048
fn main() {
11-
// anonymous function callback
49+
println('=== Test 1: Basic callbacks with struct fields ===')
50+
51+
// 1.1: Anonymous function callback with optional callback
52+
println('1.1: Anonymous function with optional callback')
1253
foo(
13-
name: 'item 1'
14-
update: fn (name string) {
54+
name: 'item 1'
55+
update: fn (name string) {
1556
println('update ${name}')
1657
}
58+
optional_cb: fn () {
59+
println('optional callback')
60+
}
1761
)
1862

19-
// lambda function callback
63+
// 1.2: Lambda function callback without optional callback
64+
println('\n1.2: Lambda function without optional callback')
2065
update := fn (name string) {
2166
println('update ${name}')
2267
}
2368
foo(name: 'item 2', update: update)
2469

25-
// anonymous function field
26-
item_3 := FooParams{
70+
// 1.3: Anonymous function field
71+
println('\n1.3: Anonymous function field')
72+
item_3 := FooProps{
73+
name: 'item 3'
2774
update: fn (name string) {
2875
println('update ${name}')
2976
}
3077
}
31-
item_3.update('item 3')
78+
item_3.update(item_3.name)
3279

33-
// lambda function field
34-
item_4 := FooParams{
80+
// 1.4: Lambda function field
81+
println('\n1.4: Lambda function field')
82+
item_4 := FooProps{
83+
name: 'item 4'
3584
update: update
3685
}
37-
item_4.update('item 4')
86+
item_4.update(item_4.name)
87+
88+
println('\n=== Test 2: Callbacks with return values ===')
89+
90+
// 2.1: Addition callback
91+
println('2.1: Addition callback')
92+
add := fn (a int, b int) int {
93+
return a + b
94+
}
95+
add_calc := CalculateProps{
96+
operation: add
97+
}
98+
println('5 + 3 = ${calculate(5, 3, add_calc)}')
99+
100+
// 2.2: Anonymous multiplication callback
101+
println('\n2.2: Anonymous multiplication callback')
102+
mult_result := calculate(4, 6, CalculateProps{
103+
operation: fn (a int, b int) int {
104+
return a * b
105+
}
106+
})
107+
println('4 * 6 = ${mult_result}')
108+
109+
println('\n=== Test 3: Callbacks in arrays ===')
110+
111+
// 3.1: Double each element
112+
println('3.1: Double each element')
113+
numbers := [1, 2, 3, 4, 5]
114+
doubled := map_array(numbers, fn (n int) int {
115+
return n * 2
116+
})
117+
println('Original: ${numbers}')
118+
println('Doubled: ${doubled}')
119+
120+
// 3.2: Square each element using lambda
121+
println('\n3.2: Square each element')
122+
square := fn (n int) int {
123+
return n * n
124+
}
125+
squared := map_array(numbers, square)
126+
println('Original: ${numbers}')
127+
println('Squared: ${squared}')
128+
129+
println('\n=== Test 4: Nested callbacks ===')
130+
131+
// 4.1: Process and format text
132+
println('4.1: Process and format text')
133+
processor := fn (data string, formatter fn (string) string) string {
134+
processed := data + ' processed'
135+
return formatter(processed)
136+
}
137+
138+
formatter := fn (s string) string {
139+
return '[${s.to_upper()}]'
140+
}
141+
142+
result := execute_with_callback('data', processor, formatter)
143+
println('Result: ${result}')
144+
145+
println('\n=== Test 5: Callback with mutable reference ===')
146+
147+
// 5.1: Increment counter
148+
println('5.1: Increment counter')
149+
mut counter := Counter{
150+
count: 0
151+
}
152+
153+
increment := fn (mut c Counter) {
154+
c.count++
155+
println('Counter incremented to ${c.count}')
156+
}
157+
158+
with_counter(mut counter, increment)
159+
with_counter(mut counter, increment)
160+
with_counter(mut counter, increment)
161+
162+
println('Final counter value: ${counter.count}')
38163
}

0 commit comments

Comments
 (0)