Skip to content

Commit

Permalink
Limit the maximum number of frames for an app (#366)
Browse files Browse the repository at this point in the history
Apps can return an arbitrarily huge number of frames in their render
tree. When painting, we keep all frames in memory to assemble an
animated WebP or GIF, so this can get out of control.

Instead, set a default maximum of 2000 frames per app. Any frames past
the 2000th frame will be discarded.
  • Loading branch information
rohansingh authored Aug 11, 2022
1 parent c8a8135 commit 6af9ca7
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions render/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const (

// DefaultFrameHeight is the normal height for a frame.
DefaultFrameHeight = 32

// DefaultMaxFrameCount is the default maximum number of frames to render.
DefaultMaxFrameCount = 2000
)

// Every Widget tree has a Root.
Expand All @@ -41,6 +44,7 @@ type Root struct {
MaxAge int32 `starlark:"max_age"`

maxParallelFrames int
maxFrameCount int
}

type RootPaintOption func(*Root)
Expand All @@ -57,14 +61,30 @@ func WithMaxParallelFrames(max int) RootPaintOption {
}
}

// WithMaxFrameCount sets the maximum number of frames that will be
// rendered when calling `Paint`.
func WithMaxFrameCount(max int) RootPaintOption {
return func(r *Root) {
r.maxFrameCount = max
}
}

// Paint renders the child widget onto the frame. It doesn't do
// any resizing or alignment.
func (r Root) Paint(solidBackground bool, opts ...RootPaintOption) []image.Image {
for _, opt := range opts {
opt(&r)
}

if r.maxFrameCount <= 0 {
r.maxFrameCount = DefaultMaxFrameCount
}

numFrames := r.Child.FrameCount()
if numFrames > r.maxFrameCount {
numFrames = r.maxFrameCount
}

frames := make([]image.Image, numFrames)

parallelism := r.maxParallelFrames
Expand Down

0 comments on commit 6af9ca7

Please sign in to comment.