Skip to content

Commit fb027eb

Browse files
authored
[1.x] Proper async/await usage in resolving props (kapi2289#29)
* Proper async/await usage in resolving props * Resolve when invoking object is a Task
1 parent 06531d3 commit fb027eb

File tree

10 files changed

+83
-79
lines changed

10 files changed

+83
-79
lines changed

InertiaCore/Props/AlwaysProp.cs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
namespace InertiaCore.Props;
22

3-
public class AlwaysProp
3+
public class AlwaysProp : InvokableProp
44
{
5-
private readonly object? _value;
5+
internal AlwaysProp(object? value) : base(value)
6+
{
7+
}
68

7-
public AlwaysProp(object? value)
9+
internal AlwaysProp(Func<object?> value) : base(value)
810
{
9-
_value = value;
1011
}
1112

12-
public object? Invoke()
13+
internal AlwaysProp(Func<Task<object?>> value) : base(value)
1314
{
14-
// Check if the value is a callable delegate
15-
return Task.Run(async () =>
16-
{
17-
return _value switch
18-
{
19-
Func<Task<object?>> asyncCallable => await asyncCallable.Invoke(),
20-
Func<object?> callable => callable.Invoke(),
21-
_ => _value
22-
};
23-
}).GetAwaiter().GetResult();
2415
}
2516
}

InertiaCore/Props/InvokableProp.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace InertiaCore.Props;
2+
3+
public class InvokableProp
4+
{
5+
private readonly object? _value;
6+
7+
protected InvokableProp(object? value) => _value = value;
8+
9+
internal Task<object?> Invoke()
10+
{
11+
return _value switch
12+
{
13+
Func<Task<object?>> asyncCallable => asyncCallable.Invoke(),
14+
Func<object?> callable => Task.Run(() => callable.Invoke()),
15+
Task<object?> value => value,
16+
_ => Task.FromResult(_value)
17+
};
18+
}
19+
}

InertiaCore/Props/LazyProp.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
namespace InertiaCore.Props;
22

3-
public class LazyProp
3+
public class LazyProp : InvokableProp
44
{
5-
private readonly Func<Task<object?>> _callback;
5+
internal LazyProp(Func<object?> value) : base(value)
6+
{
7+
}
68

7-
public LazyProp(Func<object?> callback) => _callback = async () => await Task.FromResult(callback());
8-
public LazyProp(Func<Task<object?>> callback) => _callback = callback;
9-
10-
public object? Invoke() => Task.Run(() => _callback.Invoke()).GetAwaiter().GetResult();
9+
internal LazyProp(Func<Task<object?>> value) : base(value)
10+
{
11+
}
1112
}

InertiaCore/Response.cs

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,20 @@ public Response(string component, object props, string rootView, string? version
2727
public async Task ExecuteResultAsync(ActionContext context)
2828
{
2929
SetContext(context);
30-
ProcessResponse();
30+
await ProcessResponse();
3131

3232
await GetResult().ExecuteResultAsync(_context!);
3333
}
3434

35-
protected internal void ProcessResponse()
35+
protected internal async Task ProcessResponse()
3636
{
3737
var page = new Page
3838
{
3939
Component = _component,
4040
Version = _version,
4141
Url = _context!.RequestedUri(),
42-
Props = ResolveProperties(_props.GetType().GetProperties().ToDictionary(o => o.Name.ToCamelCase(), o => o.GetValue(_props)))
42+
Props = await ResolveProperties(_props.GetType().GetProperties()
43+
.ToDictionary(o => o.Name.ToCamelCase(), o => o.GetValue(_props)))
4344
};
4445

4546
var shared = _context!.HttpContext.Features.Get<InertiaSharedData>();
@@ -51,15 +52,15 @@ protected internal void ProcessResponse()
5152
SetPage(page);
5253
}
5354

54-
private static Dictionary<string, object?> PrepareProps(Dictionary<string, object?> props)
55+
private static async Task<Dictionary<string, object?>> PrepareProps(Dictionary<string, object?> props)
5556
{
56-
return props.ToDictionary(pair => pair.Key, pair => pair.Value switch
57+
return (await Task.WhenAll(props.Select(async pair => pair.Value switch
5758
{
58-
Func<object?> f => f.Invoke(),
59-
LazyProp l => l.Invoke(),
60-
AlwaysProp l => l.Invoke(),
61-
_ => pair.Value
62-
});
59+
Func<object?> f => (pair.Key, f.Invoke()),
60+
LazyProp l => (pair.Key, await l.Invoke()),
61+
AlwaysProp l => (pair.Key, await l.Invoke()),
62+
_ => (pair.Key, pair.Value)
63+
}))).ToDictionary(pair => pair.Key, pair => pair.Item2);
6364
}
6465

6566
protected internal JsonResult GetJson()
@@ -111,7 +112,7 @@ public Response WithViewData(IDictionary<string, object> viewData)
111112
return this;
112113
}
113114

