Skip to content

Commit

Permalink
optimize filter ui (#736)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxence-charriere committed Jun 20, 2022
1 parent 9db2a4e commit 68901be
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 21 deletions.
4 changes: 2 additions & 2 deletions pkg/app/html-mount.new.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
goos: darwin
goarch: arm64
pkg: github.com/maxence-charriere/go-app/v9/pkg/app
BenchmarkMountHTMLElement-10 52202 23502 ns/op 140310 B/op 72 allocs/op
BenchmarkMountHTMLElement-10 52926 22826 ns/op 140279 B/op 71 allocs/op
PASS
ok github.com/maxence-charriere/go-app/v9/pkg/app 2.818s
ok github.com/maxence-charriere/go-app/v9/pkg/app 2.692s
41 changes: 23 additions & 18 deletions pkg/app/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"net/url"
"reflect"
"strings"

"github.com/maxence-charriere/go-app/v9/pkg/errors"
)

// UI is the interface that describes a user interface element such as
Expand Down Expand Up @@ -97,37 +95,44 @@ const (
//
// It should be used only when implementing components that can accept content
// with variadic arguments like HTML elements Body method.
func FilterUIElems(uis ...UI) []UI {
if len(uis) == 0 {
func FilterUIElems(v ...UI) []UI {
if len(v) == 0 {
return nil
}

elems := make([]UI, 0, len(uis))
remove := func(i int) {
copy(v[i:], v[i+1:])
v[len(v)-1] = nil
v = v[:len(v)-1]
}

var b []UI
replaceAt := func(i int, s ...UI) {
b = append(b, v[i+1:]...)
v = append(v[:i], s...)
v = append(v, b...)
b = b[:0]
}

for _, n := range uis {
// Ignore nil elements:
if v := reflect.ValueOf(n); n == nil ||
v.Kind() == reflect.Ptr && v.IsNil() {
for i := len(v) - 1; i >= 0; i-- {
e := v[i]
if ev := reflect.ValueOf(e); e == nil || ev.Kind() == reflect.Pointer && ev.IsNil() {
remove(i)
continue
}

switch n.Kind() {
switch e.Kind() {
case SimpleText, HTML, Component, RawHTML:
elems = append(elems, n)

case Selector:
elems = append(elems, n.getChildren()...)
replaceAt(i, e.getChildren()...)

default:
panic(errors.New("filtering ui elements failed").
Tag("reason", "unexpected element type found").
Tag("kind", n.Kind()).
Tag("name", n.name()),
)
remove(i)
}
}

return elems
return v
}

func mount(d Dispatcher, n UI) error {
Expand Down
23 changes: 22 additions & 1 deletion pkg/app/node_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -42,17 +43,37 @@ func TestKindString(t *testing.T) {

func TestFilterUIElems(t *testing.T) {
var nilText *text
var foo *foo

simpleText := Text("hello")

expectedResult := []UI{
simpleText,
}

res := FilterUIElems(nil, nilText, simpleText)
res := FilterUIElems(nil, nilText, simpleText, foo)
require.Equal(t, expectedResult, res)
}

func BenchmarkFilterUIElems(b *testing.B) {
for n := 0; n < b.N; n++ {
FilterUIElems(Div().
Class("shell").
Body(
H1().Class("title").
Text("Hello"),
Input().
Type("text").
Class("in").
Value("World").
Placeholder("Type a name.").
OnChange(func(ctx Context, e Event) {
fmt.Println("Yo!")
}),
))
}
}

type mountTest struct {
scenario string
node UI
Expand Down

0 comments on commit 68901be

Please sign in to comment.