Skip to content

Commit

Permalink
Add ResetContext API to support a use case when shared context stat…
Browse files Browse the repository at this point in the history
…e could lead to race condition
  • Loading branch information
kanstantsin-chernik committed Nov 5, 2024
1 parent 079e286 commit 4631a04
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
9 changes: 7 additions & 2 deletions runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,17 +550,22 @@ func (v *contextValue) hasClassBeenRendered(s string) (ok bool) {

// InitializeContext initializes context used to store internal state used during rendering.
func InitializeContext(ctx context.Context) context.Context {
if _, ok := ctx.Value(contextKey).(*contextValue); ok {
if v, ok := ctx.Value(contextKey).(*contextValue); ok && v != nil {
return ctx
}
v := &contextValue{}
ctx = context.WithValue(ctx, contextKey, v)
return ctx
}

// ResetContext resets context to prevent further usage of context state.
func ResetContext(ctx context.Context) context.Context {
return context.WithValue(ctx, contextKey, nil)
}

func getContext(ctx context.Context) (context.Context, *contextValue) {
v, ok := ctx.Value(contextKey).(*contextValue)
if !ok {
if !ok || v == nil {
ctx = InitializeContext(ctx)
v = ctx.Value(contextKey).(*contextValue)
}
Expand Down
25 changes: 25 additions & 0 deletions runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,3 +569,28 @@ func TestNonce(t *testing.T) {
}
})
}

func TestContextManipulations(t *testing.T) {
t.Run("reinitializing an already initialized context returns the same instance", func(t *testing.T) {
ctx := templ.InitializeContext(context.Background())
if ctx != templ.InitializeContext(ctx) {
t.Error("expected reinitialization of an already initialized context to return the same instance")
}
})

t.Run("reset context allows reinitialization to create a new instance", func(t *testing.T) {
ctx := templ.InitializeContext(context.Background())
resetCtx := templ.ResetContext(ctx)
if ctx == templ.InitializeContext(resetCtx) {
t.Error("expected reinitialization of a reset context to return a new instance")
}
})

t.Run("reset context clears existing state", func(t *testing.T) {
ctx := templ.WithNonce(context.Background(), "abc123")
ctx = templ.ResetContext(ctx)
if templ.GetNonce(ctx) != "" {
t.Error("expected reset context to have an empty state, but found a non-empty nonce")
}
})
}

0 comments on commit 4631a04

Please sign in to comment.