114-
private Dictionary<string, object?> ResolveProperties(Dictionary<string, object?> props)
115+
private async Task<Dictionary<string, object?>> ResolveProperties(Dictionary<string, object?> props)
115116
{
116117
var isPartial = _context!.IsInertiaPartialComponent(_component);
117118

@@ -126,37 +127,29 @@ public Response WithViewData(IDictionary<string, object> viewData)
126127
props = props.ToDictionary(kv => kv.Key, kv => kv.Value);
127128

128129
if (_context!.HttpContext.Request.Headers.ContainsKey(InertiaHeader.PartialOnly))
129-
{
130130
props = ResolveOnly(props);
131-
}
132131

133132
if (_context!.HttpContext.Request.Headers.ContainsKey(InertiaHeader.PartialExcept))
134-
{
135133
props = ResolveExcept(props);
136-
}
137134
}
138135

139136
props = ResolveAlways(props);
140-
props = PrepareProps(props);
137+
props = await PrepareProps(props);
141138

142139
return props;
143140
}
144141

145142
private Dictionary<string, object?> ResolveOnly(Dictionary<string, object?> props)
146-
{
147-
return _context!.OnlyProps(props);
148-
}
143+
=> _context!.OnlyProps(props);
149144

150145
private Dictionary<string, object?> ResolveExcept(Dictionary<string, object?> props)
151-
{
152-
return _context!.ExceptProps(props);
153-
}
146+
=> _context!.ExceptProps(props);
154147

