summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lazy/init.go7
-rw-r--r--lazy/init_test.go6
-rw-r--r--resources/transform.go4
-rw-r--r--tpl/partials/integration_test.go28
-rw-r--r--tpl/partials/partials.go9
5 files changed, 40 insertions, 14 deletions
diff --git a/lazy/init.go b/lazy/init.go
index 4de2a83f7..bfb9c4e07 100644
--- a/lazy/init.go
+++ b/lazy/init.go
@@ -180,14 +180,15 @@ func (ini *Init) checkDone() {
}
func (ini *Init) withTimeout(ctx context.Context, timeout time.Duration, f func(ctx context.Context) (any, error)) (any, error) {
- ctx, cancel := context.WithTimeout(ctx, timeout)
+ // Create a new context with a timeout not connected to the incoming context.
+ waitCtx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
c := make(chan verr, 1)
go func() {
v, err := f(ctx)
select {
- case <-ctx.Done():
+ case <-waitCtx.Done():
return
default:
c <- verr{v: v, err: err}
@@ -195,7 +196,7 @@ func (ini *Init) withTimeout(ctx context.Context, timeout time.Duration, f func(
}()
select {
- case <-ctx.Done():
+ case <-waitCtx.Done():
return nil, errors.New("timed out initializing value. You may have a circular loop in a shortcode, or your site may have resources that take longer to build than the `timeout` limit in your Hugo config file.")
case ve := <-c:
return ve.v, ve.err
diff --git a/lazy/init_test.go b/lazy/init_test.go
index 499ea2cce..efc329d79 100644
--- a/lazy/init_test.go
+++ b/lazy/init_test.go
@@ -126,12 +126,6 @@ func TestInitAddWithTimeoutTimeout(t *testing.T) {
init := New().AddWithTimeout(100*time.Millisecond, func(ctx context.Context) (any, error) {
time.Sleep(500 * time.Millisecond)
- select {
- case <-ctx.Done():
- return nil, nil
- default:
- }
- t.Fatal("slept")
return nil, nil
})
diff --git a/resources/transform.go b/resources/transform.go
index 4ab51485e..fe438e366 100644
--- a/resources/transform.go
+++ b/resources/transform.go
@@ -164,12 +164,12 @@ type resourceAdapter struct {
*resourceAdapterInner
}
-func (r *resourceAdapter) Content(context.Context) (any, error) {
+func (r *resourceAdapter) Content(ctx context.Context) (any, error) {
r.init(false, true)
if r.transformationsErr != nil {
return nil, r.transformationsErr
}
- return r.target.Content(context.Background())
+ return r.target.Content(ctx)
}
func (r *resourceAdapter) Err() resource.ResourceError {
diff --git a/tpl/partials/integration_test.go b/tpl/partials/integration_test.go
index fcebe6c05..3dbaf2ce4 100644
--- a/tpl/partials/integration_test.go
+++ b/tpl/partials/integration_test.go
@@ -324,3 +324,31 @@ timeout = '200ms'
b.Assert(err.Error(), qt.Contains, "timed out")
}
+
+// See Issue #10789
+func TestReturnExecuteFromTemplateInPartial(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- config.toml --
+baseURL = 'http://example.com/'
+-- layouts/index.html --
+{{ $r := partial "foo" }}
+FOO:{{ $r.Content }}
+-- layouts/partials/foo.html --
+{{ $r := §§{{ partial "bar" }}§§ | resources.FromString "bar.html" | resources.ExecuteAsTemplate "bar.html" . }}
+{{ return $r }}
+-- layouts/partials/bar.html --
+BAR
+ `
+
+ b := hugolib.NewIntegrationTestBuilder(
+ hugolib.IntegrationTestConfig{
+ T: t,
+ TxtarString: files,
+ },
+ ).Build()
+
+ b.AssertFileContent("public/index.html", "OO:BAR")
+
+}
diff --git a/tpl/partials/partials.go b/tpl/partials/partials.go
index d9a826aa4..26ce0f5c6 100644
--- a/tpl/partials/partials.go
+++ b/tpl/partials/partials.go
@@ -129,7 +129,10 @@ func (ns *Namespace) Include(ctx context.Context, name string, contextList ...an
}
func (ns *Namespace) includWithTimeout(ctx context.Context, name string, dataList ...any) includeResult {
- ctx, cancel := context.WithTimeout(ctx, ns.deps.Timeout)
+ // There are situation where the ctx we pass on to the partial lives longer than
+ // the partial itself. For example, when the partial returns the result from reosurces.ExecuteAsTemplate.
+ // Because of that, create a completely new context here.
+ timeoutCtx, cancel := context.WithTimeout(context.Background(), ns.deps.Timeout)
defer cancel()
res := make(chan includeResult, 1)
@@ -141,8 +144,8 @@ func (ns *Namespace) includWithTimeout(ctx context.Context, name string, dataLis
select {
case r := <-res:
return r
- case <-ctx.Done():
- err := ctx.Err()
+ case <-timeoutCtx.Done():
+ err := timeoutCtx.Err()
if err == context.DeadlineExceeded {
err = fmt.Errorf("partial %q timed out after %s. This is most likely due to infinite recursion. If this is just a slow template, you can try to increase the 'timeout' config setting.", name, ns.deps.Timeout)
}