155148
private Dictionary<string, object?> ResolveAlways(Dictionary<string, object?> props)
156149
{
157150
var alwaysProps = _props.GetType().GetProperties()
158-
.Where(o => o.PropertyType == typeof(AlwaysProp))
159-
.ToDictionary(o => o.Name.ToCamelCase(), o => o.GetValue(_props));
151+
.Where(o => o.PropertyType == typeof(AlwaysProp))
152+
.ToDictionary(o => o.Name.ToCamelCase(), o => o.GetValue(_props));
160153

161154
return props
162155
.Where(kv => kv.Value is not AlwaysProp)

InertiaCoreTests/UnitTestAlwaysData.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public partial class Tests
77
{
88
[Test]
99
[Description("Test if the always data is fetched properly.")]
10-
public void TestAlwaysData()
10+
public async Task TestAlwaysData()
1111
{
1212
var response = _factory.Render("Test/Page", new
1313
{
@@ -19,7 +19,7 @@ public void TestAlwaysData()
1919
var context = PrepareContext();
2020

2121
response.SetContext(context);
22-
response.ProcessResponse();
22+
await response.ProcessResponse();
2323

2424
var page = response.GetJson().Value as Page;
2525

@@ -34,7 +34,7 @@ public void TestAlwaysData()
3434

3535
[Test]
3636
[Description("Test if the always data is fetched properly with specified partial props.")]
37-
public void TestAlwaysPartialData()
37+
public async Task TestAlwaysPartialData()
3838
{
3939
var response = _factory.Render("Test/Page", new
4040
{
@@ -51,7 +51,7 @@ public void TestAlwaysPartialData()
5151
var context = PrepareContext(headers);
5252

5353
response.SetContext(context);
54-
response.ProcessResponse();
54+
await response.ProcessResponse();
5555

5656
var page = response.GetJson().Value as Page;
5757

@@ -65,7 +65,7 @@ public void TestAlwaysPartialData()
6565

6666
[Test]
6767
[Description("Test if the always async data is fetched properly.")]
68-
public void TestAlwaysAsyncData()
68+
public async Task TestAlwaysAsyncData()
6969
{
7070
var testFunction = new Func<Task<object?>>(async () =>
7171
{
@@ -83,7 +83,7 @@ public void TestAlwaysAsyncData()
8383
var context = PrepareContext();
8484

8585
response.SetContext(context);
86-
response.ProcessResponse();
86+
await response.ProcessResponse();
8787

8888
var page = response.GetJson().Value as Page;
8989

@@ -98,7 +98,7 @@ public void TestAlwaysAsyncData()
9898

9999
[Test]
100100
[Description("Test if the always async data is fetched properly with specified partial props.")]
101-
public void TestAlwaysAsyncPartialData()
101+
public async Task TestAlwaysAsyncPartialData()
102102
{
103103
var testFunction = new Func<Task<string>>(async () =>
104104
{
@@ -121,7 +121,7 @@ public void TestAlwaysAsyncPartialData()
121121
var context = PrepareContext(headers);
122122

123123
response.SetContext(context);
124-
response.ProcessResponse();
124+
await response.ProcessResponse();
125125

126126
var page = response.GetJson().Value as Page;
127127

@@ -135,7 +135,7 @@ public void TestAlwaysAsyncPartialData()
135135

136136
[Test]
137137
[Description("Test if the always async data is fetched properly without specified partial props.")]
138-
public void TestAlwaysAsyncPartialDataOmitted()
138+
public async Task TestAlwaysAsyncPartialDataOmitted()
139139
{
140140
var testFunction = new Func<Task<string>>(async () =>
141141
{
@@ -159,7 +159,7 @@ public void TestAlwaysAsyncPartialDataOmitted()
159159
var context = PrepareContext(headers);
160160

161161
response.SetContext(context);
162-
response.ProcessResponse();
162+
await response.ProcessResponse();
163163

164164
var page = response.GetJson().Value as Page;
165165

InertiaCoreTests/UnitTestLazyData.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public partial class Tests
77
{
88
[Test]
99
[Description("Test if the lazy data is fetched properly.")]
10-
public void TestLazyData()
10+
public async Task TestLazyData()
1111
{
1212
var response = _factory.Render("Test/Page", new
1313
{
@@ -23,7 +23,7 @@ public void TestLazyData()
2323
var context = PrepareContext();
2424

2525
response.SetContext(context);
26-
response.ProcessResponse();
26+
await response.ProcessResponse();
2727

2828
var page = response.GetJson().Value as Page;
2929

@@ -37,7 +37,7 @@ public void TestLazyData()
3737

3838
[Test]
3939
[Description("Test if the lazy data is fetched properly with specified partial props.")]
40-
public void TestLazyPartialData()
40+
public async Task TestLazyPartialData()
4141
{
4242
var response = _factory.Render("Test/Page", new
4343
{
@@ -54,7 +54,7 @@ public void TestLazyPartialData()
5454
var context = PrepareContext(headers);
5555

5656
response.SetContext(context);
57-
response.ProcessResponse();
57+
await response.ProcessResponse();
5858

5959
var page = response.GetJson().Value as Page;
6060

@@ -69,7 +69,7 @@ public void TestLazyPartialData()
6969

7070
[Test]
7171
[Description("Test if the lazy async data is fetched properly.")]
72-
public void TestLazyAsyncData()
72+
public async Task TestLazyAsyncData()
7373
{
7474
var testFunction = new Func<Task<object?>>(async () =>
7575
{
@@ -88,7 +88,7 @@ public void TestLazyAsyncData()
8888
var context = PrepareContext();
8989

9090
response.SetContext(context);
91-
response.ProcessResponse();
91+
await response.ProcessResponse();
9292

9393
var page = response.GetJson().Value as Page;
9494

@@ -102,7 +102,7 @@ public void TestLazyAsyncData()
102102

103103
[Test]
104104
[Description("Test if the lazy async data is fetched properly with specified partial props.")]
105-
public void TestLazyAsyncPartialData()
105+
public async Task TestLazyAsyncPartialData()
106106
{
107107
var testFunction = new Func<Task<string>>(async () =>
108108
{
@@ -125,7 +125,7 @@ public void TestLazyAsyncPartialData()
125125
var context = PrepareContext(headers);
126126

127127
response.SetContext(context);
128-
response.ProcessResponse();
128+
await response.ProcessResponse();
129129

130130
var page = response.GetJson().Value as Page;
131131

InertiaCoreTests/UnitTestModelState.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public partial class Tests
66
{
77
[Test]
88
[Description("Test if the model state dictionary is passed to the props correctly.")]
9-
public void TestModelState()
9+
public async Task TestModelState()
1010
{
1111
var response = _factory.Render("Test/Page", new
1212
{
@@ -19,7 +19,7 @@ public void TestModelState()
1919
});
2020

2121
response.SetContext(context);
22-
response.ProcessResponse();
22+
await response.ProcessResponse();
2323

2424
var page = response.GetJson().Value as Page;
2525

0 commit comments

Comments
 (0)