diff --git a/core/handlers/v2/simulation_handler_test.go b/core/handlers/v2/simulation_handler_test.go index c5bc20d64..454ee35d6 100644 --- a/core/handlers/v2/simulation_handler_test.go +++ b/core/handlers/v2/simulation_handler_test.go @@ -385,7 +385,7 @@ func TestSimulationHandler_Put_ReturnsErrorIfJsonDoesntMatchSchema_MissingDataKe Expect(err).To(BeNil()) Expect(response.Result().StatusCode).To(Equal(400)) - Expect(errorView.Error).To(Equal("Invalid v3 simulation: [Error for : data is required]")) + Expect(errorView.Error).To(Equal("Invalid v3 simulation: [Error for <(root)>: data is required]")) } func TestSimulationHandler_Put_ReturnsErrorIfJsonDoesntMatchSchema_EmptyObject(t *testing.T) { diff --git a/core/handlers/v2/simulation_views_test.go b/core/handlers/v2/simulation_views_test.go index dd7f90eae..e7ed0e4ee 100644 --- a/core/handlers/v2/simulation_views_test.go +++ b/core/handlers/v2/simulation_views_test.go @@ -251,7 +251,7 @@ func Test_NewSimulationViewFromRequestBody_WontCreateSimulationFromInvalidV1Simu }`)) Expect(err).ToNot(BeNil()) - Expect(err.Error()).To(Equal("Invalid v1 simulation: [Error for : request is required; Error for : response is required]")) + Expect(err.Error()).To(Equal("Invalid v1 simulation: [Error for : request is required; Error for : response is required]")) Expect(simulation).ToNot(BeNil()) Expect(simulation.RequestResponsePairs).To(HaveLen(0)) diff --git a/go.mod b/go.mod index 6300fc1f8..596362607 100644 --- a/go.mod +++ b/go.mod @@ -5,73 +5,74 @@ go 1.22.10 require ( github.com/ChrisTrenkamp/xsel v0.9.16 github.com/SpectoLabs/goproxy v0.0.0-20240717215706-55e01f38b2c9 - github.com/SpectoLabs/goproxy/ext v0.0.0-20220724222243-c982a2c966ae + github.com/SpectoLabs/goproxy/ext v0.0.0-20240717215706-55e01f38b2c9 github.com/SpectoLabs/goxml2json v0.0.0-20240121223617-8e03292c14ea github.com/SpectoLabs/raymond v2.0.3-0.20240827093205-07f3a7bebd7d+incompatible github.com/antonholmquist/jason v1.0.1-0.20160829104012-962e09b85496 - github.com/beevik/etree v1.1.0 - github.com/boltdb/bolt v1.2.1-0.20160424201119-d97499360d1e - github.com/brianvoe/gofakeit/v6 v6.19.0 - github.com/codegangsta/negroni v0.1.1-0.20160503152438-24bf3506bb5e - github.com/dghubble/sling v1.2.0 - github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 + github.com/beevik/etree v1.4.1 + github.com/boltdb/bolt v1.3.1 + github.com/brianvoe/gofakeit/v6 v6.28.0 + github.com/codegangsta/negroni v1.0.0 + github.com/dghubble/sling v1.4.2 + github.com/dsnet/compress v0.0.1 github.com/go-zoo/bone v1.3.0 github.com/golang-jwt/jwt/v4 v4.5.1 - github.com/gorilla/mux v0.0.0-20160502175624-9c19ed558d5d - github.com/gorilla/websocket v1.4.2 - github.com/hashicorp/golang-lru v0.5.1 - github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 + github.com/gorilla/mux v1.8.1 + github.com/gorilla/websocket v1.5.3 + github.com/hashicorp/golang-lru v1.0.2 + github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0 github.com/jackwakefield/gopac v1.0.3-0.20180823145755-c4d2e0b9a672 - github.com/kardianos/osext v0.0.0-20151222153229-29ae4ffbc9a6 - github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 - github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a - github.com/onsi/ginkgo v1.16.4 - github.com/onsi/gomega v1.36.0 - github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 - github.com/phayes/freeport v0.0.0-20141201041908-e7681b376149 - github.com/rakyll/statik v0.1.1-0.20160322004535-2940084503a4 - github.com/rcrowley/go-metrics v0.0.0-20160226052904-eeba7bd0dd01 - github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 + github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 + github.com/mitchellh/go-homedir v1.1.0 + github.com/olekukonko/tablewriter v0.0.5 + github.com/onsi/ginkgo v1.16.5 + github.com/onsi/gomega v1.36.1 + github.com/pborman/uuid v1.2.1 + github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 + github.com/rakyll/statik v0.1.7 + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 + github.com/ryanuber/go-glob v1.0.0 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v0.0.0-20160517171929-f36824430130 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v0.0.0-20160508180713-d8a428b8a306 - github.com/tdewolff/minify/v2 v2.12.4 - github.com/xeipuuv/gojsonschema v0.0.0-20170225172124-ff0417f4272e - golang.org/x/crypto v0.29.0 - gonum.org/v1/gonum v0.7.0 + github.com/tdewolff/minify/v2 v2.21.2 + github.com/xeipuuv/gojsonschema v1.2.0 + golang.org/x/crypto v0.30.0 + gonum.org/v1/gonum v0.15.1 gopkg.in/yaml.v2 v2.4.0 - k8s.io/client-go v0.26.1 + k8s.io/client-go v0.31.3 ) require ( - github.com/BurntSushi/toml v1.2.1 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/aymerick/raymond v2.0.2+incompatible // indirect - github.com/corpix/uarand v0.0.0-20170903190822-2b8494104d86 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/corpix/uarand v0.2.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/goccmack/goutil v1.2.3 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 // indirect - github.com/gorilla/context v0.0.0-20160422134237-a8d44e7d8e4d // indirect - github.com/hashicorp/hcl v0.0.0-20160426221300-9a905a34e628 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/magiconair/properties v1.7.0 // indirect - github.com/mattn/go-runewidth v0.0.1 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.9 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/nxadm/tail v1.4.8 // indirect + github.com/nxadm/tail v1.4.11 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d // indirect - github.com/spf13/cast v0.0.0-20160314192028-27b586b42e29 // indirect - github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 // indirect - github.com/tdewolff/parse/v2 v2.6.4 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35 // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c // indirect - golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 // indirect - golang.org/x/net v0.31.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect - golang.org/x/text v0.20.0 // indirect - gonum.org/v1/netlib v0.0.0-20200317120129-c5a04cffd98a // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/robertkrimen/otto v0.5.1 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/tdewolff/parse/v2 v2.7.19 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 9b5dab9ef..e642821a7 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,11 @@ -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ChrisTrenkamp/xsel v0.9.16 h1:/rEkJMh14TEibqfY2fhG2r/UYCMr3aa0bufsG31IBjg= github.com/ChrisTrenkamp/xsel v0.9.16/go.mod h1:fDW9sVs8fwuiDmskzqybrIJ/RsI+vIspxe8G0AVg/+w= github.com/SpectoLabs/goproxy v0.0.0-20240717215706-55e01f38b2c9 h1:KLYZMZu6prwwPmCalgoE+ah7FxANPjMH9kERMN9TMfc= github.com/SpectoLabs/goproxy v0.0.0-20240717215706-55e01f38b2c9/go.mod h1:43+j4Hye/DLXHbJHM0O5dcwOkQp7zGCgDKTq6nzGXQM= -github.com/SpectoLabs/goproxy/ext v0.0.0-20220724222243-c982a2c966ae h1:3Qfw4yZArPnqymR+G9sHRNBXHbrtj84wXaj6+EGkBjs= -github.com/SpectoLabs/goproxy/ext v0.0.0-20220724222243-c982a2c966ae/go.mod h1:rnDN1CpKP9iJXwxRtnvM7d5wdPHQY0K5NkHeXWPlQ+o= +github.com/SpectoLabs/goproxy/ext v0.0.0-20240717215706-55e01f38b2c9 h1:O+R4cM+z0ftgq4SS3shT9x7JqCFvmQSKk0K8eATiDyE= +github.com/SpectoLabs/goproxy/ext v0.0.0-20240717215706-55e01f38b2c9/go.mod h1:itUI83WK8YFpzCbT9MsnCOWcvLUB2SaqXCrU8vwze5E= github.com/SpectoLabs/goxml2json v0.0.0-20240121223617-8e03292c14ea h1:VAu3xT0OShIqnm4K3TdPpxCd3k4uyXq/H6W76ueIWf0= github.com/SpectoLabs/goxml2json v0.0.0-20240121223617-8e03292c14ea/go.mod h1:P8Yk6l9gKxTfgnJeXVEQKCH7nGgvhNdeLs0zVs2h2KM= github.com/SpectoLabs/raymond v2.0.3-0.20240827093205-07f3a7bebd7d+incompatible h1:WQc9MpeneDjPv0utx7P5RmXPLfyWpbqXb+LiHK+hZxg= @@ -16,33 +15,36 @@ github.com/antonholmquist/jason v1.0.1-0.20160829104012-962e09b85496 h1:dESITduf github.com/antonholmquist/jason v1.0.1-0.20160829104012-962e09b85496/go.mod h1:+GxMEKI0Va2U8h3os6oiUAetHAlGMvxjdpAH/9uvUMA= github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= -github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= +github.com/beevik/etree v1.4.1 h1:PmQJDDYahBGNKDcpdX8uPy1xRCwoCGVUiW669MEirVI= +github.com/beevik/etree v1.4.1/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs= github.com/bitly/go-simplejson v0.5.1 h1:xgwPbetQScXt1gh9BmoJ6j9JMr3TElvuIyjR8pgdoow= github.com/bitly/go-simplejson v0.5.1/go.mod h1:YOPVLzCfwK14b4Sff3oP1AmGhI9T9Vsg84etUnlyp+Q= -github.com/boltdb/bolt v1.2.1-0.20160424201119-d97499360d1e h1:ZjpTXDvUplNMT6aktSoMffTkAGIQJGNGPQW/xL4kPwA= -github.com/boltdb/bolt v1.2.1-0.20160424201119-d97499360d1e/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/brianvoe/gofakeit/v6 v6.19.0 h1:g+yJ+meWVEsAmR+bV4mNM/eXI0N+0pZ3D+Mi+G5+YQo= -github.com/brianvoe/gofakeit/v6 v6.19.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= -github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= -github.com/codegangsta/negroni v0.1.1-0.20160503152438-24bf3506bb5e h1:2Ic1pGNC0EZvHLeWg8N2x3SDWACFj9PKRD4nqSoJzPA= -github.com/codegangsta/negroni v0.1.1-0.20160503152438-24bf3506bb5e/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= -github.com/corpix/uarand v0.0.0-20170903190822-2b8494104d86 h1:kRNlij/Yv/baHnXYdNqr+8ch5tLYAWS/VRaJ2ZvFgu0= -github.com/corpix/uarand v0.0.0-20170903190822-2b8494104d86/go.mod h1:JSm890tOkDN+M1jqN8pUGDKnzJrsVbJwSMHBY4zwz7M= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= +github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY= +github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= +github.com/corpix/uarand v0.2.0 h1:U98xXwud/AVuCpkpgfPF7J5TQgr7R5tqT8VZP5KWbzE= +github.com/corpix/uarand v0.2.0/go.mod h1:/3Z1QIqWkDIhf6XWn/08/uMHoQ8JUoTIKc2iPchBOmM= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dghubble/sling v1.2.0 h1:PYGS9ofwbV9nfhB1kYjB1vtXshMxlp2oQxTMMXVJ5pE= -github.com/dghubble/sling v1.2.0/go.mod h1:ZcPRuLm0qrcULW2gOrjXrAWgf76sahqSyxXyVOvkunE= -github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= -github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 h1:eX+pdPPlD279OWgdx7f6KqIRSONuK7egk+jDx7OM3Ac= -github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76/go.mod h1:KjxHHirfLaw19iGT70HvVjHQsL1vq1SRQB4yOsAfy2s= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dghubble/sling v1.4.2 h1:vs1HIGBbSl2SEALyU+irpYFLZMfc49Fp+jYryFebQjM= +github.com/dghubble/sling v1.4.2/go.mod h1:o0arCOz0HwfqYQJLrRtqunaWOn4X6jxE/6ORKRpVTD4= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= @@ -67,103 +69,122 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 h1:oERTZ1buOUYlpmKaqlO5fYmz8cZ1rYu5DieJzF4ZVmU= -github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/gorilla/context v0.0.0-20160422134237-a8d44e7d8e4d h1:BuwODXV4sNFjaSRNixz/sbmD1g/F3poPtHWxYTZE3C8= -github.com/gorilla/context v0.0.0-20160422134237-a8d44e7d8e4d/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v0.0.0-20160502175624-9c19ed558d5d h1:AegJdPZEQ6uNJobPN8BiOYffHTAyJyTlyhO7Hn33SHY= -github.com/gorilla/mux v0.0.0-20160502175624-9c19ed558d5d/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v0.0.0-20160426221300-9a905a34e628 h1:79lPy9LYAtihGQvcubOdkAol0FbhRAJ2BjXbiy8jDvM= -github.com/hashicorp/hcl v0.0.0-20160426221300-9a905a34e628/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0 h1:ufr2e4uIgz/Ft0RPudkFMyVrp77buvTFxqoDvwNGVSk= +github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackwakefield/gopac v1.0.3-0.20180823145755-c4d2e0b9a672 h1:8gMw+o9GKWC1Ml6pUbcdy3E1Nydvh6wasZiXmqKvYP4= github.com/jackwakefield/gopac v1.0.3-0.20180823145755-c4d2e0b9a672/go.mod h1:yR1sfJXcndScUFYPx7Xqxj7bkNlCWw9AMmuJFMHLXm8= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kardianos/osext v0.0.0-20151222153229-29ae4ffbc9a6 h1:yZAE+xNuc/2gmWV+s5UAb43LYLZQiqyngl6IUCQGJg0= -github.com/kardianos/osext v0.0.0-20151222153229-29ae4ffbc9a6/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= -github.com/magiconair/properties v1.7.0 h1:8Oygzd+nhiSWfp2XOwattyfEt36Q/F/99zQJy4axKdg= -github.com/magiconair/properties v1.7.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= -github.com/mattn/go-runewidth v0.0.1 h1:+EiaBVXhogb1Klb4tRJ7hYnuGK6PkKOZlK04D/GMOqk= -github.com/mattn/go-runewidth v0.0.1/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk= -github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a h1:m6hB6GkmZ/suOSKZM7yx3Yt+7iZ9HNfzacCykJqgXA8= -github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= -github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= -github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 h1:/CPgDYrfeK2LMK6xcUhvI17yO9SlpAdDIJGkhDEgO8A= -github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= -github.com/phayes/freeport v0.0.0-20141201041908-e7681b376149 h1:nU4ri+KRaSg4fOlRbGqaEHZ6tU84ZnrjHCqqq0em+VQ= -github.com/phayes/freeport v0.0.0-20141201041908-e7681b376149/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= +github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rakyll/statik v0.1.1-0.20160322004535-2940084503a4 h1:6UhUengh0GxTWyOCh8Qzam8cXzSgtrQD5dIMbo8qVqI= -github.com/rakyll/statik v0.1.1-0.20160322004535-2940084503a4/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= -github.com/rcrowley/go-metrics v0.0.0-20160226052904-eeba7bd0dd01 h1:XCHS0IhcFEQoiyKtFqXFRXgLKjcxOuyCDeeXPNb0T7o= -github.com/rcrowley/go-metrics v0.0.0-20160226052904-eeba7bd0dd01/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4= -github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= -github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= -github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE= -github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robertkrimen/otto v0.5.1 h1:avDI4ToRk8k1hppLdYFTuuzND41n37vPGJU7547dGf0= +github.com/robertkrimen/otto v0.5.1/go.mod h1:bS433I4Q9p+E5pZLu7r17vP6FkE6/wLxBdmKjoqJXF8= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cast v0.0.0-20160314192028-27b586b42e29 h1:Lgc6pP3ludnufG3ehP2WboB0IIKxlizm8NvXsI0/Z58= -github.com/spf13/cast v0.0.0-20160314192028-27b586b42e29/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.0-20160517171929-f36824430130 h1:FgjZIXM8t7/smwWZySOMSXVyrIACwJNdHMGvpdhXGCc= -github.com/spf13/cobra v0.0.0-20160517171929-f36824430130/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 h1:evyGXhHMrxKBDkdlSPv9HMWV2o53o+Ibhm28BGc0450= -github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v0.0.0-20160508180713-d8a428b8a306 h1:fvXBhJjS/jLG2A5yTggvllwqmgL4P6n6M9BKw1PIFmY= github.com/spf13/viper v0.0.0-20160508180713-d8a428b8a306/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/tdewolff/minify/v2 v2.12.4 h1:kejsHQMM17n6/gwdw53qsi6lg0TGddZADVyQOz1KMdE= -github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk= -github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZycQ= -github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= -github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM= -github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= -github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35 h1:0TnXeVP6mx+A4CBf8cQVkQfkhyGBQCmJcT4g6zKzm7M= -github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c h1:XZWnr3bsDQWAZg4Ne+cPoXRPILrNlPNQfxBuwLl43is= -github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20170225172124-ff0417f4272e h1:vhu5zToI4Rj62MgHj/UrrrM8RqNtKoCZUx8ARkpyzKA= -github.com/xeipuuv/gojsonschema v0.0.0-20170225172124-ff0417f4272e/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.21.2 h1:VfTvmGVtBYhMTlUAeHtXM7XOsW0JT/6uMwUPPqgUs9k= +github.com/tdewolff/minify/v2 v2.21.2/go.mod h1:Olje3eHdBnrMjINKffDsil/3NV98Iv7MhWf7556WQVg= +github.com/tdewolff/parse/v2 v2.7.19 h1:7Ljh26yj+gdLFEq/7q9LT4SYyKtwQX4ocNrj45UCePg= +github.com/tdewolff/parse/v2 v2.7.19/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -171,21 +192,18 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -195,8 +213,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -204,7 +222,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -214,51 +231,48 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw= -gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM= +gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= +gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20200317120129-c5a04cffd98a h1:y158/g9tKwBGw9gnNENlUIi9NTJCoiQg2RFB1gr9atQ= -gonum.org/v1/netlib v0.0.0-20200317120129-c5a04cffd98a/go.mod h1:6EVtvAMWMjOBOsTVX0xrjO4A6ULtEgWtAWHzqxDWdJs= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -268,8 +282,9 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= @@ -283,11 +298,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= -modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= -modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= -modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/vendor/github.com/BurntSushi/toml/README.md b/vendor/github.com/BurntSushi/toml/README.md index 3651cfa96..639e6c399 100644 --- a/vendor/github.com/BurntSushi/toml/README.md +++ b/vendor/github.com/BurntSushi/toml/README.md @@ -9,7 +9,7 @@ See the [releases page](https://github.com/BurntSushi/toml/releases) for a changelog; this information is also in the git tag annotations (e.g. `git show v0.4.0`). -This library requires Go 1.13 or newer; add it to your go.mod with: +This library requires Go 1.18 or newer; add it to your go.mod with: % go get github.com/BurntSushi/toml@latest diff --git a/vendor/github.com/BurntSushi/toml/decode.go b/vendor/github.com/BurntSushi/toml/decode.go index 0ca1dc4fe..7aaf462c9 100644 --- a/vendor/github.com/BurntSushi/toml/decode.go +++ b/vendor/github.com/BurntSushi/toml/decode.go @@ -6,7 +6,7 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" + "io/fs" "math" "os" "reflect" @@ -18,13 +18,13 @@ import ( // Unmarshaler is the interface implemented by objects that can unmarshal a // TOML description of themselves. type Unmarshaler interface { - UnmarshalTOML(interface{}) error + UnmarshalTOML(any) error } // Unmarshal decodes the contents of data in TOML format into a pointer v. // // See [Decoder] for a description of the decoding process. -func Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v any) error { _, err := NewDecoder(bytes.NewReader(data)).Decode(v) return err } @@ -32,12 +32,12 @@ func Unmarshal(data []byte, v interface{}) error { // Decode the TOML data in to the pointer v. // // See [Decoder] for a description of the decoding process. -func Decode(data string, v interface{}) (MetaData, error) { +func Decode(data string, v any) (MetaData, error) { return NewDecoder(strings.NewReader(data)).Decode(v) } // DecodeFile reads the contents of a file and decodes it with [Decode]. -func DecodeFile(path string, v interface{}) (MetaData, error) { +func DecodeFile(path string, v any) (MetaData, error) { fp, err := os.Open(path) if err != nil { return MetaData{}, err @@ -46,6 +46,17 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { return NewDecoder(fp).Decode(v) } +// DecodeFS reads the contents of a file from [fs.FS] and decodes it with +// [Decode]. +func DecodeFS(fsys fs.FS, path string, v any) (MetaData, error) { + fp, err := fsys.Open(path) + if err != nil { + return MetaData{}, err + } + defer fp.Close() + return NewDecoder(fp).Decode(v) +} + // Primitive is a TOML value that hasn't been decoded into a Go value. // // This type can be used for any value, which will cause decoding to be delayed. @@ -58,7 +69,7 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { // overhead of reflection. They can be useful when you don't know the exact type // of TOML data until runtime. type Primitive struct { - undecoded interface{} + undecoded any context Key } @@ -91,7 +102,7 @@ const ( // UnmarshalText method. See the Unmarshaler example for a demonstration with // email addresses. // -// ### Key mapping +// # Key mapping // // TOML keys can map to either keys in a Go map or field names in a Go struct. // The special `toml` struct tag can be used to map TOML keys to struct fields @@ -122,7 +133,7 @@ var ( ) // Decode TOML data in to the pointer `v`. -func (dec *Decoder) Decode(v interface{}) (MetaData, error) { +func (dec *Decoder) Decode(v any) (MetaData, error) { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr { s := "%q" @@ -136,8 +147,8 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v)) } - // Check if this is a supported type: struct, map, interface{}, or something - // that implements UnmarshalTOML or UnmarshalText. + // Check if this is a supported type: struct, map, any, or something that + // implements UnmarshalTOML or UnmarshalText. rv = indirect(rv) rt := rv.Type() if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map && @@ -148,7 +159,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { // TODO: parser should read from io.Reader? Or at the very least, make it // read from []byte rather than string - data, err := ioutil.ReadAll(dec.r) + data, err := io.ReadAll(dec.r) if err != nil { return MetaData{}, err } @@ -179,7 +190,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { // will only reflect keys that were decoded. Namely, any keys hidden behind a // Primitive will be considered undecoded. Executing this method will update the // undecoded keys in the meta data. (See the example.) -func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { +func (md *MetaData) PrimitiveDecode(primValue Primitive, v any) error { md.context = primValue.context defer func() { md.context = nil }() return md.unify(primValue.undecoded, rvalue(v)) @@ -190,7 +201,7 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { // // Any type mismatch produces an error. Finding a type that we don't know // how to handle produces an unsupported type error. -func (md *MetaData) unify(data interface{}, rv reflect.Value) error { +func (md *MetaData) unify(data any, rv reflect.Value) error { // Special case. Look for a `Primitive` value. // TODO: #76 would make this superfluous after implemented. if rv.Type() == primitiveType { @@ -207,7 +218,11 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { rvi := rv.Interface() if v, ok := rvi.(Unmarshaler); ok { - return v.UnmarshalTOML(data) + err := v.UnmarshalTOML(data) + if err != nil { + return md.parseErr(err) + } + return nil } if v, ok := rvi.(encoding.TextUnmarshaler); ok { return md.unifyText(data, v) @@ -227,14 +242,6 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return md.unifyInt(data, rv) } switch k { - case reflect.Ptr: - elem := reflect.New(rv.Type().Elem()) - err := md.unify(data, reflect.Indirect(elem)) - if err != nil { - return err - } - rv.Set(elem) - return nil case reflect.Struct: return md.unifyStruct(data, rv) case reflect.Map: @@ -248,7 +255,7 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { case reflect.Bool: return md.unifyBool(data, rv) case reflect.Interface: - if rv.NumMethod() > 0 { // Only support empty interfaces are supported. + if rv.NumMethod() > 0 { /// Only empty interfaces are supported. return md.e("unsupported type %s", rv.Type()) } return md.unifyAnything(data, rv) @@ -258,14 +265,13 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return md.e("unsupported type %s", rv.Kind()) } -func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { - tmap, ok := mapping.(map[string]interface{}) +func (md *MetaData) unifyStruct(mapping any, rv reflect.Value) error { + tmap, ok := mapping.(map[string]any) if !ok { if mapping == nil { return nil } - return md.e("type mismatch for %s: expected table but found %T", - rv.Type().String(), mapping) + return md.e("type mismatch for %s: expected table but found %s", rv.Type().String(), fmtType(mapping)) } for key, datum := range tmap { @@ -304,14 +310,14 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { +func (md *MetaData) unifyMap(mapping any, rv reflect.Value) error { keyType := rv.Type().Key().Kind() if keyType != reflect.String && keyType != reflect.Interface { return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)", keyType, rv.Type()) } - tmap, ok := mapping.(map[string]interface{}) + tmap, ok := mapping.(map[string]any) if !ok { if tmap == nil { return nil @@ -347,7 +353,7 @@ func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyArray(data any, rv reflect.Value) error { datav := reflect.ValueOf(data) if datav.Kind() != reflect.Slice { if !datav.IsValid() { @@ -361,7 +367,7 @@ func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { return md.unifySliceArray(datav, rv) } -func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifySlice(data any, rv reflect.Value) error { datav := reflect.ValueOf(data) if datav.Kind() != reflect.Slice { if !datav.IsValid() { @@ -388,7 +394,7 @@ func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { return nil } -func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyString(data any, rv reflect.Value) error { _, ok := rv.Interface().(json.Number) if ok { if i, ok := data.(int64); ok { @@ -408,7 +414,7 @@ func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { return md.badtype("string", data) } -func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyFloat64(data any, rv reflect.Value) error { rvk := rv.Kind() if num, ok := data.(float64); ok { @@ -429,7 +435,7 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { if num, ok := data.(int64); ok { if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) || (rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) { - return md.parseErr(errParseRange{i: num, size: rvk.String()}) + return md.parseErr(errUnsafeFloat{i: num, size: rvk.String()}) } rv.SetFloat(float64(num)) return nil @@ -438,7 +444,7 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { return md.badtype("float", data) } -func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyInt(data any, rv reflect.Value) error { _, ok := rv.Interface().(time.Duration) if ok { // Parse as string duration, and fall back to regular integer parsing @@ -481,7 +487,7 @@ func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyBool(data any, rv reflect.Value) error { if b, ok := data.(bool); ok { rv.SetBool(b) return nil @@ -489,12 +495,12 @@ func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { return md.badtype("boolean", data) } -func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyAnything(data any, rv reflect.Value) error { rv.Set(reflect.ValueOf(data)) return nil } -func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error { +func (md *MetaData) unifyText(data any, v encoding.TextUnmarshaler) error { var s string switch sdata := data.(type) { case Marshaler: @@ -523,13 +529,13 @@ func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) erro return md.badtype("primitive (string-like)", data) } if err := v.UnmarshalText([]byte(s)); err != nil { - return err + return md.parseErr(err) } return nil } -func (md *MetaData) badtype(dst string, data interface{}) error { - return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst) +func (md *MetaData) badtype(dst string, data any) error { + return md.e("incompatible types: TOML value has type %s; destination has type %s", fmtType(data), dst) } func (md *MetaData) parseErr(err error) error { @@ -543,7 +549,7 @@ func (md *MetaData) parseErr(err error) error { } } -func (md *MetaData) e(format string, args ...interface{}) error { +func (md *MetaData) e(format string, args ...any) error { f := "toml: " if len(md.context) > 0 { f = fmt.Sprintf("toml: (last key %q): ", md.context) @@ -556,7 +562,7 @@ func (md *MetaData) e(format string, args ...interface{}) error { } // rvalue returns a reflect.Value of `v`. All pointers are resolved. -func rvalue(v interface{}) reflect.Value { +func rvalue(v any) reflect.Value { return indirect(reflect.ValueOf(v)) } @@ -600,3 +606,8 @@ func isUnifiable(rv reflect.Value) bool { } return false } + +// fmt %T with "interface {}" replaced with "any", which is far more readable. +func fmtType(t any) string { + return strings.ReplaceAll(fmt.Sprintf("%T", t), "interface {}", "any") +} diff --git a/vendor/github.com/BurntSushi/toml/decode_go116.go b/vendor/github.com/BurntSushi/toml/decode_go116.go deleted file mode 100644 index 086d0b686..000000000 --- a/vendor/github.com/BurntSushi/toml/decode_go116.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build go1.16 -// +build go1.16 - -package toml - -import ( - "io/fs" -) - -// DecodeFS reads the contents of a file from [fs.FS] and decodes it with -// [Decode]. -func DecodeFS(fsys fs.FS, path string, v interface{}) (MetaData, error) { - fp, err := fsys.Open(path) - if err != nil { - return MetaData{}, err - } - defer fp.Close() - return NewDecoder(fp).Decode(v) -} diff --git a/vendor/github.com/BurntSushi/toml/deprecated.go b/vendor/github.com/BurntSushi/toml/deprecated.go index c6af3f239..155709a80 100644 --- a/vendor/github.com/BurntSushi/toml/deprecated.go +++ b/vendor/github.com/BurntSushi/toml/deprecated.go @@ -5,17 +5,25 @@ import ( "io" ) +// TextMarshaler is an alias for encoding.TextMarshaler. +// // Deprecated: use encoding.TextMarshaler type TextMarshaler encoding.TextMarshaler +// TextUnmarshaler is an alias for encoding.TextUnmarshaler. +// // Deprecated: use encoding.TextUnmarshaler type TextUnmarshaler encoding.TextUnmarshaler +// DecodeReader is an alias for NewDecoder(r).Decode(v). +// +// Deprecated: use NewDecoder(reader).Decode(&value). +func DecodeReader(r io.Reader, v any) (MetaData, error) { return NewDecoder(r).Decode(v) } + +// PrimitiveDecode is an alias for MetaData.PrimitiveDecode(). +// // Deprecated: use MetaData.PrimitiveDecode. -func PrimitiveDecode(primValue Primitive, v interface{}) error { +func PrimitiveDecode(primValue Primitive, v any) error { md := MetaData{decoded: make(map[string]struct{})} return md.unify(primValue.undecoded, rvalue(v)) } - -// Deprecated: use NewDecoder(reader).Decode(&value). -func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) } diff --git a/vendor/github.com/BurntSushi/toml/doc.go b/vendor/github.com/BurntSushi/toml/doc.go index 81a7c0fe9..82c90a905 100644 --- a/vendor/github.com/BurntSushi/toml/doc.go +++ b/vendor/github.com/BurntSushi/toml/doc.go @@ -2,9 +2,6 @@ // // This package supports TOML v1.0.0, as specified at https://toml.io // -// There is also support for delaying decoding with the Primitive type, and -// querying the set of keys in a TOML document with the MetaData type. -// // The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator, // and can be used to verify if TOML document is valid. It can also be used to // print the type of each key. diff --git a/vendor/github.com/BurntSushi/toml/encode.go b/vendor/github.com/BurntSushi/toml/encode.go index 930e1d521..73366c0d9 100644 --- a/vendor/github.com/BurntSushi/toml/encode.go +++ b/vendor/github.com/BurntSushi/toml/encode.go @@ -2,6 +2,7 @@ package toml import ( "bufio" + "bytes" "encoding" "encoding/json" "errors" @@ -76,6 +77,17 @@ type Marshaler interface { MarshalTOML() ([]byte, error) } +// Marshal returns a TOML representation of the Go value. +// +// See [Encoder] for a description of the encoding process. +func Marshal(v any) ([]byte, error) { + buff := new(bytes.Buffer) + if err := NewEncoder(buff).Encode(v); err != nil { + return nil, err + } + return buff.Bytes(), nil +} + // Encoder encodes a Go to a TOML document. // // The mapping between Go values and TOML values should be precisely the same as @@ -115,28 +127,24 @@ type Marshaler interface { // NOTE: only exported keys are encoded due to the use of reflection. Unexported // keys are silently discarded. type Encoder struct { - // String to use for a single indentation level; default is two spaces. - Indent string - + Indent string // string for a single indentation level; default is two spaces. + hasWritten bool // written any output to w yet? w *bufio.Writer - hasWritten bool // written any output to w yet? } // NewEncoder create a new Encoder. func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - w: bufio.NewWriter(w), - Indent: " ", - } + return &Encoder{w: bufio.NewWriter(w), Indent: " "} } // Encode writes a TOML representation of the Go value to the [Encoder]'s writer. // // An error is returned if the value given cannot be encoded to a valid TOML // document. -func (enc *Encoder) Encode(v interface{}) error { +func (enc *Encoder) Encode(v any) error { rv := eindirect(reflect.ValueOf(v)) - if err := enc.safeEncode(Key([]string{}), rv); err != nil { + err := enc.safeEncode(Key([]string{}), rv) + if err != nil { return err } return enc.w.Flush() @@ -279,18 +287,30 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Float32: f := rv.Float() if math.IsNaN(f) { + if math.Signbit(f) { + enc.wf("-") + } enc.wf("nan") } else if math.IsInf(f, 0) { - enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)]) + if math.Signbit(f) { + enc.wf("-") + } + enc.wf("inf") } else { enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 32))) } case reflect.Float64: f := rv.Float() if math.IsNaN(f) { + if math.Signbit(f) { + enc.wf("-") + } enc.wf("nan") } else if math.IsInf(f, 0) { - enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)]) + if math.Signbit(f) { + enc.wf("-") + } + enc.wf("inf") } else { enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 64))) } @@ -303,7 +323,7 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Interface: enc.eElement(rv.Elem()) default: - encPanic(fmt.Errorf("unexpected type: %T", rv.Interface())) + encPanic(fmt.Errorf("unexpected type: %s", fmtType(rv.Interface()))) } } @@ -457,6 +477,16 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { frv := eindirect(rv.Field(i)) + if is32Bit { + // Copy so it works correct on 32bit archs; not clear why this + // is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4 + // This also works fine on 64bit, but 32bit archs are somewhat + // rare and this is a wee bit faster. + copyStart := make([]int, len(start)) + copy(copyStart, start) + start = copyStart + } + // Treat anonymous struct fields with tag names as though they are // not anonymous, like encoding/json does. // @@ -471,17 +501,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { if typeIsTable(tomlTypeOfGo(frv)) { fieldsSub = append(fieldsSub, append(start, f.Index...)) } else { - // Copy so it works correct on 32bit archs; not clear why this - // is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4 - // This also works fine on 64bit, but 32bit archs are somewhat - // rare and this is a wee bit faster. - if is32Bit { - copyStart := make([]int, len(start)) - copy(copyStart, start) - fieldsDirect = append(fieldsDirect, append(copyStart, f.Index...)) - } else { - fieldsDirect = append(fieldsDirect, append(start, f.Index...)) - } + fieldsDirect = append(fieldsDirect, append(start, f.Index...)) } } } @@ -490,24 +510,27 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { writeFields := func(fields [][]int) { for _, fieldIndex := range fields { fieldType := rt.FieldByIndex(fieldIndex) - fieldVal := eindirect(rv.FieldByIndex(fieldIndex)) + fieldVal := rv.FieldByIndex(fieldIndex) - if isNil(fieldVal) { /// Don't write anything for nil fields. + opts := getOptions(fieldType.Tag) + if opts.skip { + continue + } + if opts.omitempty && isEmpty(fieldVal) { continue } - opts := getOptions(fieldType.Tag) - if opts.skip { + fieldVal = eindirect(fieldVal) + + if isNil(fieldVal) { /// Don't write anything for nil fields. continue } + keyName := fieldType.Name if opts.name != "" { keyName = opts.name } - if opts.omitempty && enc.isEmpty(fieldVal) { - continue - } if opts.omitzero && isZero(fieldVal) { continue } @@ -649,7 +672,7 @@ func isZero(rv reflect.Value) bool { return false } -func (enc *Encoder) isEmpty(rv reflect.Value) bool { +func isEmpty(rv reflect.Value) bool { switch rv.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.String: return rv.Len() == 0 @@ -664,13 +687,15 @@ func (enc *Encoder) isEmpty(rv reflect.Value) bool { // type b struct{ s []string } // s := a{field: b{s: []string{"AAA"}}} for i := 0; i < rv.NumField(); i++ { - if !enc.isEmpty(rv.Field(i)) { + if !isEmpty(rv.Field(i)) { return false } } return true case reflect.Bool: return !rv.Bool() + case reflect.Ptr: + return rv.IsNil() } return false } @@ -693,8 +718,11 @@ func (enc *Encoder) newline() { // v v v v vv // key = {k = 1, k2 = 2} func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) { + /// Marshaler used on top-level document; call eElement() to just call + /// Marshal{TOML,Text}. if len(key) == 0 { - encPanic(errNoKey) + enc.eElement(val) + return } enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1)) enc.eElement(val) @@ -703,7 +731,7 @@ func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) { } } -func (enc *Encoder) wf(format string, v ...interface{}) { +func (enc *Encoder) wf(format string, v ...any) { _, err := fmt.Fprintf(enc.w, format, v...) if err != nil { encPanic(err) diff --git a/vendor/github.com/BurntSushi/toml/error.go b/vendor/github.com/BurntSushi/toml/error.go index f4f390e64..b45a3f45f 100644 --- a/vendor/github.com/BurntSushi/toml/error.go +++ b/vendor/github.com/BurntSushi/toml/error.go @@ -84,7 +84,7 @@ func (pe ParseError) Error() string { pe.Position.Line, pe.LastKey, msg) } -// ErrorWithUsage() returns the error with detailed location context. +// ErrorWithPosition returns the error with detailed location context. // // See the documentation on [ParseError]. func (pe ParseError) ErrorWithPosition() string { @@ -114,17 +114,26 @@ func (pe ParseError) ErrorWithPosition() string { msg, pe.Position.Line, col, col+pe.Position.Len) } if pe.Position.Line > 2 { - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, lines[pe.Position.Line-3]) + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3])) } if pe.Position.Line > 1 { - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, lines[pe.Position.Line-2]) + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, expandTab(lines[pe.Position.Line-2])) } - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, lines[pe.Position.Line-1]) - fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col), strings.Repeat("^", pe.Position.Len)) + + /// Expand tabs, so that the ^^^s are at the correct position, but leave + /// "column 10-13" intact. Adjusting this to the visual column would be + /// better, but we don't know the tabsize of the user in their editor, which + /// can be 8, 4, 2, or something else. We can't know. So leaving it as the + /// character index is probably the "most correct". + expanded := expandTab(lines[pe.Position.Line-1]) + diff := len(expanded) - len(lines[pe.Position.Line-1]) + + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded) + fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col+diff), strings.Repeat("^", pe.Position.Len)) return b.String() } -// ErrorWithUsage() returns the error with detailed location context and usage +// ErrorWithUsage returns the error with detailed location context and usage // guidance. // // See the documentation on [ParseError]. @@ -159,17 +168,47 @@ func (pe ParseError) column(lines []string) int { return col } +func expandTab(s string) string { + var ( + b strings.Builder + l int + fill = func(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = ' ' + } + return string(b) + } + ) + b.Grow(len(s)) + for _, r := range s { + switch r { + case '\t': + tw := 8 - l%8 + b.WriteString(fill(tw)) + l += tw + default: + b.WriteRune(r) + l += 1 + } + } + return b.String() +} + type ( errLexControl struct{ r rune } errLexEscape struct{ r rune } errLexUTF8 struct{ b byte } - errLexInvalidNum struct{ v string } - errLexInvalidDate struct{ v string } + errParseDate struct{ v string } errLexInlineTableNL struct{} errLexStringNL struct{} errParseRange struct { - i interface{} // int or float - size string // "int64", "uint16", etc. + i any // int or float + size string // "int64", "uint16", etc. + } + errUnsafeFloat struct { + i interface{} // float32 or float64 + size string // "float32" or "float64" } errParseDuration struct{ d string } ) @@ -183,18 +222,20 @@ func (e errLexEscape) Error() string { return fmt.Sprintf(`invalid escape func (e errLexEscape) Usage() string { return usageEscape } func (e errLexUTF8) Error() string { return fmt.Sprintf("invalid UTF-8 byte: 0x%02x", e.b) } func (e errLexUTF8) Usage() string { return "" } -func (e errLexInvalidNum) Error() string { return fmt.Sprintf("invalid number: %q", e.v) } -func (e errLexInvalidNum) Usage() string { return "" } -func (e errLexInvalidDate) Error() string { return fmt.Sprintf("invalid date: %q", e.v) } -func (e errLexInvalidDate) Usage() string { return "" } +func (e errParseDate) Error() string { return fmt.Sprintf("invalid datetime: %q", e.v) } +func (e errParseDate) Usage() string { return usageDate } func (e errLexInlineTableNL) Error() string { return "newlines not allowed within inline tables" } func (e errLexInlineTableNL) Usage() string { return usageInlineNewline } func (e errLexStringNL) Error() string { return "strings cannot contain newlines" } func (e errLexStringNL) Usage() string { return usageStringNewline } func (e errParseRange) Error() string { return fmt.Sprintf("%v is out of range for %s", e.i, e.size) } func (e errParseRange) Usage() string { return usageIntOverflow } -func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } -func (e errParseDuration) Usage() string { return usageDuration } +func (e errUnsafeFloat) Error() string { + return fmt.Sprintf("%v is out of the safe %s range", e.i, e.size) +} +func (e errUnsafeFloat) Usage() string { return usageUnsafeFloat } +func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } +func (e errParseDuration) Usage() string { return usageDuration } const usageEscape = ` A '\' inside a "-delimited string is interpreted as an escape character. @@ -251,19 +292,35 @@ bug in the program that uses too small of an integer. The maximum and minimum values are: size │ lowest │ highest - ───────┼────────────────┼────────── + ───────┼────────────────┼────────────── int8 │ -128 │ 127 int16 │ -32,768 │ 32,767 int32 │ -2,147,483,648 │ 2,147,483,647 int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷ uint8 │ 0 │ 255 - uint16 │ 0 │ 65535 - uint32 │ 0 │ 4294967295 + uint16 │ 0 │ 65,535 + uint32 │ 0 │ 4,294,967,295 uint64 │ 0 │ 1.8 × 10¹⁸ int refers to int32 on 32-bit systems and int64 on 64-bit systems. ` +const usageUnsafeFloat = ` +This number is outside of the "safe" range for floating point numbers; whole +(non-fractional) numbers outside the below range can not always be represented +accurately in a float, leading to some loss of accuracy. + +Explicitly mark a number as a fractional unit by adding ".0", which will incur +some loss of accuracy; for example: + + f = 2_000_000_000.0 + +Accuracy ranges: + + float32 = 16,777,215 + float64 = 9,007,199,254,740,991 +` + const usageDuration = ` A duration must be as "number", without any spaces. Valid units are: @@ -277,3 +334,23 @@ A duration must be as "number", without any spaces. Valid units are: You can combine multiple units; for example "5m10s" for 5 minutes and 10 seconds. ` + +const usageDate = ` +A TOML datetime must be in one of the following formats: + + 2006-01-02T15:04:05Z07:00 Date and time, with timezone. + 2006-01-02T15:04:05 Date and time, but without timezone. + 2006-01-02 Date without a time or timezone. + 15:04:05 Just a time, without any timezone. + +Seconds may optionally have a fraction, up to nanosecond precision: + + 15:04:05.123 + 15:04:05.856018510 +` + +// TOML 1.1: +// The seconds part in times is optional, and may be omitted: +// 2006-01-02T15:04Z07:00 +// 2006-01-02T15:04 +// 15:04 diff --git a/vendor/github.com/BurntSushi/toml/lex.go b/vendor/github.com/BurntSushi/toml/lex.go index d4d70871d..a1016d98a 100644 --- a/vendor/github.com/BurntSushi/toml/lex.go +++ b/vendor/github.com/BurntSushi/toml/lex.go @@ -17,6 +17,7 @@ const ( itemEOF itemText itemString + itemStringEsc itemRawString itemMultilineString itemRawMultilineString @@ -46,12 +47,14 @@ func (p Position) String() string { } type lexer struct { - input string - start int - pos int - line int - state stateFn - items chan item + input string + start int + pos int + line int + state stateFn + items chan item + tomlNext bool + esc bool // Allow for backing up up to 4 runes. This is necessary because TOML // contains 3-rune tokens (""" and '''). @@ -87,13 +90,14 @@ func (lx *lexer) nextItem() item { } } -func lex(input string) *lexer { +func lex(input string, tomlNext bool) *lexer { lx := &lexer{ - input: input, - state: lexTop, - items: make(chan item, 10), - stack: make([]stateFn, 0, 10), - line: 1, + input: input, + state: lexTop, + items: make(chan item, 10), + stack: make([]stateFn, 0, 10), + line: 1, + tomlNext: tomlNext, } return lx } @@ -162,7 +166,7 @@ func (lx *lexer) next() (r rune) { } r, w := utf8.DecodeRuneInString(lx.input[lx.pos:]) - if r == utf8.RuneError { + if r == utf8.RuneError && w == 1 { lx.error(errLexUTF8{lx.input[lx.pos]}) return utf8.RuneError } @@ -268,7 +272,7 @@ func (lx *lexer) errorPos(start, length int, err error) stateFn { } // errorf is like error, and creates a new error. -func (lx *lexer) errorf(format string, values ...interface{}) stateFn { +func (lx *lexer) errorf(format string, values ...any) stateFn { if lx.atEOF { pos := lx.getPos() pos.Line-- @@ -331,9 +335,7 @@ func lexTopEnd(lx *lexer) stateFn { lx.emit(itemEOF) return nil } - return lx.errorf( - "expected a top-level item to end with a newline, comment, or EOF, but got %q instead", - r) + return lx.errorf("expected a top-level item to end with a newline, comment, or EOF, but got %q instead", r) } // lexTable lexes the beginning of a table. Namely, it makes sure that @@ -408,7 +410,7 @@ func lexTableNameEnd(lx *lexer) stateFn { // Lexes only one part, e.g. only 'a' inside 'a.b'. func lexBareName(lx *lexer) stateFn { r := lx.next() - if isBareKeyChar(r) { + if isBareKeyChar(r, lx.tomlNext) { return lexBareName } lx.backup() @@ -618,6 +620,9 @@ func lexInlineTableValue(lx *lexer) stateFn { case isWhitespace(r): return lexSkip(lx, lexInlineTableValue) case isNL(r): + if lx.tomlNext { + return lexSkip(lx, lexInlineTableValue) + } return lx.errorPrevLine(errLexInlineTableNL{}) case r == '#': lx.push(lexInlineTableValue) @@ -640,6 +645,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn { case isWhitespace(r): return lexSkip(lx, lexInlineTableValueEnd) case isNL(r): + if lx.tomlNext { + return lexSkip(lx, lexInlineTableValueEnd) + } return lx.errorPrevLine(errLexInlineTableNL{}) case r == '#': lx.push(lexInlineTableValueEnd) @@ -648,6 +656,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn { lx.ignore() lx.skip(isWhitespace) if lx.peek() == '}' { + if lx.tomlNext { + return lexInlineTableValueEnd + } return lx.errorf("trailing comma not allowed in inline tables") } return lexInlineTableValue @@ -687,7 +698,12 @@ func lexString(lx *lexer) stateFn { return lexStringEscape case r == '"': lx.backup() - lx.emit(itemString) + if lx.esc { + lx.esc = false + lx.emit(itemStringEsc) + } else { + lx.emit(itemString) + } lx.next() lx.ignore() return lx.pop() @@ -737,6 +753,7 @@ func lexMultilineString(lx *lexer) stateFn { lx.backup() /// backup: don't include the """ in the item. lx.backup() lx.backup() + lx.esc = false lx.emit(itemMultilineString) lx.next() /// Read over ''' again and discard it. lx.next() @@ -770,8 +787,8 @@ func lexRawString(lx *lexer) stateFn { } } -// lexMultilineRawString consumes a raw string. Nothing can be escaped in such -// a string. It assumes that the beginning ''' has already been consumed and +// lexMultilineRawString consumes a raw string. Nothing can be escaped in such a +// string. It assumes that the beginning triple-' has already been consumed and // ignored. func lexMultilineRawString(lx *lexer) stateFn { r := lx.next() @@ -826,8 +843,14 @@ func lexMultilineStringEscape(lx *lexer) stateFn { } func lexStringEscape(lx *lexer) stateFn { + lx.esc = true r := lx.next() switch r { + case 'e': + if !lx.tomlNext { + return lx.error(errLexEscape{r}) + } + fallthrough case 'b': fallthrough case 't': @@ -846,6 +869,11 @@ func lexStringEscape(lx *lexer) stateFn { fallthrough case '\\': return lx.pop() + case 'x': + if !lx.tomlNext { + return lx.error(errLexEscape{r}) + } + return lexHexEscape case 'u': return lexShortUnicodeEscape case 'U': @@ -854,14 +882,23 @@ func lexStringEscape(lx *lexer) stateFn { return lx.error(errLexEscape{r}) } +func lexHexEscape(lx *lexer) stateFn { + var r rune + for i := 0; i < 2; i++ { + r = lx.next() + if !isHex(r) { + return lx.errorf(`expected two hexadecimal digits after '\x', but got %q instead`, lx.current()) + } + } + return lx.pop() +} + func lexShortUnicodeEscape(lx *lexer) stateFn { var r rune for i := 0; i < 4; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected four hexadecimal digits after '\u', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected four hexadecimal digits after '\u', but got %q instead`, lx.current()) } } return lx.pop() @@ -871,10 +908,8 @@ func lexLongUnicodeEscape(lx *lexer) stateFn { var r rune for i := 0; i < 8; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected eight hexadecimal digits after '\U', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected eight hexadecimal digits after '\U', but got %q instead`, lx.current()) } } return lx.pop() @@ -941,7 +976,7 @@ func lexDatetime(lx *lexer) stateFn { // lexHexInteger consumes a hexadecimal integer after seeing the '0x' prefix. func lexHexInteger(lx *lexer) stateFn { r := lx.next() - if isHexadecimal(r) { + if isHex(r) { return lexHexInteger } switch r { @@ -1075,7 +1110,7 @@ func lexBaseNumberOrDate(lx *lexer) stateFn { return lexOctalInteger case 'x': r = lx.peek() - if !isHexadecimal(r) { + if !isHex(r) { lx.errorf("not a hexidecimal number: '%s%c'", lx.current(), r) } return lexHexInteger @@ -1173,7 +1208,7 @@ func (itype itemType) String() string { return "EOF" case itemText: return "Text" - case itemString, itemRawString, itemMultilineString, itemRawMultilineString: + case itemString, itemStringEsc, itemRawString, itemMultilineString, itemRawMultilineString: return "String" case itemBool: return "Bool" @@ -1206,7 +1241,7 @@ func (itype itemType) String() string { } func (item item) String() string { - return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) + return fmt.Sprintf("(%s, %s)", item.typ, item.val) } func isWhitespace(r rune) bool { return r == '\t' || r == ' ' } @@ -1222,10 +1257,23 @@ func isControl(r rune) bool { // Control characters except \t, \r, \n func isDigit(r rune) bool { return r >= '0' && r <= '9' } func isBinary(r rune) bool { return r == '0' || r == '1' } func isOctal(r rune) bool { return r >= '0' && r <= '7' } -func isHexadecimal(r rune) bool { - return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F') -} -func isBareKeyChar(r rune) bool { +func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') } +func isBareKeyChar(r rune, tomlNext bool) bool { + if tomlNext { + return (r >= 'A' && r <= 'Z') || + (r >= 'a' && r <= 'z') || + (r >= '0' && r <= '9') || + r == '_' || r == '-' || + r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) || + (r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) || + (r >= 0x037f && r <= 0x1fff) || + (r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) || + (r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) || + (r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) || + (r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) || + (r >= 0x10000 && r <= 0xeffff) + } + return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || diff --git a/vendor/github.com/BurntSushi/toml/meta.go b/vendor/github.com/BurntSushi/toml/meta.go index 71847a041..e61453730 100644 --- a/vendor/github.com/BurntSushi/toml/meta.go +++ b/vendor/github.com/BurntSushi/toml/meta.go @@ -13,7 +13,7 @@ type MetaData struct { context Key // Used only during decoding. keyInfo map[string]keyInfo - mapping map[string]interface{} + mapping map[string]any keys []Key decoded map[string]struct{} data []byte // Input file; for errors. @@ -31,12 +31,12 @@ func (md *MetaData) IsDefined(key ...string) bool { } var ( - hash map[string]interface{} + hash map[string]any ok bool - hashOrVal interface{} = md.mapping + hashOrVal any = md.mapping ) for _, k := range key { - if hash, ok = hashOrVal.(map[string]interface{}); !ok { + if hash, ok = hashOrVal.(map[string]any); !ok { return false } if hashOrVal, ok = hash[k]; !ok { @@ -94,28 +94,55 @@ func (md *MetaData) Undecoded() []Key { type Key []string func (k Key) String() string { - ss := make([]string, len(k)) - for i := range k { - ss[i] = k.maybeQuoted(i) + // This is called quite often, so it's a bit funky to make it faster. + var b strings.Builder + b.Grow(len(k) * 25) +outer: + for i, kk := range k { + if i > 0 { + b.WriteByte('.') + } + if kk == "" { + b.WriteString(`""`) + } else { + for _, r := range kk { + // "Inline" isBareKeyChar + if !((r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' || r == '-') { + b.WriteByte('"') + b.WriteString(dblQuotedReplacer.Replace(kk)) + b.WriteByte('"') + continue outer + } + } + b.WriteString(kk) + } } - return strings.Join(ss, ".") + return b.String() } func (k Key) maybeQuoted(i int) string { if k[i] == "" { return `""` } - for _, c := range k[i] { - if !isBareKeyChar(c) { - return `"` + dblQuotedReplacer.Replace(k[i]) + `"` + for _, r := range k[i] { + if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' || r == '-' { + continue } + return `"` + dblQuotedReplacer.Replace(k[i]) + `"` } return k[i] } +// Like append(), but only increase the cap by 1. func (k Key) add(piece string) Key { + if cap(k) > len(k) { + return append(k, piece) + } newKey := make(Key, len(k)+1) copy(newKey, k) newKey[len(k)] = piece return newKey } + +func (k Key) parent() Key { return k[:len(k)-1] } // all except the last piece. +func (k Key) last() string { return k[len(k)-1] } // last piece of this key. diff --git a/vendor/github.com/BurntSushi/toml/parse.go b/vendor/github.com/BurntSushi/toml/parse.go index d2542d6f9..11ac3108b 100644 --- a/vendor/github.com/BurntSushi/toml/parse.go +++ b/vendor/github.com/BurntSushi/toml/parse.go @@ -2,6 +2,8 @@ package toml import ( "fmt" + "math" + "os" "strconv" "strings" "time" @@ -15,12 +17,13 @@ type parser struct { context Key // Full key for the current hash in scope. currentKey string // Base key name for everything except hashes. pos Position // Current position in the TOML file. + tomlNext bool ordered []Key // List of keys in the order that they appear in the TOML data. - keyInfo map[string]keyInfo // Map keyname → info about the TOML key. - mapping map[string]interface{} // Map keyname → key value. - implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). + keyInfo map[string]keyInfo // Map keyname → info about the TOML key. + mapping map[string]any // Map keyname → key value. + implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). } type keyInfo struct { @@ -29,6 +32,8 @@ type keyInfo struct { } func parse(data string) (p *parser, err error) { + _, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110") + defer func() { if r := recover(); r != nil { if pErr, ok := r.(ParseError); ok { @@ -41,9 +46,13 @@ func parse(data string) (p *parser, err error) { }() // Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString() - // which mangles stuff. - if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { + // which mangles stuff. UTF-16 BOM isn't strictly valid, but some tools add + // it anyway. + if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16 data = data[2:] + //lint:ignore S1017 https://github.com/dominikh/go-tools/issues/1447 + } else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8 + data = data[3:] } // Examine first few bytes for NULL bytes; this probably means it's a UTF-16 @@ -64,10 +73,11 @@ func parse(data string) (p *parser, err error) { p = &parser{ keyInfo: make(map[string]keyInfo), - mapping: make(map[string]interface{}), - lx: lex(data), + mapping: make(map[string]any), + lx: lex(data, tomlNext), ordered: make([]Key, 0), implicits: make(map[string]struct{}), + tomlNext: tomlNext, } for { item := p.next() @@ -89,7 +99,7 @@ func (p *parser) panicErr(it item, err error) { }) } -func (p *parser) panicItemf(it item, format string, v ...interface{}) { +func (p *parser) panicItemf(it item, format string, v ...any) { panic(ParseError{ Message: fmt.Sprintf(format, v...), Position: it.pos, @@ -98,7 +108,7 @@ func (p *parser) panicItemf(it item, format string, v ...interface{}) { }) } -func (p *parser) panicf(format string, v ...interface{}) { +func (p *parser) panicf(format string, v ...any) { panic(ParseError{ Message: fmt.Sprintf(format, v...), Position: p.pos, @@ -131,7 +141,7 @@ func (p *parser) nextPos() item { return it } -func (p *parser) bug(format string, v ...interface{}) { +func (p *parser) bug(format string, v ...any) { panic(fmt.Sprintf("BUG: "+format+"\n\n", v...)) } @@ -186,20 +196,21 @@ func (p *parser) topLevel(item item) { p.assertEqual(itemKeyEnd, k.typ) /// The current key is the last part. - p.currentKey = key[len(key)-1] + p.currentKey = key.last() /// All the other parts (if any) are the context; need to set each part /// as implicit. - context := key[:len(key)-1] + context := key.parent() for i := range context { p.addImplicitContext(append(p.context, context[i:i+1]...)) } + p.ordered = append(p.ordered, p.context.add(p.currentKey)) /// Set value. vItem := p.next() val, typ := p.value(vItem, false) - p.set(p.currentKey, val, typ, vItem.pos) - p.ordered = append(p.ordered, p.context.add(p.currentKey)) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ, vItem.pos) /// Remove the context we added (preserving any context from [tbl] lines). p.context = outerContext @@ -214,7 +225,7 @@ func (p *parser) keyString(it item) string { switch it.typ { case itemText: return it.val - case itemString, itemMultilineString, + case itemString, itemStringEsc, itemMultilineString, itemRawString, itemRawMultilineString: s, _ := p.value(it, false) return s.(string) @@ -231,12 +242,14 @@ var datetimeRepl = strings.NewReplacer( // value translates an expected value from the lexer into a Go value wrapped // as an empty interface. -func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { +func (p *parser) value(it item, parentIsArray bool) (any, tomlType) { switch it.typ { case itemString: + return it.val, p.typeOfPrimitive(it) + case itemStringEsc: return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it) case itemMultilineString: - return p.replaceEscapes(it, stripFirstNewline(p.stripEscapedNewlines(it.val))), p.typeOfPrimitive(it) + return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it) case itemRawString: return it.val, p.typeOfPrimitive(it) case itemRawMultilineString: @@ -266,7 +279,7 @@ func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { panic("unreachable") } -func (p *parser) valueInteger(it item) (interface{}, tomlType) { +func (p *parser) valueInteger(it item) (any, tomlType) { if !numUnderscoresOK(it.val) { p.panicItemf(it, "Invalid integer %q: underscores must be surrounded by digits", it.val) } @@ -290,7 +303,7 @@ func (p *parser) valueInteger(it item) (interface{}, tomlType) { return num, p.typeOfPrimitive(it) } -func (p *parser) valueFloat(it item) (interface{}, tomlType) { +func (p *parser) valueFloat(it item) (any, tomlType) { parts := strings.FieldsFunc(it.val, func(r rune) bool { switch r { case '.', 'e', 'E': @@ -314,7 +327,9 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { p.panicItemf(it, "Invalid float %q: '.' must be followed by one or more digits", it.val) } val := strings.Replace(it.val, "_", "", -1) - if val == "+nan" || val == "-nan" { // Go doesn't support this, but TOML spec does. + signbit := false + if val == "+nan" || val == "-nan" { + signbit = val == "-nan" val = "nan" } num, err := strconv.ParseFloat(val, 64) @@ -325,20 +340,29 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { p.panicItemf(it, "Invalid float value: %q", it.val) } } + if signbit { + num = math.Copysign(num, -1) + } return num, p.typeOfPrimitive(it) } var dtTypes = []struct { fmt string zone *time.Location + next bool }{ - {time.RFC3339Nano, time.Local}, - {"2006-01-02T15:04:05.999999999", internal.LocalDatetime}, - {"2006-01-02", internal.LocalDate}, - {"15:04:05.999999999", internal.LocalTime}, + {time.RFC3339Nano, time.Local, false}, + {"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false}, + {"2006-01-02", internal.LocalDate, false}, + {"15:04:05.999999999", internal.LocalTime, false}, + + // tomlNext + {"2006-01-02T15:04Z07:00", time.Local, true}, + {"2006-01-02T15:04", internal.LocalDatetime, true}, + {"15:04", internal.LocalTime, true}, } -func (p *parser) valueDatetime(it item) (interface{}, tomlType) { +func (p *parser) valueDatetime(it item) (any, tomlType) { it.val = datetimeRepl.Replace(it.val) var ( t time.Time @@ -346,28 +370,49 @@ func (p *parser) valueDatetime(it item) (interface{}, tomlType) { err error ) for _, dt := range dtTypes { + if dt.next && !p.tomlNext { + continue + } t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone) if err == nil { + if missingLeadingZero(it.val, dt.fmt) { + p.panicErr(it, errParseDate{it.val}) + } ok = true break } } if !ok { - p.panicItemf(it, "Invalid TOML Datetime: %q.", it.val) + p.panicErr(it, errParseDate{it.val}) } return t, p.typeOfPrimitive(it) } -func (p *parser) valueArray(it item) (interface{}, tomlType) { +// Go's time.Parse() will accept numbers without a leading zero; there isn't any +// way to require it. https://github.com/golang/go/issues/29911 +// +// Depend on the fact that the separators (- and :) should always be at the same +// location. +func missingLeadingZero(d, l string) bool { + for i, c := range []byte(l) { + if c == '.' || c == 'Z' { + return false + } + if (c < '0' || c > '9') && d[i] != c { + return true + } + } + return false +} + +func (p *parser) valueArray(it item) (any, tomlType) { p.setType(p.currentKey, tomlArray, it.pos) var ( - types []tomlType - - // Initialize to a non-nil empty slice. This makes it consistent with - // how S = [] decodes into a non-nil slice inside something like struct - // { S []string }. See #338 - array = []interface{}{} + // Initialize to a non-nil slice to make it consistent with how S = [] + // decodes into a non-nil slice inside something like struct { S + // []string }. See #338 + array = make([]any, 0, 2) ) for it = p.next(); it.typ != itemArrayEnd; it = p.next() { if it.typ == itemCommentStart { @@ -377,20 +422,20 @@ func (p *parser) valueArray(it item) (interface{}, tomlType) { val, typ := p.value(it, true) array = append(array, val) - types = append(types, typ) - // XXX: types isn't used here, we need it to record the accurate type + // XXX: type isn't used here, we need it to record the accurate type // information. // // Not entirely sure how to best store this; could use "key[0]", // "key[1]" notation, or maybe store it on the Array type? + _ = typ } return array, tomlArray } -func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tomlType) { +func (p *parser) valueInlineTable(it item, parentIsArray bool) (any, tomlType) { var ( - hash = make(map[string]interface{}) + topHash = make(map[string]any) outerContext = p.context outerKey = p.currentKey ) @@ -418,19 +463,33 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom p.assertEqual(itemKeyEnd, k.typ) /// The current key is the last part. - p.currentKey = key[len(key)-1] + p.currentKey = key.last() /// All the other parts (if any) are the context; need to set each part /// as implicit. - context := key[:len(key)-1] + context := key.parent() for i := range context { p.addImplicitContext(append(p.context, context[i:i+1]...)) } + p.ordered = append(p.ordered, p.context.add(p.currentKey)) /// Set the value. val, typ := p.value(p.next(), false) - p.set(p.currentKey, val, typ, it.pos) - p.ordered = append(p.ordered, p.context.add(p.currentKey)) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ, it.pos) + + hash := topHash + for _, c := range context { + h, ok := hash[c] + if !ok { + h = make(map[string]any) + hash[c] = h + } + hash, ok = h.(map[string]any) + if !ok { + p.panicf("%q is not a table", p.context) + } + } hash[p.currentKey] = val /// Restore context. @@ -438,7 +497,7 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom } p.context = outerContext p.currentKey = outerKey - return hash, tomlHash + return topHash, tomlHash } // numHasLeadingZero checks if this number has leading zeroes, allowing for '0', @@ -468,9 +527,9 @@ func numUnderscoresOK(s string) bool { } } - // isHexadecimal is a superset of all the permissable characters - // surrounding an underscore. - accept = isHexadecimal(r) + // isHexis a superset of all the permissable characters surrounding an + // underscore. + accept = isHex(r) } return accept } @@ -493,21 +552,19 @@ func numPeriodsOK(s string) bool { // Establishing the context also makes sure that the key isn't a duplicate, and // will create implicit hashes automatically. func (p *parser) addContext(key Key, array bool) { - var ok bool - - // Always start at the top level and drill down for our context. + /// Always start at the top level and drill down for our context. hashContext := p.mapping - keyContext := make(Key, 0) + keyContext := make(Key, 0, len(key)-1) - // We only need implicit hashes for key[0:-1] - for _, k := range key[0 : len(key)-1] { - _, ok = hashContext[k] + /// We only need implicit hashes for the parents. + for _, k := range key.parent() { + _, ok := hashContext[k] keyContext = append(keyContext, k) // No key? Make an implicit hash and move on. if !ok { p.addImplicit(keyContext) - hashContext[k] = make(map[string]interface{}) + hashContext[k] = make(map[string]any) } // If the hash context is actually an array of tables, then set @@ -516,9 +573,9 @@ func (p *parser) addContext(key Key, array bool) { // Otherwise, it better be a table, since this MUST be a key group (by // virtue of it not being the last element in a key). switch t := hashContext[k].(type) { - case []map[string]interface{}: + case []map[string]any: hashContext = t[len(t)-1] - case map[string]interface{}: + case map[string]any: hashContext = t default: p.panicf("Key '%s' was already created as a hash.", keyContext) @@ -529,40 +586,33 @@ func (p *parser) addContext(key Key, array bool) { if array { // If this is the first element for this array, then allocate a new // list of tables for it. - k := key[len(key)-1] + k := key.last() if _, ok := hashContext[k]; !ok { - hashContext[k] = make([]map[string]interface{}, 0, 4) + hashContext[k] = make([]map[string]any, 0, 4) } // Add a new table. But make sure the key hasn't already been used // for something else. - if hash, ok := hashContext[k].([]map[string]interface{}); ok { - hashContext[k] = append(hash, make(map[string]interface{})) + if hash, ok := hashContext[k].([]map[string]any); ok { + hashContext[k] = append(hash, make(map[string]any)) } else { p.panicf("Key '%s' was already created and cannot be used as an array.", key) } } else { - p.setValue(key[len(key)-1], make(map[string]interface{})) + p.setValue(key.last(), make(map[string]any)) } - p.context = append(p.context, key[len(key)-1]) -} - -// set calls setValue and setType. -func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) { - p.setValue(key, val) - p.setType(key, typ, pos) - + p.context = append(p.context, key.last()) } // setValue sets the given key to the given value in the current context. // It will make sure that the key hasn't already been defined, account for // implicit key groups. -func (p *parser) setValue(key string, value interface{}) { +func (p *parser) setValue(key string, value any) { var ( - tmpHash interface{} + tmpHash any ok bool hash = p.mapping - keyContext Key + keyContext = make(Key, 0, len(p.context)+1) ) for _, k := range p.context { keyContext = append(keyContext, k) @@ -570,11 +620,11 @@ func (p *parser) setValue(key string, value interface{}) { p.bug("Context for key '%s' has not been established.", keyContext) } switch t := tmpHash.(type) { - case []map[string]interface{}: + case []map[string]any: // The context is a table of hashes. Pick the most recent table // defined as the current hash. hash = t[len(t)-1] - case map[string]interface{}: + case map[string]any: hash = t default: p.panicf("Key '%s' has already been defined.", keyContext) @@ -601,9 +651,8 @@ func (p *parser) setValue(key string, value interface{}) { p.removeImplicit(keyContext) return } - - // Otherwise, we have a concrete key trying to override a previous - // key, which is *always* wrong. + // Otherwise, we have a concrete key trying to override a previous key, + // which is *always* wrong. p.panicf("Key '%s' has already been defined.", keyContext) } @@ -632,14 +681,11 @@ func (p *parser) setType(key string, typ tomlType, pos Position) { // Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and // "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly). -func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} } -func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) } -func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok } -func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray } -func (p *parser) addImplicitContext(key Key) { - p.addImplicit(key) - p.addContext(key, false) -} +func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} } +func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) } +func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok } +func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray } +func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) } // current returns the full key name of the current context. func (p *parser) current() string { @@ -662,114 +708,131 @@ func stripFirstNewline(s string) string { return s } -// Remove newlines inside triple-quoted strings if a line ends with "\". +// stripEscapedNewlines removes whitespace after line-ending backslashes in +// multiline strings. +// +// A line-ending backslash is an unescaped \ followed only by whitespace until +// the next newline. After a line-ending backslash, all whitespace is removed +// until the next non-whitespace character. func (p *parser) stripEscapedNewlines(s string) string { - split := strings.Split(s, "\n") - if len(split) < 1 { - return s - } - - escNL := false // Keep track of the last non-blank line was escaped. - for i, line := range split { - line = strings.TrimRight(line, " \t\r") - - if len(line) == 0 || line[len(line)-1] != '\\' { - split[i] = strings.TrimRight(split[i], "\r") - if !escNL && i != len(split)-1 { - split[i] += "\n" - } - continue + var ( + b strings.Builder + i int + ) + b.Grow(len(s)) + for { + ix := strings.Index(s[i:], `\`) + if ix < 0 { + b.WriteString(s) + return b.String() } + i += ix - escBS := true - for j := len(line) - 1; j >= 0 && line[j] == '\\'; j-- { - escBS = !escBS + if len(s) > i+1 && s[i+1] == '\\' { + // Escaped backslash. + i += 2 + continue } - if escNL { - line = strings.TrimLeft(line, " \t\r") + // Scan until the next non-whitespace. + j := i + 1 + whitespaceLoop: + for ; j < len(s); j++ { + switch s[j] { + case ' ', '\t', '\r', '\n': + default: + break whitespaceLoop + } } - escNL = !escBS - - if escBS { - split[i] += "\n" + if j == i+1 { + // Not a whitespace escape. + i++ continue } - - if i == len(split)-1 { - p.panicf("invalid escape: '\\ '") - } - - split[i] = line[:len(line)-1] // Remove \ - if len(split)-1 > i { - split[i+1] = strings.TrimLeft(split[i+1], " \t\r") + if !strings.Contains(s[i:j], "\n") { + // This is not a line-ending backslash. (It's a bad escape sequence, + // but we can let replaceEscapes catch it.) + i++ + continue } + b.WriteString(s[:i]) + s = s[j:] + i = 0 } - return strings.Join(split, "") } func (p *parser) replaceEscapes(it item, str string) string { - replaced := make([]rune, 0, len(str)) - s := []byte(str) - r := 0 - for r < len(s) { - if s[r] != '\\' { - c, size := utf8.DecodeRune(s[r:]) - r += size - replaced = append(replaced, c) + var ( + b strings.Builder + skip = 0 + ) + b.Grow(len(str)) + for i, c := range str { + if skip > 0 { + skip-- + continue + } + if c != '\\' { + b.WriteRune(c) continue } - r += 1 - if r >= len(s) { + + if i >= len(str) { p.bug("Escape sequence at end of string.") return "" } - switch s[r] { + switch str[i+1] { default: - p.bug("Expected valid escape code after \\, but got %q.", s[r]) + p.bug("Expected valid escape code after \\, but got %q.", str[i+1]) case ' ', '\t': - p.panicItemf(it, "invalid escape: '\\%c'", s[r]) + p.panicItemf(it, "invalid escape: '\\%c'", str[i+1]) case 'b': - replaced = append(replaced, rune(0x0008)) - r += 1 + b.WriteByte(0x08) + skip = 1 case 't': - replaced = append(replaced, rune(0x0009)) - r += 1 + b.WriteByte(0x09) + skip = 1 case 'n': - replaced = append(replaced, rune(0x000A)) - r += 1 + b.WriteByte(0x0a) + skip = 1 case 'f': - replaced = append(replaced, rune(0x000C)) - r += 1 + b.WriteByte(0x0c) + skip = 1 case 'r': - replaced = append(replaced, rune(0x000D)) - r += 1 + b.WriteByte(0x0d) + skip = 1 + case 'e': + if p.tomlNext { + b.WriteByte(0x1b) + skip = 1 + } case '"': - replaced = append(replaced, rune(0x0022)) - r += 1 + b.WriteByte(0x22) + skip = 1 case '\\': - replaced = append(replaced, rune(0x005C)) - r += 1 + b.WriteByte(0x5c) + skip = 1 + // The lexer guarantees the correct number of characters are present; + // don't need to check here. + case 'x': + if p.tomlNext { + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+4]) + b.WriteRune(escaped) + skip = 3 + } case 'u': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+5). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+5]) - replaced = append(replaced, escaped) - r += 5 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+6]) + b.WriteRune(escaped) + skip = 5 case 'U': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+9). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+9]) - replaced = append(replaced, escaped) - r += 9 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+10]) + b.WriteRune(escaped) + skip = 9 } } - return string(replaced) + return b.String() } -func (p *parser) asciiEscapeToUnicode(it item, bs []byte) rune { - s := string(bs) +func (p *parser) asciiEscapeToUnicode(it item, s string) rune { hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) if err != nil { p.bug("Could not parse '%s' as a hexadecimal number, but the lexer claims it's OK: %s", s, err) diff --git a/vendor/github.com/BurntSushi/toml/type_fields.go b/vendor/github.com/BurntSushi/toml/type_fields.go index 254ca82e5..10c51f7ee 100644 --- a/vendor/github.com/BurntSushi/toml/type_fields.go +++ b/vendor/github.com/BurntSushi/toml/type_fields.go @@ -25,10 +25,8 @@ type field struct { // breaking ties with index sequence. type byName []field -func (x byName) Len() int { return len(x) } - +func (x byName) Len() int { return len(x) } func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - func (x byName) Less(i, j int) bool { if x[i].name != x[j].name { return x[i].name < x[j].name @@ -45,10 +43,8 @@ func (x byName) Less(i, j int) bool { // byIndex sorts field by index sequence. type byIndex []field -func (x byIndex) Len() int { return len(x) } - +func (x byIndex) Len() int { return len(x) } func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - func (x byIndex) Less(i, j int) bool { for k, xik := range x[i].index { if k >= len(x[j].index) { diff --git a/vendor/github.com/BurntSushi/toml/type_toml.go b/vendor/github.com/BurntSushi/toml/type_toml.go index 4e90d7737..1c090d331 100644 --- a/vendor/github.com/BurntSushi/toml/type_toml.go +++ b/vendor/github.com/BurntSushi/toml/type_toml.go @@ -22,13 +22,8 @@ func typeIsTable(t tomlType) bool { type tomlBaseType string -func (btype tomlBaseType) typeString() string { - return string(btype) -} - -func (btype tomlBaseType) String() string { - return btype.typeString() -} +func (btype tomlBaseType) typeString() string { return string(btype) } +func (btype tomlBaseType) String() string { return btype.typeString() } var ( tomlInteger tomlBaseType = "Integer" @@ -54,7 +49,7 @@ func (p *parser) typeOfPrimitive(lexItem item) tomlType { return tomlFloat case itemDatetime: return tomlDatetime - case itemString: + case itemString, itemStringEsc: return tomlString case itemMultilineString: return tomlString diff --git a/vendor/github.com/beevik/etree/.travis.yml b/vendor/github.com/beevik/etree/.travis.yml deleted file mode 100644 index f4cb25d47..000000000 --- a/vendor/github.com/beevik/etree/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -sudo: false - -go: - - 1.11.x - - tip - -matrix: - allow_failures: - - go: tip - -script: - - go vet ./... - - go test -v ./... diff --git a/vendor/github.com/beevik/etree/CONTRIBUTORS b/vendor/github.com/beevik/etree/CONTRIBUTORS index 03211a85e..24ab2dfba 100644 --- a/vendor/github.com/beevik/etree/CONTRIBUTORS +++ b/vendor/github.com/beevik/etree/CONTRIBUTORS @@ -8,3 +8,7 @@ Nicolas Piganeau (npiganeau) Chris Brown (ccbrown) Earncef Sequeira (earncef) Gabriel de Labachelerie (wuzuf) +Martin Dosch (mdosch) +Hugo Wetterberg (hugowetterberg) +Tobias Theel (nerzal) +Daniel Potapov (dpotapov) diff --git a/vendor/github.com/beevik/etree/LICENSE b/vendor/github.com/beevik/etree/LICENSE index 26f1f7751..4ebd85673 100644 --- a/vendor/github.com/beevik/etree/LICENSE +++ b/vendor/github.com/beevik/etree/LICENSE @@ -1,4 +1,4 @@ -Copyright 2015-2019 Brett Vickers. All rights reserved. +Copyright 2015-2024 Brett Vickers. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/vendor/github.com/beevik/etree/README.md b/vendor/github.com/beevik/etree/README.md index 08ec26b0a..98a451839 100644 --- a/vendor/github.com/beevik/etree/README.md +++ b/vendor/github.com/beevik/etree/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://travis-ci.org/beevik/etree.svg?branch=master)](https://travis-ci.org/beevik/etree) [![GoDoc](https://godoc.org/github.com/beevik/etree?status.svg)](https://godoc.org/github.com/beevik/etree) +[![Go](https://github.com/beevik/etree/actions/workflows/go.yml/badge.svg)](https://github.com/beevik/etree/actions/workflows/go.yml) etree ===== diff --git a/vendor/github.com/beevik/etree/RELEASE_NOTES.md b/vendor/github.com/beevik/etree/RELEASE_NOTES.md index ee59d7abf..e82b02dda 100644 --- a/vendor/github.com/beevik/etree/RELEASE_NOTES.md +++ b/vendor/github.com/beevik/etree/RELEASE_NOTES.md @@ -1,3 +1,75 @@ +Release 1.4.1 +============= + +**Changes** + +* Minimal go version updated to 1.21. +* Default-initialized CharsetReader causes same result as NewDocument(). +* When reading an XML document, attributes are parsed more efficiently. + +Release v1.4.0 +============== + +**New Features** + +* Add `AutoClose` option to `ReadSettings`. +* Add `ValidateInput` to `ReadSettings`. +* Add `NotNil` function to `Element`. +* Add `NextSibling` and `PrevSibling` functions to `Element`. + +Release v1.3.0 +============== + +**New Features** + +* Add support for double-quotes in filter path queries. +* Add `PreserveDuplicateAttrs` to `ReadSettings`. +* Add `ReindexChildren` to `Element`. + +Release v1.2.0 +============== + +**New Features** + +* Add the ability to write XML fragments using Token WriteTo functions. +* Add the ability to re-indent an XML element as though it were the root of + the document. +* Add a ReadSettings option to preserve CDATA blocks when reading and XML + document. + +Release v1.1.4 +============== + +**New Features** + +* Add the ability to preserve whitespace in leaf elements during indent. +* Add the ability to suppress a document-trailing newline during indent. +* Add choice of XML attribute quoting style (single-quote or double-quote). + +**Removed Features** + +* Removed the CDATA preservation change introduced in v1.1.3. It was + implemented in a way that broke the ability to process XML documents + encoded using non-UTF8 character sets. + +Release v1.1.3 +============== + +* XML reads now preserve CDATA sections instead of converting them to + standard character data. + +Release v1.1.2 +============== + +* Fixed a path parsing bug. +* The `Element.Text` function now handles comments embedded between + character data spans. + +Release v1.1.1 +============== + +* Updated go version in `go.mod` to 1.20 + Release v1.1.0 ============== diff --git a/vendor/github.com/beevik/etree/etree.go b/vendor/github.com/beevik/etree/etree.go index 9e24f9012..536e4fc2a 100644 --- a/vendor/github.com/beevik/etree/etree.go +++ b/vendor/github.com/beevik/etree/etree.go @@ -13,44 +13,94 @@ import ( "errors" "io" "os" - "sort" + "slices" "strings" ) const ( - // NoIndent is used with Indent to disable all indenting. + // NoIndent is used with the IndentSettings record to remove all + // indenting. NoIndent = -1 ) // ErrXML is returned when XML parsing fails due to incorrect formatting. var ErrXML = errors.New("etree: invalid XML format") -// ReadSettings allow for changing the default behavior of the ReadFrom* -// methods. +// cdataPrefix is used to detect CDATA text when ReadSettings.PreserveCData is +// true. +var cdataPrefix = []byte(" and '. Default: false. CanonicalAttrVal bool - // When outputting indented XML, use a carriage return and linefeed - // ("\r\n") as a new-line delimiter instead of just a linefeed ("\n"). - // This is useful on Windows-based systems. + // AttrSingleQuote causes attributes to use single quotes (attr='example') + // instead of double quotes (attr = "example") when set to true. Default: + // false. + AttrSingleQuote bool + + // UseCRLF causes the document's Indent* functions to use a carriage return + // followed by a linefeed ("\r\n") when outputting a newline. If false, + // only a linefeed is used ("\n"). Default: false. + // + // Deprecated: UseCRLF is deprecated. Use IndentSettings.UseCRLF instead. UseCRLF bool } -// newWriteSettings creates a default WriteSettings record. -func newWriteSettings() WriteSettings { - return WriteSettings{ - CanonicalEndTags: false, - CanonicalText: false, - CanonicalAttrVal: false, - UseCRLF: false, +// dup creates a duplicate of the WriteSettings object. +func (s *WriteSettings) dup() WriteSettings { + return *s +} + +// IndentSettings determine the behavior of the Document's Indent* functions. +type IndentSettings struct { + // Spaces indicates the number of spaces to insert for each level of + // indentation. Set to etree.NoIndent to remove all indentation. Ignored + // when UseTabs is true. Default: 4. + Spaces int + + // UseTabs causes tabs to be used instead of spaces when indenting. + // Default: false. + UseTabs bool + + // UseCRLF causes newlines to be written as a carriage return followed by + // a linefeed ("\r\n"). If false, only a linefeed character is output + // for a newline ("\n"). Default: false. + UseCRLF bool + + // PreserveLeafWhitespace causes indent functions to preserve whitespace + // within XML elements containing only non-CDATA character data. Default: + // false. + PreserveLeafWhitespace bool + + // SuppressTrailingWhitespace suppresses the generation of a trailing + // whitespace characters (such as newlines) at the end of the indented + // document. Default: false. + SuppressTrailingWhitespace bool +} + +// NewIndentSettings creates a default IndentSettings record. +func NewIndentSettings() *IndentSettings { + return &IndentSettings{ + Spaces: 4, + UseTabs: false, + UseCRLF: false, + PreserveLeafWhitespace: false, + SuppressTrailingWhitespace: false, } } -// A Token is an empty interface that represents an Element, CharData, -// Comment, Directive, or ProcInst. +type indentFunc func(depth int) string + +func getIndentFunc(s *IndentSettings) indentFunc { + if s.UseTabs { + if s.UseCRLF { + return func(depth int) string { return indentCRLF(depth, indentTabs) } + } else { + return func(depth int) string { return indentLF(depth, indentTabs) } + } + } else { + if s.Spaces < 0 { + return func(depth int) string { return "" } + } else if s.UseCRLF { + return func(depth int) string { return indentCRLF(depth*s.Spaces, indentSpaces) } + } else { + return func(depth int) string { return indentLF(depth*s.Spaces, indentSpaces) } + } + } +} + +// Writer is the interface that wraps the Write* functions called by each token +// type's WriteTo function. +type Writer interface { + io.StringWriter + io.ByteWriter + io.Writer +} + +// A Token is an interface type used to represent XML elements, character +// data, CDATA sections, XML comments, XML directives, and XML processing +// instructions. type Token interface { Parent() *Element Index() int + WriteTo(w Writer, s *WriteSettings) dup(parent *Element) Token setParent(parent *Element) setIndex(index int) - writeTo(w *bufio.Writer, s *WriteSettings) } -// A Document is a container holding a complete XML hierarchy. Its embedded -// element contains zero or more children, one of which is usually the root -// element. The embedded element may include other children such as -// processing instructions or BOM CharData tokens. +// A Document is a container holding a complete XML tree. +// +// A document has a single embedded element, which contains zero or more child +// tokens, one of which is usually the root element. The embedded element may +// include other children such as processing instruction tokens or character +// data tokens. The document's embedded element is never directly serialized; +// only its children are. +// +// A document also contains read and write settings, which influence the way +// the document is deserialized, serialized, and indented. type Document struct { Element ReadSettings ReadSettings @@ -112,7 +237,7 @@ type Element struct { index int // token index in parent's children } -// An Attr represents a key-value attribute of an XML element. +// An Attr represents a key-value attribute within an XML element. type Attr struct { Space, Key string // The attribute's namespace prefix and key Value string // The attribute value string @@ -123,17 +248,18 @@ type Attr struct { type charDataFlags uint8 const ( - // The CharData was created by an indent function as whitespace. + // The CharData contains only whitespace. whitespaceFlag charDataFlags = 1 << iota // The CharData contains a CDATA section. cdataFlag ) -// CharData can be used to represent character data or a CDATA section within -// an XML document. +// CharData may be used to represent simple text data or a CDATA section +// within an XML document. The Data property should never be modified +// directly; use the SetData function instead. type CharData struct { - Data string + Data string // the simple text or CDATA section content parent *Element index int flags charDataFlags @@ -141,22 +267,22 @@ type CharData struct { // A Comment represents an XML comment. type Comment struct { - Data string + Data string // the comment's text parent *Element index int } // A Directive represents an XML directive. type Directive struct { - Data string + Data string // the directive string parent *Element index int } // A ProcInst represents an XML processing instruction. type ProcInst struct { - Target string - Inst string + Target string // the processing instruction target + Inst string // the processing instruction value parent *Element index int } @@ -164,19 +290,30 @@ type ProcInst struct { // NewDocument creates an XML document without a root element. func NewDocument() *Document { return &Document{ - Element{Child: make([]Token, 0)}, - newReadSettings(), - newWriteSettings(), + Element: Element{Child: make([]Token, 0)}, } } +// NewDocumentWithRoot creates an XML document and sets the element 'e' as its +// root element. If the element 'e' is already part of another document, it is +// first removed from its existing document. +func NewDocumentWithRoot(e *Element) *Document { + d := NewDocument() + d.SetRoot(e) + return d +} + // Copy returns a recursive, deep copy of the document. func (d *Document) Copy() *Document { - return &Document{*(d.dup(nil).(*Element)), d.ReadSettings, d.WriteSettings} + return &Document{ + Element: *(d.Element.dup(nil).(*Element)), + ReadSettings: d.ReadSettings.dup(), + WriteSettings: d.WriteSettings.dup(), + } } -// Root returns the root element of the document, or nil if there is no root -// element. +// Root returns the root element of the document. It returns nil if there is +// no root element. func (d *Document) Root() *Element { for _, t := range d.Child { if c, ok := t.(*Element); ok { @@ -186,25 +323,23 @@ func (d *Document) Root() *Element { return nil } -// SetRoot replaces the document's root element with e. If the document -// already has a root when this function is called, then the document's -// original root is unbound first. If the element e is bound to another -// document (or to another element within a document), then it is unbound -// first. +// SetRoot replaces the document's root element with the element 'e'. If the +// document already has a root element when this function is called, then the +// existing root element is unbound from the document. If the element 'e' is +// part of another document, then it is unbound from the other document. func (d *Document) SetRoot(e *Element) { if e.parent != nil { e.parent.RemoveChild(e) } - p := &d.Element - e.setParent(p) - // If there is already a root element, replace it. + p := &d.Element for i, t := range p.Child { if _, ok := t.(*Element); ok { t.setParent(nil) t.setIndex(-1) p.Child[i] = e + e.setParent(p) e.setIndex(i) return } @@ -214,51 +349,104 @@ func (d *Document) SetRoot(e *Element) { p.addChild(e) } -// ReadFrom reads XML from the reader r into the document d. It returns the -// number of bytes read and any error encountered. +// ReadFrom reads XML from the reader 'r' into this document. The function +// returns the number of bytes read and any error encountered. func (d *Document) ReadFrom(r io.Reader) (n int64, err error) { + if d.ReadSettings.ValidateInput { + b, err := io.ReadAll(r) + if err != nil { + return 0, err + } + if err := validateXML(bytes.NewReader(b), d.ReadSettings); err != nil { + return 0, err + } + r = bytes.NewReader(b) + } return d.Element.readFrom(r, d.ReadSettings) } -// ReadFromFile reads XML from the string s into the document d. -func (d *Document) ReadFromFile(filename string) error { - f, err := os.Open(filename) +// ReadFromFile reads XML from a local file at path 'filepath' into this +// document. +func (d *Document) ReadFromFile(filepath string) error { + f, err := os.Open(filepath) if err != nil { return err } defer f.Close() + _, err = d.ReadFrom(f) return err } -// ReadFromBytes reads XML from the byte slice b into the document d. +// ReadFromBytes reads XML from the byte slice 'b' into the this document. func (d *Document) ReadFromBytes(b []byte) error { - _, err := d.ReadFrom(bytes.NewReader(b)) + if d.ReadSettings.ValidateInput { + if err := validateXML(bytes.NewReader(b), d.ReadSettings); err != nil { + return err + } + } + _, err := d.Element.readFrom(bytes.NewReader(b), d.ReadSettings) return err } -// ReadFromString reads XML from the string s into the document d. +// ReadFromString reads XML from the string 's' into this document. func (d *Document) ReadFromString(s string) error { - _, err := d.ReadFrom(strings.NewReader(s)) + if d.ReadSettings.ValidateInput { + if err := validateXML(strings.NewReader(s), d.ReadSettings); err != nil { + return err + } + } + _, err := d.Element.readFrom(strings.NewReader(s), d.ReadSettings) return err } -// WriteTo serializes an XML document into the writer w. It -// returns the number of bytes written and any error encountered. +// validateXML determines if the data read from the reader 'r' contains +// well-formed XML according to the rules set by the go xml package. +func validateXML(r io.Reader, settings ReadSettings) error { + dec := newDecoder(r, settings) + err := dec.Decode(new(interface{})) + if err != nil { + return err + } + + // If there are any trailing tokens after unmarshalling with Decode(), + // then the XML input didn't terminate properly. + _, err = dec.Token() + if err == io.EOF { + return nil + } + return ErrXML +} + +// newDecoder creates an XML decoder for the reader 'r' configured using +// the provided read settings. +func newDecoder(r io.Reader, settings ReadSettings) *xml.Decoder { + d := xml.NewDecoder(r) + d.CharsetReader = settings.CharsetReader + if d.CharsetReader == nil { + d.CharsetReader = defaultCharsetReader + } + d.Strict = !settings.Permissive + d.Entity = settings.Entity + d.AutoClose = settings.AutoClose + return d +} + +// WriteTo serializes the document out to the writer 'w'. The function returns +// the number of bytes written and any error encountered. func (d *Document) WriteTo(w io.Writer) (n int64, err error) { - cw := newCountWriter(w) - b := bufio.NewWriter(cw) + xw := newXmlWriter(w) + b := bufio.NewWriter(xw) for _, c := range d.Child { - c.writeTo(b, &d.WriteSettings) + c.WriteTo(b, &d.WriteSettings) } - err, n = b.Flush(), cw.bytes + err, n = b.Flush(), xw.bytes return } -// WriteToFile serializes an XML document into the file named -// filename. -func (d *Document) WriteToFile(filename string) error { - f, err := os.Create(filename) +// WriteToFile serializes the document out to the file at path 'filepath'. +func (d *Document) WriteToFile(filepath string) error { + f, err := os.Create(filepath) if err != nil { return err } @@ -267,8 +455,7 @@ func (d *Document) WriteToFile(filename string) error { return err } -// WriteToBytes serializes the XML document into a slice of -// bytes. +// WriteToBytes serializes this document into a slice of bytes. func (d *Document) WriteToBytes() (b []byte, err error) { var buf bytes.Buffer if _, err = d.WriteTo(&buf); err != nil { @@ -277,7 +464,7 @@ func (d *Document) WriteToBytes() (b []byte, err error) { return buf.Bytes(), nil } -// WriteToString serializes the XML document into a string. +// WriteToString serializes this document into a string. func (d *Document) WriteToString() (s string, err error) { var b []byte if b, err = d.WriteToBytes(); err != nil { @@ -286,41 +473,54 @@ func (d *Document) WriteToString() (s string, err error) { return string(b), nil } -type indentFunc func(depth int) string - // Indent modifies the document's element tree by inserting character data -// tokens containing newlines and indentation. The amount of indentation per -// depth level is given as spaces. Pass etree.NoIndent for spaces if you want -// no indentation at all. +// tokens containing newlines and spaces for indentation. The amount of +// indentation per depth level is given by the 'spaces' parameter. Other than +// the number of spaces, default IndentSettings are used. func (d *Document) Indent(spaces int) { - var indent indentFunc - switch { - case spaces < 0: - indent = func(depth int) string { return "" } - case d.WriteSettings.UseCRLF == true: - indent = func(depth int) string { return indentCRLF(depth*spaces, indentSpaces) } - default: - indent = func(depth int) string { return indentLF(depth*spaces, indentSpaces) } - } - d.Element.indent(0, indent) + s := NewIndentSettings() + s.Spaces = spaces + d.IndentWithSettings(s) } // IndentTabs modifies the document's element tree by inserting CharData -// tokens containing newlines and tabs for indentation. One tab is used per -// indentation level. +// tokens containing newlines and tabs for indentation. One tab is used per +// indentation level. Other than the use of tabs, default IndentSettings +// are used. func (d *Document) IndentTabs() { - var indent indentFunc - switch d.WriteSettings.UseCRLF { - case true: - indent = func(depth int) string { return indentCRLF(depth, indentTabs) } - default: - indent = func(depth int) string { return indentLF(depth, indentTabs) } + s := NewIndentSettings() + s.UseTabs = true + d.IndentWithSettings(s) +} + +// IndentWithSettings modifies the document's element tree by inserting +// character data tokens containing newlines and indentation. The behavior +// of the indentation algorithm is configured by the indent settings. +func (d *Document) IndentWithSettings(s *IndentSettings) { + // WriteSettings.UseCRLF is deprecated. Until removed from the package, it + // overrides IndentSettings.UseCRLF when true. + if d.WriteSettings.UseCRLF { + s.UseCRLF = true + } + + d.Element.indent(0, getIndentFunc(s), s) + + if s.SuppressTrailingWhitespace { + d.Element.stripTrailingWhitespace() } - d.Element.indent(0, indent) } -// NewElement creates an unparented element with the specified tag. The tag -// may be prefixed by a namespace prefix and a colon. +// Unindent modifies the document's element tree by removing character data +// tokens containing only whitespace. Other than the removal of indentation, +// default IndentSettings are used. +func (d *Document) Unindent() { + s := NewIndentSettings() + s.Spaces = NoIndent + d.IndentWithSettings(s) +} + +// NewElement creates an unparented element with the specified tag (i.e., +// name). The tag may include a namespace prefix followed by a colon. func NewElement(tag string) *Element { space, stag := spaceDecompose(tag) return newElement(space, stag, nil) @@ -345,7 +545,8 @@ func newElement(space, tag string, parent *Element) *Element { // Copy creates a recursive, deep copy of the element and all its attributes // and children. The returned element has no parent but can be parented to a -// another element using AddElement, or to a document using SetRoot. +// another element using AddChild, or added to a document with SetRoot or +// NewDocumentWithRoot. func (e *Element) Copy() *Element { return e.dup(nil).(*Element) } @@ -400,16 +601,6 @@ func (e *Element) findDefaultNamespaceURI() string { return e.parent.findDefaultNamespaceURI() } -// hasText returns true if the element has character data immediately -// folllowing the element's opening tag. -func (e *Element) hasText() bool { - if len(e.Child) == 0 { - return false - } - _, ok := e.Child[0].(*CharData) - return ok -} - // namespacePrefix returns the namespace prefix associated with the element. func (e *Element) namespacePrefix() string { return e.Space @@ -420,6 +611,15 @@ func (e *Element) name() string { return e.Tag } +// ReindexChildren recalculates the index values of the element's child +// tokens. This is necessary only if you have manually manipulated the +// element's `Child` array. +func (e *Element) ReindexChildren() { + for i := 0; i < len(e.Child); i++ { + e.Child[i].setIndex(i) + } +} + // Text returns all character data immediately following the element's opening // tag. func (e *Element) Text() string { @@ -433,8 +633,10 @@ func (e *Element) Text() string { if text == "" { text = cd.Data } else { - text = text + cd.Data + text += cd.Data } + } else if _, ok := ch.(*Comment); ok { + // ignore } else { break } @@ -470,7 +672,7 @@ func (e *Element) Tail() string { if text == "" { text = cd.Data } else { - text = text + cd.Data + text += cd.Data } } else { break @@ -548,30 +750,30 @@ func (e *Element) findTermCharDataIndex(start int) int { return len(e.Child) } -// CreateElement creates an element with the specified tag and adds it as the -// last child element of the element e. The tag may be prefixed by a namespace -// prefix and a colon. +// CreateElement creates a new element with the specified tag (i.e., name) and +// adds it as the last child token of this element. The tag may include a +// prefix followed by a colon. func (e *Element) CreateElement(tag string) *Element { space, stag := spaceDecompose(tag) return newElement(space, stag, e) } -// AddChild adds the token t as the last child of element e. If token t was -// already the child of another element, it is first removed from its current +// AddChild adds the token 't' as the last child of the element. If token 't' +// was already the child of another element, it is first removed from its // parent element. func (e *Element) AddChild(t Token) { if t.Parent() != nil { t.Parent().RemoveChild(t) } - - t.setParent(e) e.addChild(t) } -// InsertChild inserts the token t before e's existing child token ex. If ex -// is nil or ex is not a child of e, then t is added to the end of e's child -// token list. If token t was already the child of another element, it is -// first removed from its current parent element. +// InsertChild inserts the token 't' into this element's list of children just +// before the element's existing child token 'ex'. If the existing element +// 'ex' does not appear in this element's list of child tokens, then 't' is +// added to the end of this element's list of child tokens. If token 't' is +// already the child of another element, it is first removed from the other +// element's list of child tokens. // // Deprecated: InsertChild is deprecated. Use InsertChildAt instead. func (e *Element) InsertChild(ex Token, t Token) { @@ -596,10 +798,10 @@ func (e *Element) InsertChild(ex Token, t Token) { } } -// InsertChildAt inserts the token t into the element e's list of child tokens -// just before the requested index. If the index is greater than or equal to -// the length of the list of child tokens, the token t is added to the end of -// the list. +// InsertChildAt inserts the token 't' into this element's list of child +// tokens just before the requested 'index'. If the index is greater than or +// equal to the length of the list of child tokens, then the token 't' is +// added to the end of the list of child tokens. func (e *Element) InsertChildAt(index int, t Token) { if index >= len(e.Child) { e.AddChild(t) @@ -624,9 +826,9 @@ func (e *Element) InsertChildAt(index int, t Token) { } } -// RemoveChild attempts to remove the token t from element e's list of -// children. If the token t is a child of e, then it is returned. Otherwise, -// nil is returned. +// RemoveChild attempts to remove the token 't' from this element's list of +// child tokens. If the token 't' was a child of this element, then it is +// removed and returned. Otherwise, nil is returned. func (e *Element) RemoveChild(t Token) Token { if t.Parent() != e { return nil @@ -634,9 +836,9 @@ func (e *Element) RemoveChild(t Token) Token { return e.RemoveChildAt(t.Index()) } -// RemoveChildAt removes the index-th child token from the element e. The -// removed child token is returned. If the index is out of bounds, no child is -// removed and nil is returned. +// RemoveChildAt removes the child token appearing in slot 'index' of this +// element's list of child tokens. The removed child token is then returned. +// If the index is out of bounds, no child is removed and nil is returned. func (e *Element) RemoveChildAt(index int) Token { if index >= len(e.Child) { return nil @@ -652,43 +854,106 @@ func (e *Element) RemoveChildAt(index int) Token { return t } -// ReadFrom reads XML from the reader r and stores the result as a new child -// of element e. +// autoClose analyzes the stack's top element and the current token to decide +// whether the top element should be closed. +func (e *Element) autoClose(stack *stack[*Element], t xml.Token, tags []string) { + if stack.empty() { + return + } + + top := stack.peek() + + for _, tag := range tags { + if strings.EqualFold(tag, top.FullTag()) { + if e, ok := t.(xml.EndElement); !ok || + !strings.EqualFold(e.Name.Space, top.Space) || + !strings.EqualFold(e.Name.Local, top.Tag) { + stack.pop() + } + break + } + } +} + +// ReadFrom reads XML from the reader 'ri' and stores the result as a new +// child of this element. func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err error) { - r := newCountReader(ri) - dec := xml.NewDecoder(r) - dec.CharsetReader = settings.CharsetReader - dec.Strict = !settings.Permissive - dec.Entity = settings.Entity - var stack stack + var r xmlReader + var pr *xmlPeekReader + if settings.PreserveCData { + pr = newXmlPeekReader(ri) + r = pr + } else { + r = newXmlSimpleReader(ri) + } + + attrCheck := make(map[xml.Name]int) + dec := newDecoder(r, settings) + + var stack stack[*Element] stack.push(e) for { + if pr != nil { + pr.PeekPrepare(dec.InputOffset(), len(cdataPrefix)) + } + t, err := dec.RawToken() + + if settings.Permissive && settings.AutoClose != nil { + e.autoClose(&stack, t, settings.AutoClose) + } + switch { case err == io.EOF: - return r.bytes, nil + if len(stack.data) != 1 { + return r.Bytes(), ErrXML + } + return r.Bytes(), nil case err != nil: - return r.bytes, err + return r.Bytes(), err case stack.empty(): - return r.bytes, ErrXML + return r.Bytes(), ErrXML } - top := stack.peek().(*Element) + top := stack.peek() switch t := t.(type) { case xml.StartElement: e := newElement(t.Name.Space, t.Name.Local, top) - for _, a := range t.Attr { - e.createAttr(a.Name.Space, a.Name.Local, a.Value, e) + if settings.PreserveDuplicateAttrs || len(t.Attr) < 2 { + for _, a := range t.Attr { + e.addAttr(a.Name.Space, a.Name.Local, a.Value) + } + } else { + for _, a := range t.Attr { + if i, contains := attrCheck[a.Name]; contains { + e.Attr[i].Value = a.Value + } else { + attrCheck[a.Name] = e.addAttr(a.Name.Space, a.Name.Local, a.Value) + } + } + clear(attrCheck) } stack.push(e) case xml.EndElement: + if top.Tag != t.Name.Local || top.Space != t.Name.Space { + return r.Bytes(), ErrXML + } stack.pop() case xml.CharData: data := string(t) var flags charDataFlags - if isWhitespace(data) { - flags = whitespaceFlag + if pr != nil { + peekBuf := pr.PeekFinalize() + if bytes.Equal(peekBuf, cdataPrefix) { + flags = cdataFlag + } else if isWhitespace(data) { + flags = whitespaceFlag + } + } else { + if isWhitespace(data) { + flags = whitespaceFlag + } } newCharData(data, flags, top) case xml.Comment: @@ -701,9 +966,10 @@ func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err er } } -// SelectAttr finds an element attribute matching the requested key and -// returns it if found. Returns nil if no matching attribute is found. The key -// may be prefixed by a namespace prefix and a colon. +// SelectAttr finds an element attribute matching the requested 'key' and, if +// found, returns a pointer to the matching attribute. The function returns +// nil if no matching attribute is found. The key may include a namespace +// prefix followed by a colon. func (e *Element) SelectAttr(key string) *Attr { space, skey := spaceDecompose(key) for i, a := range e.Attr { @@ -714,9 +980,10 @@ func (e *Element) SelectAttr(key string) *Attr { return nil } -// SelectAttrValue finds an element attribute matching the requested key and -// returns its value if found. The key may be prefixed by a namespace prefix -// and a colon. If the key is not found, the dflt value is returned instead. +// SelectAttrValue finds an element attribute matching the requested 'key' and +// returns its value if found. If no matching attribute is found, the function +// returns the 'dflt' value instead. The key may include a namespace prefix +// followed by a colon. func (e *Element) SelectAttrValue(key, dflt string) string { space, skey := spaceDecompose(key) for _, a := range e.Attr { @@ -727,7 +994,7 @@ func (e *Element) SelectAttrValue(key, dflt string) string { return dflt } -// ChildElements returns all elements that are children of element e. +// ChildElements returns all elements that are children of this element. func (e *Element) ChildElements() []*Element { var elements []*Element for _, t := range e.Child { @@ -738,9 +1005,9 @@ func (e *Element) ChildElements() []*Element { return elements } -// SelectElement returns the first child element with the given tag. The tag -// may be prefixed by a namespace prefix and a colon. Returns nil if no -// element with a matching tag was found. +// SelectElement returns the first child element with the given 'tag' (i.e., +// name). The function returns nil if no child element matching the tag is +// found. The tag may include a namespace prefix followed by a colon. func (e *Element) SelectElement(tag string) *Element { space, stag := spaceDecompose(tag) for _, t := range e.Child { @@ -751,8 +1018,8 @@ func (e *Element) SelectElement(tag string) *Element { return nil } -// SelectElements returns a slice of all child elements with the given tag. -// The tag may be prefixed by a namespace prefix and a colon. +// SelectElements returns a slice of all child elements with the given 'tag' +// (i.e., name). The tag may include a namespace prefix followed by a colon. func (e *Element) SelectElements(tag string) []*Element { space, stag := spaceDecompose(tag) var elements []*Element @@ -764,39 +1031,58 @@ func (e *Element) SelectElements(tag string) []*Element { return elements } -// FindElement returns the first element matched by the XPath-like path -// string. Returns nil if no element is found using the path. Panics if an -// invalid path string is supplied. +// FindElement returns the first element matched by the XPath-like 'path' +// string. The function returns nil if no child element is found using the +// path. It panics if an invalid path string is supplied. func (e *Element) FindElement(path string) *Element { return e.FindElementPath(MustCompilePath(path)) } -// FindElementPath returns the first element matched by the XPath-like path -// string. Returns nil if no element is found using the path. +// FindElementPath returns the first element matched by the 'path' object. The +// function returns nil if no element is found using the path. func (e *Element) FindElementPath(path Path) *Element { p := newPather() elements := p.traverse(e, path) - switch { - case len(elements) > 0: + if len(elements) > 0 { return elements[0] - default: - return nil } + return nil } -// FindElements returns a slice of elements matched by the XPath-like path -// string. Panics if an invalid path string is supplied. +// FindElements returns a slice of elements matched by the XPath-like 'path' +// string. The function returns nil if no child element is found using the +// path. It panics if an invalid path string is supplied. func (e *Element) FindElements(path string) []*Element { return e.FindElementsPath(MustCompilePath(path)) } -// FindElementsPath returns a slice of elements matched by the Path object. +// FindElementsPath returns a slice of elements matched by the 'path' object. func (e *Element) FindElementsPath(path Path) []*Element { p := newPather() return p.traverse(e, path) } -// GetPath returns the absolute path of the element. +// NotNil returns the receiver element if it isn't nil; otherwise, it returns +// an unparented element with an empty string tag. This function simplifies +// the task of writing code to ignore not-found results from element queries. +// For example, instead of writing this: +// +// if e := doc.SelectElement("enabled"); e != nil { +// e.SetText("true") +// } +// +// You could write this: +// +// doc.SelectElement("enabled").NotNil().SetText("true") +func (e *Element) NotNil() *Element { + if e == nil { + return NewElement("") + } + return e +} + +// GetPath returns the absolute path of the element. The absolute path is the +// full path from the document's root. func (e *Element) GetPath() string { path := []string{} for seg := e; seg != nil; seg = seg.Parent() { @@ -813,9 +1099,9 @@ func (e *Element) GetPath() string { return "/" + strings.Join(path, "/") } -// GetRelativePath returns the path of the element relative to the source +// GetRelativePath returns the path of this element relative to the 'source' // element. If the two elements are not part of the same element tree, then -// GetRelativePath returns the empty string. +// the function returns the empty string. func (e *Element) GetRelativePath(source *Element) string { var path []*Element @@ -884,10 +1170,20 @@ func (e *Element) GetRelativePath(source *Element) string { return strings.Join(parts, "/") } -// indent recursively inserts proper indentation between an -// XML element's child tokens. -func (e *Element) indent(depth int, indent indentFunc) { - e.stripIndent() +// IndentWithSettings modifies the element and its child tree by inserting +// character data tokens containing newlines and indentation. The behavior of +// the indentation algorithm is configured by the indent settings. Because +// this function indents the element as if it were at the root of a document, +// it is most useful when called just before writing the element as an XML +// fragment using WriteTo. +func (e *Element) IndentWithSettings(s *IndentSettings) { + e.indent(1, getIndentFunc(s), s) +} + +// indent recursively inserts proper indentation between an XML element's +// child tokens. +func (e *Element) indent(depth int, indent indentFunc, s *IndentSettings) { + e.stripIndent(s) n := len(e.Child) if n == 0 { return @@ -915,7 +1211,7 @@ func (e *Element) indent(depth int, indent indentFunc) { // Recursively process child elements. if ce, ok := c.(*Element); ok { - ce.indent(depth+1, indent) + ce.indent(depth+1, indent, s) } } @@ -931,7 +1227,7 @@ func (e *Element) indent(depth int, indent indentFunc) { } // stripIndent removes any previously inserted indentation. -func (e *Element) stripIndent() { +func (e *Element) stripIndent(s *IndentSettings) { // Count the number of non-indent child tokens n := len(e.Child) for _, c := range e.Child { @@ -942,6 +1238,9 @@ func (e *Element) stripIndent() { if n == len(e.Child) { return } + if n == 0 && len(e.Child) == 1 && s.PreserveLeafWhitespace { + return + } // Strip out indent CharData newChild := make([]Token, n) @@ -957,6 +1256,17 @@ func (e *Element) stripIndent() { e.Child = newChild } +// stripTrailingWhitespace removes any trailing whitespace CharData tokens +// from the element's children. +func (e *Element) stripTrailingWhitespace() { + for i := len(e.Child) - 1; i >= 0; i-- { + if cd, ok := e.Child[i].(*CharData); !ok || !cd.IsWhitespace() { + e.Child = e.Child[:i+1] + return + } + } +} + // dup duplicates the element. func (e *Element) dup(parent *Element) Token { ne := &Element{ @@ -970,47 +1280,63 @@ func (e *Element) dup(parent *Element) Token { for i, t := range e.Child { ne.Child[i] = t.dup(ne) } - for i, a := range e.Attr { - ne.Attr[i] = a - } + copy(ne.Attr, e.Attr) return ne } -// Parent returns the element token's parent element, or nil if it has no -// parent. +// NextSibling returns this element's next sibling element. It returns nil if +// there is no next sibling element. +func (e *Element) NextSibling() *Element { + if e.parent == nil { + return nil + } + for i := e.index + 1; i < len(e.parent.Child); i++ { + if s, ok := e.parent.Child[i].(*Element); ok { + return s + } + } + return nil +} + +// PrevSibling returns this element's preceding sibling element. It returns +// nil if there is no preceding sibling element. +func (e *Element) PrevSibling() *Element { + if e.parent == nil { + return nil + } + for i := e.index - 1; i >= 0; i-- { + if s, ok := e.parent.Child[i].(*Element); ok { + return s + } + } + return nil +} + +// Parent returns this element's parent element. It returns nil if this +// element has no parent. func (e *Element) Parent() *Element { return e.parent } // Index returns the index of this element within its parent element's -// list of child tokens. If this element has no parent element, the index -// is -1. +// list of child tokens. If this element has no parent, then the function +// returns -1. func (e *Element) Index() int { return e.index } -// setParent replaces the element token's parent. -func (e *Element) setParent(parent *Element) { - e.parent = parent -} - -// setIndex sets the element token's index within its parent's Child slice. -func (e *Element) setIndex(index int) { - e.index = index -} - -// writeTo serializes the element to the writer w. -func (e *Element) writeTo(w *bufio.Writer, s *WriteSettings) { +// WriteTo serializes the element to the writer w. +func (e *Element) WriteTo(w Writer, s *WriteSettings) { w.WriteByte('<') w.WriteString(e.FullTag()) for _, a := range e.Attr { w.WriteByte(' ') - a.writeTo(w, s) + a.WriteTo(w, s) } if len(e.Child) > 0 { - w.WriteString(">") + w.WriteByte('>') for _, c := range e.Child { - c.writeTo(w, s) + c.WriteTo(w, s) } w.Write([]byte{'<', '/'}) w.WriteString(e.FullTag()) @@ -1026,42 +1352,58 @@ func (e *Element) writeTo(w *bufio.Writer, s *WriteSettings) { } } +// setParent replaces this element token's parent. +func (e *Element) setParent(parent *Element) { + e.parent = parent +} + +// setIndex sets this element token's index within its parent's Child slice. +func (e *Element) setIndex(index int) { + e.index = index +} + // addChild adds a child token to the element e. func (e *Element) addChild(t Token) { + t.setParent(e) t.setIndex(len(e.Child)) e.Child = append(e.Child, t) } -// CreateAttr creates an attribute and adds it to element e. The key may be -// prefixed by a namespace prefix and a colon. If an attribute with the key -// already exists, its value is replaced. +// CreateAttr creates an attribute with the specified 'key' and 'value' and +// adds it to this element. If an attribute with same key already exists on +// this element, then its value is replaced. The key may include a namespace +// prefix followed by a colon. func (e *Element) CreateAttr(key, value string) *Attr { space, skey := spaceDecompose(key) - return e.createAttr(space, skey, value, e) -} -// createAttr is a helper function that creates attributes. -func (e *Element) createAttr(space, key, value string, parent *Element) *Attr { for i, a := range e.Attr { - if space == a.Space && key == a.Key { + if space == a.Space && skey == a.Key { e.Attr[i].Value = value return &e.Attr[i] } } + + i := e.addAttr(space, skey, value) + return &e.Attr[i] +} + +// addAttr is a helper function that adds an attribute to an element. Returns +// the index of the added attribute. +func (e *Element) addAttr(space, key, value string) int { a := Attr{ Space: space, Key: key, Value: value, - element: parent, + element: e, } e.Attr = append(e.Attr, a) - return &e.Attr[len(e.Attr)-1] + return len(e.Attr) - 1 } -// RemoveAttr removes and returns a copy of the first attribute of the element -// whose key matches the given key. The key may be prefixed by a namespace -// prefix and a colon. If a matching attribute does not exist, nil is -// returned. +// RemoveAttr removes the first attribute of this element whose key matches +// 'key'. It returns a copy of the removed attribute if a match is found. If +// no match is found, it returns nil. The key may include a namespace prefix +// followed by a colon. func (e *Element) RemoveAttr(key string) *Attr { space, skey := spaceDecompose(key) for i, a := range e.Attr { @@ -1078,30 +1420,17 @@ func (e *Element) RemoveAttr(key string) *Attr { return nil } -// SortAttrs sorts the element's attributes lexicographically by key. +// SortAttrs sorts this element's attributes lexicographically by key. func (e *Element) SortAttrs() { - sort.Sort(byAttr(e.Attr)) -} - -type byAttr []Attr - -func (a byAttr) Len() int { - return len(a) -} - -func (a byAttr) Swap(i, j int) { - a[i], a[j] = a[j], a[i] -} - -func (a byAttr) Less(i, j int) bool { - sp := strings.Compare(a[i].Space, a[j].Space) - if sp == 0 { - return strings.Compare(a[i].Key, a[j].Key) < 0 - } - return sp < 0 + slices.SortFunc(e.Attr, func(a, b Attr) int { + if v := strings.Compare(a.Space, b.Space); v != 0 { + return v + } + return strings.Compare(a.Key, b.Key) + }) } -// FullKey returns the attribute a's complete key, including namespace prefix +// FullKey returns this attribute's complete key, including namespace prefix // if present. func (a *Attr) FullKey() string { if a.Space == "" { @@ -1110,22 +1439,29 @@ func (a *Attr) FullKey() string { return a.Space + ":" + a.Key } -// Element returns the element containing the attribute. +// Element returns a pointer to the element containing this attribute. func (a *Attr) Element() *Element { return a.element } -// NamespaceURI returns the XML namespace URI associated with the attribute. -// If the element is part of the XML default namespace, NamespaceURI returns -// the empty string. +// NamespaceURI returns the XML namespace URI associated with this attribute. +// The function returns the empty string if the attribute is unprefixed or +// if the attribute is part of the XML default namespace. func (a *Attr) NamespaceURI() string { - return a.element.NamespaceURI() + if a.Space == "" { + return "" + } + return a.element.findLocalNamespaceURI(a.Space) } -// writeTo serializes the attribute to the writer. -func (a *Attr) writeTo(w *bufio.Writer, s *WriteSettings) { +// WriteTo serializes the attribute to the writer. +func (a *Attr) WriteTo(w Writer, s *WriteSettings) { w.WriteString(a.FullKey()) - w.WriteString(`="`) + if s.AttrSingleQuote { + w.WriteString(`='`) + } else { + w.WriteString(`="`) + } var m escapeMode if s.CanonicalAttrVal { m = escapeCanonicalAttr @@ -1133,20 +1469,26 @@ func (a *Attr) writeTo(w *bufio.Writer, s *WriteSettings) { m = escapeNormal } escapeString(w, a.Value, m) - w.WriteByte('"') + if s.AttrSingleQuote { + w.WriteByte('\'') + } else { + w.WriteByte('"') + } } -// NewText creates a parentless CharData token containing character data. +// NewText creates an unparented CharData token containing simple text data. func NewText(text string) *CharData { return newCharData(text, 0, nil) } -// NewCData creates a parentless XML character CDATA section. +// NewCData creates an unparented XML character CDATA section with 'data' as +// its content. func NewCData(data string) *CharData { return newCharData(data, cdataFlag, nil) } -// NewCharData creates a parentless CharData token containing character data. +// NewCharData creates an unparented CharData token containing simple text +// data. // // Deprecated: NewCharData is deprecated. Instead, use NewText, which does the // same thing. @@ -1159,7 +1501,7 @@ func NewCharData(data string) *CharData { func newCharData(data string, flags charDataFlags, parent *Element) *CharData { c := &CharData{ Data: data, - parent: parent, + parent: nil, index: -1, flags: flags, } @@ -1169,75 +1511,67 @@ func newCharData(data string, flags charDataFlags, parent *Element) *CharData { return c } -// CreateText creates a CharData token containing character data and adds it -// as a child of element e. +// CreateText creates a CharData token containing simple text data and adds it +// to the end of this element's list of child tokens. func (e *Element) CreateText(text string) *CharData { return newCharData(text, 0, e) } -// CreateCData creates a CharData token containing a CDATA section and adds it -// as a child of element e. +// CreateCData creates a CharData token containing a CDATA section with 'data' +// as its content and adds it to the end of this element's list of child +// tokens. func (e *Element) CreateCData(data string) *CharData { return newCharData(data, cdataFlag, e) } -// CreateCharData creates a CharData token containing character data and adds -// it as a child of element e. +// CreateCharData creates a CharData token containing simple text data and +// adds it to the end of this element's list of child tokens. // // Deprecated: CreateCharData is deprecated. Instead, use CreateText, which // does the same thing. func (e *Element) CreateCharData(data string) *CharData { - return newCharData(data, 0, e) + return e.CreateText(data) } -// dup duplicates the character data. -func (c *CharData) dup(parent *Element) Token { - return &CharData{ - Data: c.Data, - flags: c.flags, - parent: parent, - index: c.index, +// SetData modifies the content of the CharData token. In the case of a +// CharData token containing simple text, the simple text is modified. In the +// case of a CharData token containing a CDATA section, the CDATA section's +// content is modified. +func (c *CharData) SetData(text string) { + c.Data = text + if isWhitespace(text) { + c.flags |= whitespaceFlag + } else { + c.flags &= ^whitespaceFlag } } -// IsCData returns true if the character data token is to be encoded as a -// CDATA section. +// IsCData returns true if this CharData token is contains a CDATA section. It +// returns false if the CharData token contains simple text. func (c *CharData) IsCData() bool { return (c.flags & cdataFlag) != 0 } -// IsWhitespace returns true if the character data token was created by one of -// the document Indent methods to contain only whitespace. +// IsWhitespace returns true if this CharData token contains only whitespace. func (c *CharData) IsWhitespace() bool { return (c.flags & whitespaceFlag) != 0 } -// Parent returns the character data token's parent element, or nil if it has -// no parent. +// Parent returns this CharData token's parent element, or nil if it has no +// parent. func (c *CharData) Parent() *Element { return c.parent } // Index returns the index of this CharData token within its parent element's -// list of child tokens. If this CharData token has no parent element, the -// index is -1. +// list of child tokens. If this CharData token has no parent, then the +// function returns -1. func (c *CharData) Index() int { return c.index } -// setParent replaces the character data token's parent. -func (c *CharData) setParent(parent *Element) { - c.parent = parent -} - -// setIndex sets the CharData token's index within its parent element's Child -// slice. -func (c *CharData) setIndex(index int) { - c.index = index -} - -// writeTo serializes character data to the writer. -func (c *CharData) writeTo(w *bufio.Writer, s *WriteSettings) { +// WriteTo serializes character data to the writer. +func (c *CharData) WriteTo(w Writer, s *WriteSettings) { if c.IsCData() { w.WriteString(`") +} + // setParent replaces the comment token's parent. func (c *Comment) setParent(parent *Element) { c.parent = parent @@ -1309,14 +1671,7 @@ func (c *Comment) setIndex(index int) { c.index = index } -// writeTo serialies the comment to the writer. -func (c *Comment) writeTo(w *bufio.Writer, s *WriteSettings) { - w.WriteString("") -} - -// NewDirective creates a parentless XML directive. +// NewDirective creates an unparented XML directive token. func NewDirective(data string) *Directive { return newDirective(data, nil) } @@ -1326,7 +1681,7 @@ func NewDirective(data string) *Directive { func newDirective(data string, parent *Element) *Directive { d := &Directive{ Data: data, - parent: parent, + parent: nil, index: -1, } if parent != nil { @@ -1335,8 +1690,8 @@ func newDirective(data string, parent *Element) *Directive { return d } -// CreateDirective creates an XML directive and adds it as the last child of -// element e. +// CreateDirective creates an XML directive token with the specified 'data' +// value and adds it as the last child token of this element. func (e *Element) CreateDirective(data string) *Directive { return newDirective(data, e) } @@ -1357,12 +1712,19 @@ func (d *Directive) Parent() *Element { } // Index returns the index of this Directive token within its parent element's -// list of child tokens. If this Directive token has no parent element, the -// index is -1. +// list of child tokens. If this Directive token has no parent, then the +// function returns -1. func (d *Directive) Index() int { return d.index } +// WriteTo serializes the XML directive to the writer. +func (d *Directive) WriteTo(w Writer, s *WriteSettings) { + w.WriteString("") +} + // setParent replaces the directive token's parent. func (d *Directive) setParent(parent *Element) { d.parent = parent @@ -1374,14 +1736,7 @@ func (d *Directive) setIndex(index int) { d.index = index } -// writeTo serializes the XML directive to the writer. -func (d *Directive) writeTo(w *bufio.Writer, s *WriteSettings) { - w.WriteString("") -} - -// NewProcInst creates a parentless XML processing instruction. +// NewProcInst creates an unparented XML processing instruction. func NewProcInst(target, inst string) *ProcInst { return newProcInst(target, inst, nil) } @@ -1392,7 +1747,7 @@ func newProcInst(target, inst string, parent *Element) *ProcInst { p := &ProcInst{ Target: target, Inst: inst, - parent: parent, + parent: nil, index: -1, } if parent != nil { @@ -1401,8 +1756,9 @@ func newProcInst(target, inst string, parent *Element) *ProcInst { return p } -// CreateProcInst creates a processing instruction and adds it as a child of -// element e. +// CreateProcInst creates an XML processing instruction token with the +// specified 'target' and instruction 'inst'. It is then added as the last +// child token of this element. func (e *Element) CreateProcInst(target, inst string) *ProcInst { return newProcInst(target, inst, e) } @@ -1424,12 +1780,23 @@ func (p *ProcInst) Parent() *Element { } // Index returns the index of this ProcInst token within its parent element's -// list of child tokens. If this ProcInst token has no parent element, the -// index is -1. +// list of child tokens. If this ProcInst token has no parent, then the +// function returns -1. func (p *ProcInst) Index() int { return p.index } +// WriteTo serializes the processing instruction to the writer. +func (p *ProcInst) WriteTo(w Writer, s *WriteSettings) { + w.WriteString("") +} + // setParent replaces the processing instruction token's parent. func (p *ProcInst) setParent(parent *Element) { p.parent = parent @@ -1440,14 +1807,3 @@ func (p *ProcInst) setParent(parent *Element) { func (p *ProcInst) setIndex(index int) { p.index = index } - -// writeTo serializes the processing instruction to the writer. -func (p *ProcInst) writeTo(w *bufio.Writer, s *WriteSettings) { - w.WriteString("") -} diff --git a/vendor/github.com/beevik/etree/helpers.go b/vendor/github.com/beevik/etree/helpers.go index 825e14e91..ea789b62a 100644 --- a/vendor/github.com/beevik/etree/helpers.go +++ b/vendor/github.com/beevik/etree/helpers.go @@ -5,43 +5,41 @@ package etree import ( - "bufio" "io" "strings" "unicode/utf8" ) -// A simple stack -type stack struct { - data []interface{} +type stack[E any] struct { + data []E } -func (s *stack) empty() bool { +func (s *stack[E]) empty() bool { return len(s.data) == 0 } -func (s *stack) push(value interface{}) { +func (s *stack[E]) push(value E) { s.data = append(s.data, value) } -func (s *stack) pop() interface{} { +func (s *stack[E]) pop() E { value := s.data[len(s.data)-1] - s.data[len(s.data)-1] = nil + var empty E + s.data[len(s.data)-1] = empty s.data = s.data[:len(s.data)-1] return value } -func (s *stack) peek() interface{} { +func (s *stack[E]) peek() E { return s.data[len(s.data)-1] } -// A fifo is a simple first-in-first-out queue. -type fifo struct { - data []interface{} +type queue[E any] struct { + data []E head, tail int } -func (f *fifo) add(value interface{}) { +func (f *queue[E]) add(value E) { if f.len()+1 >= len(f.data) { f.grow() } @@ -51,70 +49,190 @@ func (f *fifo) add(value interface{}) { } } -func (f *fifo) remove() interface{} { +func (f *queue[E]) remove() E { value := f.data[f.head] - f.data[f.head] = nil + var empty E + f.data[f.head] = empty if f.head++; f.head == len(f.data) { f.head = 0 } return value } -func (f *fifo) len() int { +func (f *queue[E]) len() int { if f.tail >= f.head { return f.tail - f.head } return len(f.data) - f.head + f.tail } -func (f *fifo) grow() { +func (f *queue[E]) grow() { c := len(f.data) * 2 if c == 0 { c = 4 } - buf, count := make([]interface{}, c), f.len() + buf, count := make([]E, c), f.len() if f.tail >= f.head { - copy(buf[0:count], f.data[f.head:f.tail]) + copy(buf[:count], f.data[f.head:f.tail]) } else { hindex := len(f.data) - f.head - copy(buf[0:hindex], f.data[f.head:]) + copy(buf[:hindex], f.data[f.head:]) copy(buf[hindex:count], f.data[:f.tail]) } f.data, f.head, f.tail = buf, 0, count } -// countReader implements a proxy reader that counts the number of +// xmlReader provides the interface by which an XML byte stream is +// processed and decoded. +type xmlReader interface { + Bytes() int64 + Read(p []byte) (n int, err error) +} + +// xmlSimpleReader implements a proxy reader that counts the number of // bytes read from its encapsulated reader. -type countReader struct { +type xmlSimpleReader struct { r io.Reader bytes int64 } -func newCountReader(r io.Reader) *countReader { - return &countReader{r: r} +func newXmlSimpleReader(r io.Reader) xmlReader { + return &xmlSimpleReader{r, 0} +} + +func (xr *xmlSimpleReader) Bytes() int64 { + return xr.bytes +} + +func (xr *xmlSimpleReader) Read(p []byte) (n int, err error) { + n, err = xr.r.Read(p) + xr.bytes += int64(n) + return n, err +} + +// xmlPeekReader implements a proxy reader that counts the number of +// bytes read from its encapsulated reader. It also allows the caller to +// "peek" at the previous portions of the buffer after they have been +// parsed. +type xmlPeekReader struct { + r io.Reader + bytes int64 // total bytes read by the Read function + buf []byte // internal read buffer + bufSize int // total bytes used in the read buffer + bufOffset int64 // total bytes read when buf was last filled + window []byte // current read buffer window + peekBuf []byte // buffer used to store data to be peeked at later + peekOffset int64 // total read offset of the start of the peek buffer +} + +func newXmlPeekReader(r io.Reader) *xmlPeekReader { + buf := make([]byte, 4096) + return &xmlPeekReader{ + r: r, + bytes: 0, + buf: buf, + bufSize: 0, + bufOffset: 0, + window: buf[0:0], + peekBuf: make([]byte, 0), + peekOffset: -1, + } +} + +func (xr *xmlPeekReader) Bytes() int64 { + return xr.bytes +} + +func (xr *xmlPeekReader) Read(p []byte) (n int, err error) { + if len(xr.window) == 0 { + err = xr.fill() + if err != nil { + return 0, err + } + if len(xr.window) == 0 { + return 0, nil + } + } + + if len(xr.window) < len(p) { + n = len(xr.window) + } else { + n = len(p) + } + + copy(p, xr.window) + xr.window = xr.window[n:] + xr.bytes += int64(n) + + return n, err +} + +func (xr *xmlPeekReader) PeekPrepare(offset int64, maxLen int) { + if maxLen > cap(xr.peekBuf) { + xr.peekBuf = make([]byte, 0, maxLen) + } + xr.peekBuf = xr.peekBuf[0:0] + xr.peekOffset = offset + xr.updatePeekBuf() +} + +func (xr *xmlPeekReader) PeekFinalize() []byte { + xr.updatePeekBuf() + return xr.peekBuf } -func (cr *countReader) Read(p []byte) (n int, err error) { - b, err := cr.r.Read(p) - cr.bytes += int64(b) - return b, err +func (xr *xmlPeekReader) fill() error { + xr.bufOffset = xr.bytes + xr.bufSize = 0 + n, err := xr.r.Read(xr.buf) + if err != nil { + xr.window, xr.bufSize = xr.buf[0:0], 0 + return err + } + xr.window, xr.bufSize = xr.buf[:n], n + xr.updatePeekBuf() + return nil +} + +func (xr *xmlPeekReader) updatePeekBuf() { + peekRemain := cap(xr.peekBuf) - len(xr.peekBuf) + if xr.peekOffset >= 0 && peekRemain > 0 { + rangeMin := xr.peekOffset + rangeMax := xr.peekOffset + int64(cap(xr.peekBuf)) + bufMin := xr.bufOffset + bufMax := xr.bufOffset + int64(xr.bufSize) + if rangeMin < bufMin { + rangeMin = bufMin + } + if rangeMax > bufMax { + rangeMax = bufMax + } + if rangeMax > rangeMin { + rangeMin -= xr.bufOffset + rangeMax -= xr.bufOffset + if int(rangeMax-rangeMin) > peekRemain { + rangeMax = rangeMin + int64(peekRemain) + } + xr.peekBuf = append(xr.peekBuf, xr.buf[rangeMin:rangeMax]...) + } + } } -// countWriter implements a proxy writer that counts the number of +// xmlWriter implements a proxy writer that counts the number of // bytes written by its encapsulated writer. -type countWriter struct { +type xmlWriter struct { w io.Writer bytes int64 } -func newCountWriter(w io.Writer) *countWriter { - return &countWriter{w: w} +func newXmlWriter(w io.Writer) *xmlWriter { + return &xmlWriter{w: w} } -func (cw *countWriter) Write(p []byte) (n int, err error) { - b, err := cw.w.Write(p) - cw.bytes += int64(b) - return b, err +func (xw *xmlWriter) Write(p []byte) (n int, err error) { + n, err = xw.w.Write(p) + xw.bytes += int64(n) + return n, err } // isWhitespace returns true if the byte slice contains only @@ -181,10 +299,10 @@ func indentLF(n int, source string) string { } } -// nextIndex returns the index of the next occurrence of sep in s, -// starting from offset. It returns -1 if the sep string is not found. -func nextIndex(s, sep string, offset int) int { - switch i := strings.Index(s[offset:], sep); i { +// nextIndex returns the index of the next occurrence of byte ch in s, +// starting from offset. It returns -1 if the byte is not found. +func nextIndex(s string, ch byte, offset int) int { + switch i := strings.IndexByte(s[offset:], ch); i { case -1: return -1 default: @@ -211,7 +329,7 @@ const ( ) // escapeString writes an escaped version of a string to the writer. -func escapeString(w *bufio.Writer, s string, m escapeMode) { +func escapeString(w Writer, s string, m escapeMode) { var esc []byte last := 0 for i := 0; i < len(s); { diff --git a/vendor/github.com/beevik/etree/path.go b/vendor/github.com/beevik/etree/path.go index 82db0ac55..8d6309605 100644 --- a/vendor/github.com/beevik/etree/path.go +++ b/vendor/github.com/beevik/etree/path.go @@ -19,66 +19,73 @@ be modified by one or more bracket-enclosed "filters". Selectors are used to traverse the etree from element to element, while filters are used to narrow the list of candidate elements at each node. -Although etree Path strings are similar to XPath strings -(https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more limited set -of selectors and filtering options. +Although etree Path strings are structurally and behaviorally similar to XPath +strings (https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more +limited set of selectors and filtering options. -The following selectors are supported by etree Path strings: +The following selectors are supported by etree paths: - . Select the current element. - .. Select the parent of the current element. - * Select all child elements of the current element. - / Select the root element when used at the start of a path. - // Select all descendants of the current element. - tag Select all child elements with a name matching the tag. + . Select the current element. + .. Select the parent of the current element. + * Select all child elements of the current element. + / Select the root element when used at the start of a path. + // Select all descendants of the current element. + tag Select all child elements with a name matching the tag. -The following basic filters are supported by etree Path strings: +The following basic filters are supported: - [@attrib] Keep elements with an attribute named attrib. - [@attrib='val'] Keep elements with an attribute named attrib and value matching val. - [tag] Keep elements with a child element named tag. - [tag='val'] Keep elements with a child element named tag and text matching val. - [n] Keep the n-th element, where n is a numeric index starting from 1. + [@attrib] Keep elements with an attribute named attrib. + [@attrib='val'] Keep elements with an attribute named attrib and value matching val. + [tag] Keep elements with a child element named tag. + [tag='val'] Keep elements with a child element named tag and text matching val. + [n] Keep the n-th element, where n is a numeric index starting from 1. -The following function filters are also supported: +The following function-based filters are supported: - [text()] Keep elements with non-empty text. - [text()='val'] Keep elements whose text matches val. - [local-name()='val'] Keep elements whose un-prefixed tag matches val. - [name()='val'] Keep elements whose full tag exactly matches val. - [namespace-prefix()='val'] Keep elements whose namespace prefix matches val. - [namespace-uri()='val'] Keep elements whose namespace URI matches val. + [text()] Keep elements with non-empty text. + [text()='val'] Keep elements whose text matches val. + [local-name()='val'] Keep elements whose un-prefixed tag matches val. + [name()='val'] Keep elements whose full tag exactly matches val. + [namespace-prefix()] Keep elements with non-empty namespace prefixes. + [namespace-prefix()='val'] Keep elements whose namespace prefix matches val. + [namespace-uri()] Keep elements with non-empty namespace URIs. + [namespace-uri()='val'] Keep elements whose namespace URI matches val. -Here are some examples of Path strings: +Below are some examples of etree path strings. -- Select the bookstore child element of the root element: - /bookstore +Select the bookstore child element of the root element: -- Beginning from the root element, select the title elements of all -descendant book elements having a 'category' attribute of 'WEB': - //book[@category='WEB']/title + /bookstore -- Beginning from the current element, select the first descendant -book element with a title child element containing the text 'Great -Expectations': - .//book[title='Great Expectations'][1] +Beginning from the root element, select the title elements of all descendant +book elements having a 'category' attribute of 'WEB': -- Beginning from the current element, select all child elements of -book elements with an attribute 'language' set to 'english': - ./book/*[@language='english'] + //book[@category='WEB']/title -- Beginning from the current element, select all child elements of -book elements containing the text 'special': - ./book/*[text()='special'] +Beginning from the current element, select the first descendant book element +with a title child element containing the text 'Great Expectations': -- Beginning from the current element, select all descendant book -elements whose title child element has a 'language' attribute of 'french': - .//book/title[@language='french']/.. + .//book[title='Great Expectations'][1] -- Beginning from the current element, select all book elements +Beginning from the current element, select all child elements of book elements +with an attribute 'language' set to 'english': + + ./book/*[@language='english'] + +Beginning from the current element, select all child elements of book elements +containing the text 'special': + + ./book/*[text()='special'] + +Beginning from the current element, select all descendant book elements whose +title child element has a 'language' attribute of 'french': + + .//book/title[@language='french']/.. + +Beginning from the current element, select all descendant book elements belonging to the http://www.w3.org/TR/html4/ namespace: - .//book[namespace-uri()='http://www.w3.org/TR/html4/'] + .//book[namespace-uri()='http://www.w3.org/TR/html4/'] */ type Path struct { segments []segment @@ -145,7 +152,7 @@ type filter interface { // a Path object. It collects and deduplicates all elements matching // the path query. type pather struct { - queue fifo + queue queue[node] results []*Element inResults map[*Element]bool candidates []*Element @@ -173,12 +180,12 @@ func newPather() *pather { // and filters. func (p *pather) traverse(e *Element, path Path) []*Element { for p.queue.add(node{e, path.segments}); p.queue.len() > 0; { - p.eval(p.queue.remove().(node)) + p.eval(p.queue.remove()) } return p.results } -// eval evalutes the current path node by applying the remaining +// eval evaluates the current path node by applying the remaining // path's selector rules against the node's element. func (p *pather) eval(n node) { p.candidates = p.candidates[0:0] @@ -210,7 +217,7 @@ type compiler struct { func (c *compiler) parsePath(path string) []segment { // If path ends with //, fix it if strings.HasSuffix(path, "//") { - path = path + "*" + path += "*" } var segments []segment @@ -232,15 +239,20 @@ func (c *compiler) parsePath(path string) []segment { } func splitPath(path string) []string { - pieces := make([]string, 0) + var pieces []string start := 0 inquote := false + var quote byte for i := 0; i+1 <= len(path); i++ { - if path[i] == '\'' { - inquote = !inquote - } else if path[i] == '/' && !inquote { - pieces = append(pieces, path[start:i]) - start = i + 1 + if !inquote { + if path[i] == '\'' || path[i] == '"' { + inquote, quote = true, path[i] + } else if path[i] == '/' { + pieces = append(pieces, path[start:i]) + start = i + 1 + } + } else if path[i] == quote { + inquote = false } } return append(pieces, path[start:]) @@ -255,7 +267,7 @@ func (c *compiler) parseSegment(path string) segment { } for i := 1; i < len(pieces); i++ { fpath := pieces[i] - if fpath[len(fpath)-1] != ']' { + if len(fpath) == 0 || fpath[len(fpath)-1] != ']' { c.err = ErrPath("path has invalid filter [brackets].") break } @@ -280,15 +292,12 @@ func (c *compiler) parseSelector(path string) selector { } } -var fnTable = map[string]struct { - hasFn func(e *Element) bool - getValFn func(e *Element) string -}{ - "local-name": {nil, (*Element).name}, - "name": {nil, (*Element).FullTag}, - "namespace-prefix": {nil, (*Element).namespacePrefix}, - "namespace-uri": {nil, (*Element).NamespaceURI}, - "text": {(*Element).hasText, (*Element).Text}, +var fnTable = map[string]func(e *Element) string{ + "local-name": (*Element).name, + "name": (*Element).FullTag, + "namespace-prefix": (*Element).namespacePrefix, + "namespace-uri": (*Element).NamespaceURI, + "text": (*Element).Text, } // parseFilter parses a path filter contained within [brackets]. @@ -298,30 +307,34 @@ func (c *compiler) parseFilter(path string) filter { return nil } - // Filter contains [@attr='val'], [fn()='val'], or [tag='val']? - eqindex := strings.Index(path, "='") - if eqindex >= 0 { - rindex := nextIndex(path, "'", eqindex+2) - if rindex != len(path)-1 { - c.err = ErrPath("path has mismatched filter quotes.") - return nil - } - - key := path[:eqindex] - value := path[eqindex+2 : rindex] + // Filter contains [@attr='val'], [@attr="val"], [fn()='val'], + // [fn()="val"], [tag='val'] or [tag="val"]? + eqindex := strings.IndexByte(path, '=') + if eqindex >= 0 && eqindex+1 < len(path) { + quote := path[eqindex+1] + if quote == '\'' || quote == '"' { + rindex := nextIndex(path, quote, eqindex+2) + if rindex != len(path)-1 { + c.err = ErrPath("path has mismatched filter quotes.") + return nil + } - switch { - case key[0] == '@': - return newFilterAttrVal(key[1:], value) - case strings.HasSuffix(key, "()"): - fn := key[:len(key)-2] - if t, ok := fnTable[fn]; ok && t.getValFn != nil { - return newFilterFuncVal(t.getValFn, value) + key := path[:eqindex] + value := path[eqindex+2 : rindex] + + switch { + case key[0] == '@': + return newFilterAttrVal(key[1:], value) + case strings.HasSuffix(key, "()"): + name := key[:len(key)-2] + if fn, ok := fnTable[name]; ok { + return newFilterFuncVal(fn, value) + } + c.err = ErrPath("path has unknown function " + name) + return nil + default: + return newFilterChildText(key, value) } - c.err = ErrPath("path has unknown function " + fn) - return nil - default: - return newFilterChildText(key, value) } } @@ -330,11 +343,11 @@ func (c *compiler) parseFilter(path string) filter { case path[0] == '@': return newFilterAttr(path[1:]) case strings.HasSuffix(path, "()"): - fn := path[:len(path)-2] - if t, ok := fnTable[fn]; ok && t.hasFn != nil { - return newFilterFunc(t.hasFn) + name := path[:len(path)-2] + if fn, ok := fnTable[name]; ok { + return newFilterFunc(fn) } - c.err = ErrPath("path has unknown function " + fn) + c.err = ErrPath("path has unknown function " + name) return nil case isInteger(path): pos, _ := strconv.Atoi(path) @@ -393,9 +406,9 @@ func (s *selectChildren) apply(e *Element, p *pather) { type selectDescendants struct{} func (s *selectDescendants) apply(e *Element, p *pather) { - var queue fifo + var queue queue[*Element] for queue.add(e); queue.len() > 0; { - e := queue.remove().(*Element) + e := queue.remove() p.candidates = append(p.candidates, e) for _, c := range e.Child { if c, ok := c.(*Element); ok { @@ -496,16 +509,16 @@ func (f *filterAttrVal) apply(p *pather) { // filterFunc filters the candidate list for elements satisfying a custom // boolean function. type filterFunc struct { - fn func(e *Element) bool + fn func(e *Element) string } -func newFilterFunc(fn func(e *Element) bool) *filterFunc { +func newFilterFunc(fn func(e *Element) string) *filterFunc { return &filterFunc{fn} } func (f *filterFunc) apply(p *pather) { for _, c := range p.candidates { - if f.fn(c) { + if f.fn(c) != "" { p.scratch = append(p.scratch, c) } } diff --git a/vendor/github.com/boltdb/bolt/README.md b/vendor/github.com/boltdb/bolt/README.md index 4c9312c08..7d43a15b2 100644 --- a/vendor/github.com/boltdb/bolt/README.md +++ b/vendor/github.com/boltdb/bolt/README.md @@ -1,4 +1,4 @@ -Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.0-green.svg) +Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.2.1-green.svg) ==== Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas] @@ -15,11 +15,11 @@ and setting values. That's it. ## Project Status -Bolt is stable and the API is fixed. Full unit test coverage and randomized -black box testing are used to ensure database consistency and thread safety. -Bolt is currently in high-load production environments serving databases as -large as 1TB. Many companies such as Shopify and Heroku use Bolt-backed -services every day. +Bolt is stable, the API is fixed, and the file format is fixed. Full unit +test coverage and randomized black box testing are used to ensure database +consistency and thread safety. Bolt is currently used in high-load production +environments serving databases as large as 1TB. Many companies such as +Shopify and Heroku use Bolt-backed services every day. ## Table of Contents @@ -209,7 +209,7 @@ and then safely close your transaction if an error is returned. This is the recommended way to use Bolt transactions. However, sometimes you may want to manually start and end your transactions. -You can use the `Tx.Begin()` function directly but **please** be sure to close +You can use the `DB.Begin()` function directly but **please** be sure to close the transaction. ```go @@ -313,7 +313,7 @@ func (s *Store) CreateUser(u *User) error { // Generate ID for the user. // This returns an error only if the Tx is closed or not writeable. // That can't happen in an Update() call so I ignore the error check. - id, _ = b.NextSequence() + id, _ := b.NextSequence() u.ID = int(id) // Marshal user data into bytes. @@ -395,7 +395,7 @@ db.View(func(tx *bolt.Tx) error { c := tx.Bucket([]byte("MyBucket")).Cursor() prefix := []byte("1234") - for k, v := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, v = c.Next() { + for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { fmt.Printf("key=%s, value=%s\n", k, v) } @@ -448,6 +448,10 @@ db.View(func(tx *bolt.Tx) error { }) ``` +Please note that keys and values in `ForEach()` are only valid while +the transaction is open. If you need to use a key or value outside of +the transaction, you must use `copy()` to copy it to another byte +slice. ### Nested buckets @@ -460,6 +464,55 @@ func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) func (*Bucket) DeleteBucket(key []byte) error ``` +Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings. + +```go + +// createUser creates a new user in the given account. +func createUser(accountID int, u *User) error { + // Start the transaction. + tx, err := db.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + // Retrieve the root bucket for the account. + // Assume this has already been created when the account was set up. + root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10))) + + // Setup the users bucket. + bkt, err := root.CreateBucketIfNotExists([]byte("USERS")) + if err != nil { + return err + } + + // Generate an ID for the new user. + userID, err := bkt.NextSequence() + if err != nil { + return err + } + u.ID = userID + + // Marshal and save the encoded user. + if buf, err := json.Marshal(u); err != nil { + return err + } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil { + return err + } + + // Commit the transaction. + if err := tx.Commit(); err != nil { + return err + } + + return nil +} + +``` + + + ### Database backups @@ -557,7 +610,7 @@ if err != nil { Bolt is able to run on mobile devices by leveraging the binding feature of the [gomobile](https://github.com/golang/mobile) tool. Create a struct that will contain your database logic and a reference to a `*bolt.DB` with a initializing -contstructor that takes in a filepath where the database file will be stored. +constructor that takes in a filepath where the database file will be stored. Neither Android nor iOS require extra permissions or cleanup from using this method. ```go @@ -715,6 +768,9 @@ Here are a few things to note when evaluating and using Bolt: can be reused by a new page or can be unmapped from virtual memory and you'll see an `unexpected fault address` panic when accessing it. +* Bolt uses an exclusive write lock on the database file so it cannot be + shared by multiple processes. + * Be careful when using `Bucket.FillPercent`. Setting a high fill percent for buckets that have random inserts will cause your database to have very poor page utilization. @@ -807,6 +863,7 @@ them via pull request. Below is a list of public, open source projects that use Bolt: +* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. * [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. * [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside. * [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. @@ -825,7 +882,6 @@ Below is a list of public, open source projects that use Bolt: * [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. * [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. * [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. -* [SkyDB](https://github.com/skydb/sky) - Behavioral analytics database. * [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. * [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. * [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. @@ -842,7 +898,19 @@ Below is a list of public, open source projects that use Bolt: * [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. * [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. * [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. -* [Storm](https://github.com/asdine/storm) - A simple ORM around BoltDB. +* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB. * [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. +* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings. +* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. +* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. +* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development. +* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains +* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal. +* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. +* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. +* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies +* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB +* [Ponzu CMS](https://ponzu-cms.org) - Headless CMS + automatic JSON API with auto-HTTPS, HTTP/2 Server Push, and flexible server framework. If you are using Bolt in a project please send a pull request to add it to the list. diff --git a/vendor/github.com/boltdb/bolt/bolt_386.go b/vendor/github.com/boltdb/bolt/bolt_386.go index e659bfb91..820d533c1 100644 --- a/vendor/github.com/boltdb/bolt/bolt_386.go +++ b/vendor/github.com/boltdb/bolt/bolt_386.go @@ -5,3 +5,6 @@ const maxMapSize = 0x7FFFFFFF // 2GB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_amd64.go b/vendor/github.com/boltdb/bolt/bolt_amd64.go index cca6b7eb7..98fafdb47 100644 --- a/vendor/github.com/boltdb/bolt/bolt_amd64.go +++ b/vendor/github.com/boltdb/bolt/bolt_amd64.go @@ -5,3 +5,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_arm.go b/vendor/github.com/boltdb/bolt/bolt_arm.go index e659bfb91..7e5cb4b94 100644 --- a/vendor/github.com/boltdb/bolt/bolt_arm.go +++ b/vendor/github.com/boltdb/bolt/bolt_arm.go @@ -1,7 +1,28 @@ package bolt +import "unsafe" + // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0x7FFFFFFF // 2GB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned bool + +func init() { + // Simple check to see whether this arch handles unaligned load/stores + // correctly. + + // ARM9 and older devices require load/stores to be from/to aligned + // addresses. If not, the lower 2 bits are cleared and that address is + // read in a jumbled up order. + + // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html + + raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11} + val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2)) + + brokenUnaligned = val != 0x11222211 +} diff --git a/vendor/github.com/boltdb/bolt/bolt_arm64.go b/vendor/github.com/boltdb/bolt/bolt_arm64.go index 6d2309352..b26d84f91 100644 --- a/vendor/github.com/boltdb/bolt/bolt_arm64.go +++ b/vendor/github.com/boltdb/bolt/bolt_arm64.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64.go b/vendor/github.com/boltdb/bolt/bolt_ppc64.go index 2dc6be02e..9331d9771 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc64.go +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go index 8351e129f..8c143bc5d 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_s390x.go b/vendor/github.com/boltdb/bolt/bolt_s390x.go index f4dd26bbb..d7c39af92 100644 --- a/vendor/github.com/boltdb/bolt/bolt_s390x.go +++ b/vendor/github.com/boltdb/bolt/bolt_s390x.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_windows.go b/vendor/github.com/boltdb/bolt/bolt_windows.go index d538e6afd..b00fb0720 100644 --- a/vendor/github.com/boltdb/bolt/bolt_windows.go +++ b/vendor/github.com/boltdb/bolt/bolt_windows.go @@ -89,7 +89,7 @@ func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) erro func funlock(db *DB) error { err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{}) db.lockfile.Close() - os.Remove(db.path+lockExt) + os.Remove(db.path + lockExt) return err } diff --git a/vendor/github.com/boltdb/bolt/bucket.go b/vendor/github.com/boltdb/bolt/bucket.go index d2f8c524e..0c5bf2746 100644 --- a/vendor/github.com/boltdb/bolt/bucket.go +++ b/vendor/github.com/boltdb/bolt/bucket.go @@ -130,9 +130,17 @@ func (b *Bucket) Bucket(name []byte) *Bucket { func (b *Bucket) openBucket(value []byte) *Bucket { var child = newBucket(b.tx) + // If unaligned load/stores are broken on this arch and value is + // unaligned simply clone to an aligned byte array. + unaligned := brokenUnaligned && uintptr(unsafe.Pointer(&value[0]))&3 != 0 + + if unaligned { + value = cloneBytes(value) + } + // If this is a writable transaction then we need to copy the bucket entry. // Read-only transactions can point directly at the mmap entry. - if b.tx.writable { + if b.tx.writable && !unaligned { child.bucket = &bucket{} *child.bucket = *(*bucket)(unsafe.Pointer(&value[0])) } else { @@ -167,9 +175,8 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { if bytes.Equal(key, k) { if (flags & bucketLeafFlag) != 0 { return nil, ErrBucketExists - } else { - return nil, ErrIncompatibleValue } + return nil, ErrIncompatibleValue } // Create empty, inline bucket. @@ -329,6 +336,28 @@ func (b *Bucket) Delete(key []byte) error { return nil } +// Sequence returns the current integer for the bucket without incrementing it. +func (b *Bucket) Sequence() uint64 { return b.bucket.sequence } + +// SetSequence updates the sequence number for the bucket. +func (b *Bucket) SetSequence(v uint64) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Materialize the root node if it hasn't been already so that the + // bucket will be saved during commit. + if b.rootNode == nil { + _ = b.node(b.root, nil) + } + + // Increment and return the sequence. + b.bucket.sequence = v + return nil +} + // NextSequence returns an autoincrementing integer for the bucket. func (b *Bucket) NextSequence() (uint64, error) { if b.tx.db == nil { diff --git a/vendor/github.com/boltdb/bolt/db.go b/vendor/github.com/boltdb/bolt/db.go index 1223493ca..f352ff14f 100644 --- a/vendor/github.com/boltdb/bolt/db.go +++ b/vendor/github.com/boltdb/bolt/db.go @@ -552,7 +552,10 @@ func (db *DB) removeTx(tx *Tx) { // Remove the transaction. for i, t := range db.txs { if t == tx { - db.txs = append(db.txs[:i], db.txs[i+1:]...) + last := len(db.txs) - 1 + db.txs[i] = db.txs[last] + db.txs[last] = nil + db.txs = db.txs[:last] break } } @@ -952,7 +955,7 @@ func (s *Stats) Sub(other *Stats) Stats { diff.PendingPageN = s.PendingPageN diff.FreeAlloc = s.FreeAlloc diff.FreelistInuse = s.FreelistInuse - diff.TxN = other.TxN - s.TxN + diff.TxN = s.TxN - other.TxN diff.TxStats = s.TxStats.Sub(&other.TxStats) return diff } diff --git a/vendor/github.com/boltdb/bolt/freelist.go b/vendor/github.com/boltdb/bolt/freelist.go index 0161948fc..aba48f58c 100644 --- a/vendor/github.com/boltdb/bolt/freelist.go +++ b/vendor/github.com/boltdb/bolt/freelist.go @@ -24,7 +24,12 @@ func newFreelist() *freelist { // size returns the size of the page after serialization. func (f *freelist) size() int { - return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * f.count()) + n := f.count() + if n >= 0xFFFF { + // The first element will be used to store the count. See freelist.write. + n++ + } + return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n) } // count returns count of pages on the freelist @@ -46,16 +51,15 @@ func (f *freelist) pending_count() int { return count } -// all returns a list of all free ids and all pending ids in one sorted list. -func (f *freelist) all() []pgid { - m := make(pgids, 0) - +// copyall copies into dst a list of all free ids and all pending ids in one sorted list. +// f.count returns the minimum length required for dst. +func (f *freelist) copyall(dst []pgid) { + m := make(pgids, 0, f.pending_count()) for _, list := range f.pending { m = append(m, list...) } - sort.Sort(m) - return pgids(f.ids).merge(m) + mergepgids(dst, f.ids, m) } // allocate returns the starting page id of a contiguous list of pages of a given size. @@ -166,12 +170,16 @@ func (f *freelist) read(p *page) { } // Copy the list of page ids from the freelist. - ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] - f.ids = make([]pgid, len(ids)) - copy(f.ids, ids) + if count == 0 { + f.ids = nil + } else { + ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] + f.ids = make([]pgid, len(ids)) + copy(f.ids, ids) - // Make sure they're sorted. - sort.Sort(pgids(f.ids)) + // Make sure they're sorted. + sort.Sort(pgids(f.ids)) + } // Rebuild the page cache. f.reindex() @@ -182,20 +190,22 @@ func (f *freelist) read(p *page) { // become free. func (f *freelist) write(p *page) error { // Combine the old free pgids and pgids waiting on an open transaction. - ids := f.all() // Update the header flag. p.flags |= freelistPageFlag // The page.count can only hold up to 64k elements so if we overflow that // number then we handle it by putting the size in the first element. - if len(ids) < 0xFFFF { - p.count = uint16(len(ids)) - copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids) + lenids := f.count() + if lenids == 0 { + p.count = uint16(lenids) + } else if lenids < 0xFFFF { + p.count = uint16(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:]) } else { p.count = 0xFFFF - ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(len(ids)) - copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:], ids) + ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:]) } return nil @@ -230,7 +240,7 @@ func (f *freelist) reload(p *page) { // reindex rebuilds the free cache based on available and pending free lists. func (f *freelist) reindex() { - f.cache = make(map[pgid]bool) + f.cache = make(map[pgid]bool, len(f.ids)) for _, id := range f.ids { f.cache[id] = true } diff --git a/vendor/github.com/boltdb/bolt/node.go b/vendor/github.com/boltdb/bolt/node.go index e9d64af81..159318b22 100644 --- a/vendor/github.com/boltdb/bolt/node.go +++ b/vendor/github.com/boltdb/bolt/node.go @@ -201,6 +201,11 @@ func (n *node) write(p *page) { } p.count = uint16(len(n.inodes)) + // Stop here if there are no items to write. + if p.count == 0 { + return + } + // Loop over each item and write it to the page. b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):] for i, item := range n.inodes { diff --git a/vendor/github.com/boltdb/bolt/page.go b/vendor/github.com/boltdb/bolt/page.go index 4a555286a..cde403ae8 100644 --- a/vendor/github.com/boltdb/bolt/page.go +++ b/vendor/github.com/boltdb/bolt/page.go @@ -62,6 +62,9 @@ func (p *page) leafPageElement(index uint16) *leafPageElement { // leafPageElements retrieves a list of leaf nodes. func (p *page) leafPageElements() []leafPageElement { + if p.count == 0 { + return nil + } return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:] } @@ -72,6 +75,9 @@ func (p *page) branchPageElement(index uint16) *branchPageElement { // branchPageElements retrieves a list of branch nodes. func (p *page) branchPageElements() []branchPageElement { + if p.count == 0 { + return nil + } return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:] } @@ -139,12 +145,33 @@ func (a pgids) merge(b pgids) pgids { // Return the opposite slice if one is nil. if len(a) == 0 { return b - } else if len(b) == 0 { + } + if len(b) == 0 { return a } + merged := make(pgids, len(a)+len(b)) + mergepgids(merged, a, b) + return merged +} + +// mergepgids copies the sorted union of a and b into dst. +// If dst is too small, it panics. +func mergepgids(dst, a, b pgids) { + if len(dst) < len(a)+len(b) { + panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b))) + } + // Copy in the opposite slice if one is nil. + if len(a) == 0 { + copy(dst, b) + return + } + if len(b) == 0 { + copy(dst, a) + return + } - // Create a list to hold all elements from both lists. - merged := make(pgids, 0, len(a)+len(b)) + // Merged will hold all elements from both lists. + merged := dst[:0] // Assign lead to the slice with a lower starting value, follow to the higher value. lead, follow := a, b @@ -166,7 +193,5 @@ func (a pgids) merge(b pgids) pgids { } // Append what's left in follow. - merged = append(merged, follow...) - - return merged + _ = append(merged, follow...) } diff --git a/vendor/github.com/boltdb/bolt/tx.go b/vendor/github.com/boltdb/bolt/tx.go index 1cfb4cde8..6700308a2 100644 --- a/vendor/github.com/boltdb/bolt/tx.go +++ b/vendor/github.com/boltdb/bolt/tx.go @@ -381,7 +381,9 @@ func (tx *Tx) Check() <-chan error { func (tx *Tx) check(ch chan error) { // Check if any pages are double freed. freed := make(map[pgid]bool) - for _, id := range tx.db.freelist.all() { + all := make([]pgid, tx.db.freelist.count()) + tx.db.freelist.copyall(all) + for _, id := range all { if freed[id] { ch <- fmt.Errorf("page %d: already freed", id) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md b/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md index f4b911072..2568ecf0b 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md +++ b/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md @@ -1,176 +1,458 @@ go test -bench=. -benchmem -goos: darwin -goarch: amd64 -pkg: github.com/brianvoe/gofakeit +goos: linux +goarch: amd64 +pkg: github.com/brianvoe/gofakeit/v6 +cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz Table generated with tablesgenerator.com/markdown_tables -| Benchmark | Ops | CPU | MEM | MEM alloc | -|---------------------------------|-----------|-------------|------------|--------------| -| BenchmarkAddress-16 | 797298 | 1649 ns/op | 248 B/op | 7 allocs/op | -| BenchmarkStreet-16 | 1987233 | 601 ns/op | 62 B/op | 3 allocs/op | -| BenchmarkStreetNumber-16 | 4808812 | 252 ns/op | 36 B/op | 2 allocs/op | -| BenchmarkStreetPrefix-16 | 12750800 | 83.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkStreetName-16 | 14026328 | 81.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkStreetSuffix-16 | 13836478 | 81.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCity-16 | 4617508 | 245 ns/op | 15 B/op | 1 allocs/op | -| BenchmarkState-16 | 12095868 | 86.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkStateAbr-16 | 13337152 | 83.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkZip-16 | 6264339 | 201 ns/op | 5 B/op | 1 allocs/op | -| BenchmarkCountry-16 | 12378775 | 85.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCountryAbr-16 | 12770610 | 86.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLatitude-16 | 30935530 | 32.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLongitude-16 | 35305698 | 32.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLatitudeInRange-16 | 35285907 | 34.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLongitudeInRange-16 | 29716158 | 34.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPetName-16 | 15559858 | 69.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAnimal-16 | 15493616 | 71.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAnimalType-16 | 15802927 | 72.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFarmAnimal-16 | 13610484 | 81.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCat-16 | 14966256 | 76.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDog-16 | 12833390 | 88.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUsername-16 | 5720742 | 220 ns/op | 16 B/op | 2 allocs/op | -| BenchmarkPassword-16 | 2016339 | 593 ns/op | 304 B/op | 6 allocs/op | -| BenchmarkBeerName-16 | 15339746 | 72.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerStyle-16 | 12902784 | 86.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerHop-16 | 15131584 | 71.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerYeast-16 | 14747238 | 73.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerMalt-16 | 14982421 | 78.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerIbu-16 | 20595496 | 53.4 ns/op | 8 B/op | 1 allocs/op | -| BenchmarkBeerAlcohol-16 | 3921880 | 299 ns/op | 40 B/op | 3 allocs/op | -| BenchmarkBeerBlg-16 | 4150712 | 300 ns/op | 48 B/op | 3 allocs/op | -| BenchmarkCar-16 | 1996923 | 597 ns/op | 96 B/op | 1 allocs/op | -| BenchmarkCarType-16 | 17076163 | 65.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarFuelType-16 | 14844217 | 73.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarTransmissionType-16 | 16047379 | 68.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarMaker-16 | 14501310 | 76.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarModel-16 | 12503469 | 87.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkColor-16 | 14812000 | 75.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSafeColor-16 | 17647850 | 66.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHexColor-16 | 3710928 | 326 ns/op | 24 B/op | 3 allocs/op | -| BenchmarkRGBColor-16 | 12641104 | 83.3 ns/op | 32 B/op | 1 allocs/op | -| BenchmarkCompany-16 | 17277220 | 67.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCompanySuffix-16 | 17099479 | 60.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBuzzWord-16 | 15963231 | 68.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBS-16 | 15149085 | 71.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkJob-16 | 3203989 | 383 ns/op | 64 B/op | 1 allocs/op | -| BenchmarkJobTitle-16 | 15232904 | 70.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkJobDescriptor-16 | 15603652 | 69.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkJobLevel-16 | 14281743 | 77.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmoji-16 | 15016417 | 75.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiDescription-16 | 14764699 | 76.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiCategory-16 | 13463936 | 78.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiAlias-16 | 12291789 | 87.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiTag-16 | 13451284 | 82.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFileMimeType-16 | 16654501 | 67.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFileExtension-16 | 13656126 | 73.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFruit-16 | 15039096 | 74.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkVegetable-16 | 14397543 | 76.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBreakfast-16 | 5960095 | 181 ns/op | 35 B/op | 1 allocs/op | -| BenchmarkLunch-16 | 6350367 | 189 ns/op | 37 B/op | 1 allocs/op | -| BenchmarkDinner-16 | 6245412 | 177 ns/op | 37 B/op | 1 allocs/op | -| BenchmarkSnack-16 | 5891965 | 192 ns/op | 36 B/op | 1 allocs/op | -| BenchmarkDessert-16 | 6603031 | 186 ns/op | 34 B/op | 2 allocs/op | -| BenchmarkGamertag-16 | 3237366 | 352 ns/op | 36 B/op | 3 allocs/op | -| BenchmarkGenerate-16 | 457622 | 2652 ns/op | 916 B/op | 23 allocs/op | -| BenchmarkMap-16 | 290334 | 4145 ns/op | 1082 B/op | 16 allocs/op | -| BenchmarkHackerPhrase-16 | 200760 | 5623 ns/op | 2909 B/op | 37 allocs/op | -| BenchmarkHackerAbbreviation-16 | 15939142 | 71.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerAdjective-16 | 14837203 | 70.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerNoun-16 | 14633212 | 72.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerVerb-16 | 13376676 | 82.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerIngverb-16 | 14869647 | 72.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkReplaceWithNumbers-16 | 4214044 | 287 ns/op | 32 B/op | 1 allocs/op | -| BenchmarkHipsterWord-16 | 14753112 | 71.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHipsterSentence-16 | 871815 | 1396 ns/op | 305 B/op | 3 allocs/op | -| BenchmarkHipsterParagraph-16 | 42579 | 28624 ns/op | 10560 B/op | 48 allocs/op | -| BenchmarkImageURL-16 | 10556988 | 121 ns/op | 38 B/op | 3 allocs/op | -| BenchmarkDomainName-16 | 2852584 | 428 ns/op | 53 B/op | 2 allocs/op | -| BenchmarkDomainSuffix-16 | 15614646 | 70.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkURL-16 | 1128352 | 1056 ns/op | 189 B/op | 4 allocs/op | -| BenchmarkHTTPMethod-16 | 15604741 | 72.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkIPv4Address-16 | 3539780 | 332 ns/op | 48 B/op | 5 allocs/op | -| BenchmarkIPv6Address-16 | 2419968 | 490 ns/op | 96 B/op | 7 allocs/op | -| BenchmarkMacAddress-16 | 2003596 | 619 ns/op | 79 B/op | 6 allocs/op | -| BenchmarkHTTPStatusCode-16 | 22232200 | 50.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHTTPStatusCodeSimple-16 | 21198192 | 48.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLogLevel-16 | 13729278 | 78.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUserAgent-16 | 1000000 | 1044 ns/op | 300 B/op | 5 allocs/op | -| BenchmarkChromeUserAgent-16 | 1591886 | 783 ns/op | 188 B/op | 5 allocs/op | -| BenchmarkFirefoxUserAgent-16 | 742941 | 1400 ns/op | 362 B/op | 6 allocs/op | -| BenchmarkSafariUserAgent-16 | 930159 | 1306 ns/op | 551 B/op | 7 allocs/op | -| BenchmarkOperaUserAgent-16 | 1454205 | 829 ns/op | 216 B/op | 5 allocs/op | -| BenchmarkLanguage-16 | 15265677 | 71.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLanguageAbbreviation-16 | 16144437 | 68.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkProgrammingLanguage-16 | 16125788 | 71.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkProgrammingLanguageBest-16 | 1000000000 | 0.229 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBool-16 | 79448815 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUUID-16 | 11553009 | 106 ns/op | 48 B/op | 1 allocs/op | -| BenchmarkNumber-16 | 59585859 | 17.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint8-16 | 79947612 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint16-16 | 79249844 | 15.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint32-16 | 81112372 | 14.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint64-16 | 50800922 | 20.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt8-16 | 66494482 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt16-16 | 79505629 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt32-16 | 79967979 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt64-16 | 60566858 | 19.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat32-16 | 84251548 | 14.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat32Range-16 | 80528571 | 14.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat64-16 | 94149510 | 12.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat64Range-16 | 94346104 | 12.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkShuffleInts-16 | 9075564 | 130 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCurrency-16 | 11273227 | 115 ns/op | 32 B/op | 1 allocs/op | -| BenchmarkCurrencyShort-16 | 15565836 | 72.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCurrencyLong-16 | 15420937 | 71.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPrice-16 | 80781411 | 15.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCreditCard-16 | 1637452 | 751 ns/op | 88 B/op | 4 allocs/op | -| BenchmarkCreditCardType-16 | 17678868 | 64.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCreditCardNumber-16 | 3361524 | 349 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkCreditCardNumberLuhn-16 | 279769 | 3620 ns/op | 160 B/op | 10 allocs/op | -| BenchmarkCreditCardExp-16 | 7523824 | 150 ns/op | 5 B/op | 1 allocs/op | -| BenchmarkCreditCardCvv-16 | 15185973 | 73.6 ns/op | 3 B/op | 1 allocs/op | -| BenchmarkName-16 | 5436148 | 215 ns/op | 17 B/op | 1 allocs/op | -| BenchmarkFirstName-16 | 14362125 | 72.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLastName-16 | 15530926 | 72.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNamePrefix-16 | 18074462 | 66.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNameSuffix-16 | 14657012 | 73.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSSN-16 | 18693813 | 68.9 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkGender-16 | 72023787 | 15.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPerson-16 | 282908 | 4377 ns/op | 752 B/op | 24 allocs/op | -| BenchmarkContact-16 | 1369327 | 911 ns/op | 146 B/op | 6 allocs/op | -| BenchmarkPhone-16 | 6015615 | 204 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkPhoneFormatted-16 | 3928914 | 296 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkEmail-16 | 1901041 | 653 ns/op | 98 B/op | 4 allocs/op | -| BenchmarkLetter-16 | 65959573 | 17.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDigit-16 | 58815334 | 17.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNumerify-16 | 5526314 | 207 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkLexify-16 | 9712312 | 129 ns/op | 8 B/op | 1 allocs/op | -| BenchmarkShuffleStrings-16 | 8997901 | 119 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDate-16 | 5949220 | 194 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDateRange-16 | 7122076 | 166 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkMonth-16 | 56979296 | 19.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDay-16 | 61808844 | 17.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkWeekDay-16 | 62598561 | 19.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkYear-16 | 14533374 | 76.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHour-16 | 62130793 | 17.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkMinute-16 | 66836017 | 17.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSecond-16 | 69860632 | 17.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNanoSecond-16 | 66957362 | 17.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZone-16 | 13841594 | 78.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZoneFull-16 | 12788362 | 89.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZoneAbv-16 | 14413452 | 77.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZoneOffset-16 | 10699014 | 103 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNoun-16 | 15025992 | 74.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkVerb-16 | 13394044 | 82.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAdverb-16 | 13968967 | 78.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPreposition-16 | 14575834 | 81.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAdjective-16 | 13957762 | 82.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkWord-16 | 11083752 | 98.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSentence-16 | 647954 | 1642 ns/op | 251 B/op | 2 allocs/op | -| BenchmarkParagraph-16 | 34026 | 35489 ns/op | 9587 B/op | 47 allocs/op | -| BenchmarkLoremIpsumWord-16 | 15156211 | 70.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLoremIpsumSentence-16 | 908371 | 1293 ns/op | 229 B/op | 2 allocs/op | -| BenchmarkLoremIpsumParagraph-16 | 41920 | 27860 ns/op | 9214 B/op | 45 allocs/op | -| BenchmarkQuestion-16 | 1000000 | 1152 ns/op | 315 B/op | 4 allocs/op | -| BenchmarkQuote-16 | 924054 | 1263 ns/op | 268 B/op | 3 allocs/op | -| BenchmarkPhrase-16 | 11034157 | 94.6 ns/op | 0 B/op | 0 allocs/op | \ No newline at end of file +| Benchmark | Ops | CPU | MEM | MEM alloc | +|--------------------------------------------------|------------|------------------|----------------|-------------------| +| BenchmarkAddress/package-8 | 1270872 | 940.1 ns/op | 197 B/op | 5 allocs/op | +| BenchmarkAddress/Faker_math-8 | 1238563 | 1042 ns/op | 197 B/op | 5 allocs/op | +| BenchmarkAddress/Faker_crypto-8 | 139857 | 7862 ns/op | 197 B/op | 5 allocs/op | +| BenchmarkStreet/package-8 | 2955518 | 422.6 ns/op | 26 B/op | 2 allocs/op | +| BenchmarkStreet/Faker_math-8 | 3027224 | 427.3 ns/op | 26 B/op | 2 allocs/op | +| BenchmarkStreet/Faker_crypto-8 | 352165 | 3559 ns/op | 26 B/op | 2 allocs/op | +| BenchmarkStreetNumber/package-8 | 6842211 | 149.2 ns/op | 4 B/op | 1 allocs/op | +| BenchmarkStreetNumber/Faker_math-8 | 6924288 | 158.8 ns/op | 4 B/op | 1 allocs/op | +| BenchmarkStreetNumber/Faker_crypto-8 | 549988 | 1900 ns/op | 4 B/op | 1 allocs/op | +| BenchmarkStreetPrefix/package-8 | 18441643 | 74.12 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetPrefix/Faker_math-8 | 17888110 | 67.51 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetPrefix/Faker_crypto-8 | 2650390 | 458.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetName/package-8 | 18799832 | 62.90 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetName/Faker_math-8 | 16124620 | 63.57 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetName/Faker_crypto-8 | 2873138 | 428.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetSuffix/package-8 | 17192164 | 72.19 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetSuffix/Faker_math-8 | 16545355 | 65.44 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetSuffix/Faker_crypto-8 | 2986934 | 450.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCity/package-8 | 18553683 | 64.93 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCity/Faker_math-8 | 17648109 | 63.77 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCity/Faker_crypto-8 | 2567427 | 470.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkState/package-8 | 18262387 | 66.25 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkState/Faker_math-8 | 16690209 | 73.21 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkState/Faker_crypto-8 | 2599795 | 401.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStateAbr/package-8 | 17492332 | 63.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStateAbr/Faker_math-8 | 18612169 | 64.82 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStateAbr/Faker_crypto-8 | 2821579 | 460.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkZip/package-8 | 7573238 | 157.1 ns/op | 5 B/op | 1 allocs/op | +| BenchmarkZip/Faker_math-8 | 6644562 | 163.4 ns/op | 5 B/op | 1 allocs/op | +| BenchmarkZip/Faker_crypto-8 | 484525 | 2470 ns/op | 5 B/op | 1 allocs/op | +| BenchmarkCountry/package-8 | 15623450 | 65.65 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountry/Faker_math-8 | 17786485 | 76.22 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountry/Faker_crypto-8 | 3002818 | 400.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountryAbr/package-8 | 17296935 | 66.75 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountryAbr/Faker_math-8 | 17862819 | 67.41 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountryAbr/Faker_crypto-8 | 2931120 | 426.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitude/package-8 | 46248466 | 26.11 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitude/Faker_math-8 | 46120956 | 26.00 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitude/Faker_crypto-8 | 3512108 | 366.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitude/package-8 | 47443129 | 24.03 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitude/Faker_math-8 | 46691144 | 24.64 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitude/Faker_crypto-8 | 3501789 | 365.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitudeInRange/package-8 | 44125588 | 26.96 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitudeInRange/Faker_math-8 | 40113348 | 27.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitudeInRange/Faker_crypto-8 | 3227358 | 378.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitudeInRange/package-8 | 38948743 | 32.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitudeInRange/Faker_math-8 | 36491187 | 27.86 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitudeInRange/Faker_crypto-8 | 3004773 | 350.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkPetName/package-8 | 23445927 | 60.81 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkPetName/Faker_math-8 | 23982228 | 53.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkPetName/Faker_crypto-8 | 2681886 | 458.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimal/package-8 | 23230071 | 55.13 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimal/Faker_math-8 | 21923606 | 53.10 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimal/Faker_crypto-8 | 2680177 | 411.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimalType/package-8 | 18826995 | 53.45 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimalType/Faker_math-8 | 22170756 | 63.39 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimalType/Faker_crypto-8 | 2780270 | 399.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFarmAnimal/package-8 | 18548028 | 64.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFarmAnimal/Faker_math-8 | 17291526 | 62.47 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFarmAnimal/Faker_crypto-8 | 2543520 | 409.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCat/package-8 | 21213028 | 68.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCat/Faker_math-8 | 19973062 | 58.74 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCat/Faker_crypto-8 | 2985601 | 405.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDog/package-8 | 16995627 | 68.15 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDog/Faker_math-8 | 17296502 | 81.35 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDog/Faker_crypto-8 | 2530860 | 433.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBird/package-8 | 14445968 | 81.31 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBird/Faker_math-8 | 14545851 | 82.69 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBird/Faker_crypto-8 | 2892721 | 420.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAppName/package-8 | 2799828 | 438.6 ns/op | 25 B/op | 1 allocs/op | +| BenchmarkAppName/Faker_math-8 | 2784135 | 431.1 ns/op | 25 B/op | 1 allocs/op | +| BenchmarkAppName/Faker_crypto-8 | 611072 | 1923 ns/op | 25 B/op | 1 allocs/op | +| BenchmarkAppVersion/package-8 | 7552165 | 154.1 ns/op | 7 B/op | 1 allocs/op | +| BenchmarkAppVersion/Faker_math-8 | 8020767 | 156.6 ns/op | 7 B/op | 1 allocs/op | +| BenchmarkAppVersion/Faker_crypto-8 | 875899 | 1209 ns/op | 7 B/op | 1 allocs/op | +| BenchmarkAppAuthor/package-8 | 9596493 | 119.7 ns/op | 8 B/op | 0 allocs/op | +| BenchmarkAppAuthor/Faker_math-8 | 10068729 | 121.0 ns/op | 8 B/op | 0 allocs/op | +| BenchmarkAppAuthor/Faker_crypto-8 | 1212542 | 983.7 ns/op | 8 B/op | 0 allocs/op | +| BenchmarkUsername/package-8 | 6687600 | 174.6 ns/op | 16 B/op | 2 allocs/op | +| BenchmarkUsername/Faker_math-8 | 7233685 | 173.3 ns/op | 16 B/op | 2 allocs/op | +| BenchmarkUsername/Faker_crypto-8 | 616884 | 2166 ns/op | 16 B/op | 2 allocs/op | +| BenchmarkPassword/package-8 | 2966407 | 401.0 ns/op | 336 B/op | 6 allocs/op | +| BenchmarkPassword/Faker_math-8 | 3080845 | 399.8 ns/op | 336 B/op | 6 allocs/op | +| BenchmarkPassword/Faker_crypto-8 | 182074 | 5963 ns/op | 336 B/op | 6 allocs/op | +| BenchmarkBeerName/package-8 | 23768442 | 53.26 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerName/Faker_math-8 | 22010898 | 63.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerName/Faker_crypto-8 | 2569424 | 392.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerStyle/package-8 | 17567354 | 69.64 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerStyle/Faker_math-8 | 16695721 | 80.73 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerStyle/Faker_crypto-8 | 2710214 | 407.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerHop/package-8 | 20877854 | 56.43 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerHop/Faker_math-8 | 22603234 | 65.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerHop/Faker_crypto-8 | 2618493 | 419.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerYeast/package-8 | 20738073 | 67.89 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerYeast/Faker_math-8 | 21325231 | 67.34 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerYeast/Faker_crypto-8 | 3042529 | 399.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerMalt/package-8 | 15756969 | 65.67 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerMalt/Faker_math-8 | 18026910 | 71.42 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerMalt/Faker_crypto-8 | 2949741 | 429.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerIbu/package-8 | 32683443 | 35.57 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkBeerIbu/Faker_math-8 | 29983339 | 36.03 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkBeerIbu/Faker_crypto-8 | 3094896 | 386.6 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkBeerAlcohol/package-8 | 4744302 | 243.6 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkBeerAlcohol/Faker_math-8 | 4718923 | 252.0 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkBeerAlcohol/Faker_crypto-8 | 1952740 | 656.0 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkBeerBlg/package-8 | 4086861 | 270.6 ns/op | 40 B/op | 3 allocs/op | +| BenchmarkBeerBlg/Faker_math-8 | 4488897 | 259.5 ns/op | 40 B/op | 3 allocs/op | +| BenchmarkBeerBlg/Faker_crypto-8 | 1865367 | 646.7 ns/op | 40 B/op | 3 allocs/op | +| BenchmarkCar/package-8 | 2800782 | 400.5 ns/op | 96 B/op | 1 allocs/op | +| BenchmarkCar/Faker_math-8 | 2938509 | 396.5 ns/op | 96 B/op | 1 allocs/op | +| BenchmarkCar/Faker_crypto-8 | 461906 | 2590 ns/op | 96 B/op | 1 allocs/op | +| BenchmarkCarType/package-8 | 23655384 | 51.72 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarType/Faker_math-8 | 25902462 | 50.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarType/Faker_crypto-8 | 3035287 | 455.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarFuelType/package-8 | 18750069 | 63.80 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarFuelType/Faker_math-8 | 18858705 | 63.15 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarFuelType/Faker_crypto-8 | 3028026 | 387.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarTransmissionType/package-8 | 22570701 | 54.01 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarTransmissionType/Faker_math-8 | 21484246 | 64.27 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarTransmissionType/Faker_crypto-8 | 3061364 | 387.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarMaker/package-8 | 17628445 | 68.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarMaker/Faker_math-8 | 21573310 | 64.19 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarMaker/Faker_crypto-8 | 2688284 | 475.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarModel/package-8 | 18500498 | 73.43 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarModel/Faker_math-8 | 16116993 | 66.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarModel/Faker_crypto-8 | 2487638 | 440.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityActor/package-8 | 18712833 | 74.12 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityActor/Faker_math-8 | 18564168 | 68.96 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityActor/Faker_crypto-8 | 2593150 | 415.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityBusiness/package-8 | 18721152 | 68.98 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityBusiness/Faker_math-8 | 16916186 | 70.66 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityBusiness/Faker_crypto-8 | 2578786 | 407.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebritySport/package-8 | 16716724 | 87.51 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebritySport/Faker_math-8 | 16602294 | 86.41 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebritySport/Faker_crypto-8 | 2919696 | 419.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkColor/package-8 | 17871778 | 62.28 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkColor/Faker_math-8 | 21601353 | 62.63 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkColor/Faker_crypto-8 | 3040459 | 463.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkNiceColors/package-8 | 81438092 | 14.86 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkNiceColors/Faker_math-8 | 75775309 | 18.52 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkNiceColors/Faker_crypto-8 | 3450939 | 353.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSafeColor/package-8 | 22775230 | 53.52 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSafeColor/Faker_math-8 | 24526308 | 59.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSafeColor/Faker_crypto-8 | 3103851 | 413.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHexColor/package-8 | 4640522 | 255.2 ns/op | 24 B/op | 3 allocs/op | +| BenchmarkHexColor/Faker_math-8 | 4723542 | 257.2 ns/op | 24 B/op | 3 allocs/op | +| BenchmarkHexColor/Faker_crypto-8 | 283828 | 4447 ns/op | 24 B/op | 3 allocs/op | +| BenchmarkRGBColor/package-8 | 19721971 | 59.64 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkRGBColor/Faker_math-8 | 18808492 | 67.35 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkRGBColor/Faker_crypto-8 | 1000000 | 1066 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkCompany/package-8 | 22072651 | 48.06 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompany/Faker_math-8 | 22528284 | 53.94 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompany/Faker_crypto-8 | 2690668 | 402.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompanySuffix/package-8 | 28169413 | 48.00 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompanySuffix/Faker_math-8 | 20685153 | 52.20 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompanySuffix/Faker_crypto-8 | 3018765 | 418.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBuzzWord/package-8 | 24238677 | 54.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBuzzWord/Faker_math-8 | 22195419 | 52.30 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBuzzWord/Faker_crypto-8 | 2840428 | 392.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBS/package-8 | 23481436 | 56.33 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBS/Faker_math-8 | 23195737 | 65.66 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBS/Faker_crypto-8 | 3027972 | 419.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJob/package-8 | 4432520 | 253.5 ns/op | 64 B/op | 1 allocs/op | +| BenchmarkJob/Faker_math-8 | 4513154 | 253.7 ns/op | 64 B/op | 1 allocs/op | +| BenchmarkJob/Faker_crypto-8 | 686028 | 1716 ns/op | 64 B/op | 1 allocs/op | +| BenchmarkJobTitle/package-8 | 20079558 | 54.21 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobTitle/Faker_math-8 | 21871627 | 54.86 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobTitle/Faker_crypto-8 | 3017896 | 413.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobDescriptor/package-8 | 21579855 | 53.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobDescriptor/Faker_math-8 | 24638751 | 55.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobDescriptor/Faker_crypto-8 | 2984810 | 415.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobLevel/package-8 | 18311070 | 59.35 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobLevel/Faker_math-8 | 17051210 | 59.53 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobLevel/Faker_crypto-8 | 2991106 | 426.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCSVLookup100-8 | 1468 | 780852 ns/op | 437416 B/op | 5933 allocs/op | +| BenchmarkCSVLookup1000-8 | 151 | 7853471 ns/op | 4224820 B/op | 59612 allocs/op | +| BenchmarkCSVLookup10000-8 | 14 | 78165009 ns/op | 41208010 B/op | 597842 allocs/op | +| BenchmarkCSVLookup100000-8 | 2 | 768800840 ns/op | 437275164 B/op | 5980461 allocs/op | +| BenchmarkEmoji/package-8 | 22212386 | 54.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmoji/Faker_math-8 | 21471013 | 51.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmoji/Faker_crypto-8 | 3036081 | 458.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiDescription/package-8 | 18250413 | 57.08 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiDescription/Faker_math-8 | 21924381 | 57.58 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiDescription/Faker_crypto-8 | 2837050 | 387.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiCategory/package-8 | 21270252 | 55.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiCategory/Faker_math-8 | 21421813 | 59.59 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiCategory/Faker_crypto-8 | 2635878 | 491.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiAlias/package-8 | 18760875 | 68.20 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiAlias/Faker_math-8 | 16918242 | 67.60 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiAlias/Faker_crypto-8 | 2854717 | 488.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiTag/package-8 | 19953885 | 65.43 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiTag/Faker_math-8 | 18220396 | 72.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiTag/Faker_crypto-8 | 2802847 | 426.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkError/package-8 | 1547610 | 786.6 ns/op | 279 B/op | 8 allocs/op | +| BenchmarkError/Faker_math-8 | 1504578 | 794.1 ns/op | 279 B/op | 8 allocs/op | +| BenchmarkError/Faker_crypto-8 | 800712 | 1476 ns/op | 279 B/op | 8 allocs/op | +| BenchmarkErrorObject/package-8 | 6054552 | 190.3 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkErrorObject/Faker_math-8 | 5968180 | 190.3 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkErrorObject/Faker_crypto-8 | 2088008 | 618.0 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkErrorDatabase/package-8 | 5275713 | 212.8 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorDatabase/Faker_math-8 | 5407803 | 217.3 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorDatabase/Faker_crypto-8 | 2005333 | 628.7 ns/op | 63 B/op | 3 allocs/op | +| BenchmarkErrorGRPC/package-8 | 5700810 | 202.9 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorGRPC/Faker_math-8 | 5907589 | 202.5 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorGRPC/Faker_crypto-8 | 2027650 | 643.3 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorHTTP/package-8 | 3182026 | 321.6 ns/op | 157 B/op | 4 allocs/op | +| BenchmarkErrorHTTP/Faker_math-8 | 3667356 | 314.9 ns/op | 157 B/op | 4 allocs/op | +| BenchmarkErrorHTTP/Faker_crypto-8 | 1590696 | 720.2 ns/op | 157 B/op | 4 allocs/op | +| BenchmarkErrorHTTPClient/package-8 | 5745494 | 204.0 ns/op | 52 B/op | 3 allocs/op | +| BenchmarkErrorHTTPClient/Faker_math-8 | 5549187 | 212.8 ns/op | 52 B/op | 3 allocs/op | +| BenchmarkErrorHTTPClient/Faker_crypto-8 | 2011905 | 596.7 ns/op | 52 B/op | 3 allocs/op | +| BenchmarkErrorHTTPServer/package-8 | 5466012 | 214.7 ns/op | 59 B/op | 3 allocs/op | +| BenchmarkErrorHTTPServer/Faker_math-8 | 5542838 | 207.3 ns/op | 59 B/op | 3 allocs/op | +| BenchmarkErrorHTTPServer/Faker_crypto-8 | 1939080 | 633.9 ns/op | 59 B/op | 3 allocs/op | +| BenchmarkErrorRuntime/package-8 | 4245986 | 263.4 ns/op | 150 B/op | 3 allocs/op | +| BenchmarkErrorRuntime/Faker_math-8 | 4355534 | 263.1 ns/op | 150 B/op | 3 allocs/op | +| BenchmarkErrorRuntime/Faker_crypto-8 | 1782044 | 651.4 ns/op | 150 B/op | 3 allocs/op | +| BenchmarkErrorValidation/package-8 | 1659858 | 715.7 ns/op | 268 B/op | 7 allocs/op | +| BenchmarkErrorValidation/Faker_math-8 | 1690849 | 716.4 ns/op | 268 B/op | 7 allocs/op | +| BenchmarkErrorValidation/Faker_crypto-8 | 883600 | 1348 ns/op | 268 B/op | 7 allocs/op | +| BenchmarkFileMimeType/package-8 | 18005230 | 56.88 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileMimeType/Faker_math-8 | 21229381 | 54.62 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileMimeType/Faker_crypto-8 | 2605701 | 462.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileExtension/package-8 | 19272264 | 73.07 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileExtension/Faker_math-8 | 20149288 | 60.79 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileExtension/Faker_crypto-8 | 2627210 | 423.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCusip/package-8 | 5402995 | 224.9 ns/op | 24 B/op | 2 allocs/op | +| BenchmarkCusip/Faker_math-8 | 5367218 | 221.1 ns/op | 24 B/op | 2 allocs/op | +| BenchmarkCusip/Faker_crypto-8 | 363460 | 2967 ns/op | 24 B/op | 2 allocs/op | +| BenchmarkIsin/package-8 | 1742368 | 701.4 ns/op | 533 B/op | 8 allocs/op | +| BenchmarkIsin/Faker_math-8 | 1653408 | 715.5 ns/op | 533 B/op | 8 allocs/op | +| BenchmarkIsin/Faker_crypto-8 | 330396 | 3583 ns/op | 533 B/op | 8 allocs/op | +| BenchmarkFruit/package-8 | 21421066 | 55.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFruit/Faker_math-8 | 22680361 | 55.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFruit/Faker_crypto-8 | 2914611 | 486.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkVegetable/package-8 | 21113413 | 56.44 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkVegetable/Faker_math-8 | 21101716 | 60.98 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkVegetable/Faker_crypto-8 | 2811384 | 467.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBreakfast/package-8 | 8954784 | 127.7 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkBreakfast/Faker_math-8 | 9430814 | 128.8 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkBreakfast/Faker_crypto-8 | 2132481 | 496.5 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkLunch/package-8 | 8934501 | 125.9 ns/op | 34 B/op | 1 allocs/op | +| BenchmarkLunch/Faker_math-8 | 8668546 | 128.9 ns/op | 34 B/op | 1 allocs/op | +| BenchmarkLunch/Faker_crypto-8 | 2216348 | 518.3 ns/op | 34 B/op | 1 allocs/op | +| BenchmarkDinner/package-8 | 9317936 | 125.2 ns/op | 36 B/op | 1 allocs/op | +| BenchmarkDinner/Faker_math-8 | 9023473 | 126.3 ns/op | 36 B/op | 1 allocs/op | +| BenchmarkDinner/Faker_crypto-8 | 2435984 | 518.9 ns/op | 36 B/op | 1 allocs/op | +| BenchmarkDrink/package-8 | 7698025 | 143.4 ns/op | 7 B/op | 2 allocs/op | +| BenchmarkDrink/Faker_math-8 | 8096294 | 139.8 ns/op | 7 B/op | 2 allocs/op | +| BenchmarkDrink/Faker_crypto-8 | 2247427 | 536.2 ns/op | 7 B/op | 2 allocs/op | +| BenchmarkSnack/package-8 | 8109601 | 149.2 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkSnack/Faker_math-8 | 7993006 | 150.5 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkSnack/Faker_crypto-8 | 2214736 | 535.7 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkDessert/package-8 | 8295364 | 133.9 ns/op | 31 B/op | 2 allocs/op | +| BenchmarkDessert/Faker_math-8 | 8610325 | 134.1 ns/op | 31 B/op | 2 allocs/op | +| BenchmarkDessert/Faker_crypto-8 | 2205777 | 507.4 ns/op | 31 B/op | 2 allocs/op | +| BenchmarkGamertag/package-8 | 2111506 | 544.8 ns/op | 83 B/op | 5 allocs/op | +| BenchmarkGamertag/Faker_math-8 | 2203573 | 551.4 ns/op | 83 B/op | 5 allocs/op | +| BenchmarkGamertag/Faker_crypto-8 | 487366 | 2428 ns/op | 83 B/op | 5 allocs/op | +| BenchmarkDice/package-8 | 43259642 | 26.58 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkDice/Faker_math-8 | 42908084 | 26.84 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkDice/Faker_crypto-8 | 2953483 | 395.5 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkGenerate/package-8 | 383122 | 2767 ns/op | 1139 B/op | 29 allocs/op | +| BenchmarkGenerate/Complex-8 | 135508 | 8555 ns/op | 4440 B/op | 80 allocs/op | +| BenchmarkGenerate/Faker_math-8 | 377151 | 2817 ns/op | 1139 B/op | 29 allocs/op | +| BenchmarkGenerate/Faker_crypto-8 | 152226 | 7234 ns/op | 1139 B/op | 29 allocs/op | +| BenchmarkRegex/package-8 | 628683 | 1922 ns/op | 1632 B/op | 27 allocs/op | +| BenchmarkRegex/Faker_math-8 | 591548 | 1940 ns/op | 1632 B/op | 27 allocs/op | +| BenchmarkRegex/Faker_crypto-8 | 616701 | 1934 ns/op | 1632 B/op | 27 allocs/op | +| BenchmarkRegexEmail/package-8 | 174812 | 6607 ns/op | 4084 B/op | 90 allocs/op | +| BenchmarkRegexEmail/Faker_math-8 | 174512 | 6619 ns/op | 4084 B/op | 90 allocs/op | +| BenchmarkRegexEmail/Faker_crypto-8 | 62312 | 18793 ns/op | 4083 B/op | 90 allocs/op | +| BenchmarkMap/package-8 | 318559 | 3275 ns/op | 1113 B/op | 16 allocs/op | +| BenchmarkMap/Faker_math-8 | 315990 | 3319 ns/op | 1113 B/op | 16 allocs/op | +| BenchmarkMap/Faker_crypto-8 | 46202 | 23997 ns/op | 1115 B/op | 16 allocs/op | +| BenchmarkHackerPhrase/package-8 | 155998 | 7191 ns/op | 3004 B/op | 50 allocs/op | +| BenchmarkHackerPhrase/Faker_math-8 | 154675 | 7305 ns/op | 3008 B/op | 50 allocs/op | +| BenchmarkHackerPhrase/Faker_crypto-8 | 109282 | 10268 ns/op | 3007 B/op | 50 allocs/op | +| BenchmarkHackerAbbreviation/package-8 | 21881574 | 57.57 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAbbreviation/Faker_math-8 | 18534495 | 59.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAbbreviation/Faker_crypto-8 | 2607735 | 401.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAdjective/package-8 | 24286845 | 55.74 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAdjective/Faker_math-8 | 22684101 | 55.22 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAdjective/Faker_crypto-8 | 2953530 | 490.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerNoun/package-8 | 22554241 | 55.35 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerNoun/Faker_math-8 | 18360708 | 56.78 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerNoun/Faker_crypto-8 | 2823256 | 464.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerVerb/package-8 | 19236123 | 65.49 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerVerb/Faker_math-8 | 18090754 | 68.18 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerVerb/Faker_crypto-8 | 2880181 | 439.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackeringVerb/package-8 | 19090326 | 71.74 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackeringVerb/Faker_math-8 | 19048659 | 63.31 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackeringVerb/Faker_crypto-8 | 3020748 | 404.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkReplaceWithNumbers-8 | 162931 | 7098 ns/op | 32 B/op | 2 allocs/op | +| BenchmarkHipsterWord/package-8 | 24059244 | 54.69 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHipsterWord/Faker_math-8 | 21708511 | 52.98 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHipsterWord/Faker_crypto-8 | 2870858 | 396.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHipsterSentence/package-8 | 1278764 | 927.7 ns/op | 288 B/op | 3 allocs/op | +| BenchmarkHipsterSentence/Faker_math-8 | 1287939 | 955.0 ns/op | 288 B/op | 3 allocs/op | +| BenchmarkHipsterSentence/Faker_crypto-8 | 237703 | 4595 ns/op | 288 B/op | 3 allocs/op | +| BenchmarkHipsterParagraph/package-8 | 57895 | 18466 ns/op | 10521 B/op | 48 allocs/op | +| BenchmarkHipsterParagraph/Faker_math-8 | 61772 | 19188 ns/op | 10520 B/op | 48 allocs/op | +| BenchmarkHipsterParagraph/Faker_crypto-8 | 12978 | 91733 ns/op | 10522 B/op | 48 allocs/op | +| BenchmarkInputName/package-8 | 15728428 | 74.49 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkInputName/Faker_math-8 | 13243030 | 89.75 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkInputName/Faker_crypto-8 | 2736225 | 478.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSvg/package-8 | 172828 | 7906 ns/op | 8871 B/op | 52 allocs/op | +| BenchmarkSvg/Faker_math-8 | 161821 | 6754 ns/op | 8875 B/op | 52 allocs/op | +| BenchmarkSvg/Faker_crypto-8 | 29023 | 40910 ns/op | 8862 B/op | 52 allocs/op | +| BenchmarkImageURL/package-8 | 11692422 | 94.34 ns/op | 38 B/op | 3 allocs/op | +| BenchmarkImageURL/Faker_math-8 | 11451087 | 91.39 ns/op | 38 B/op | 3 allocs/op | +| BenchmarkImageURL/Faker_crypto-8 | 12107578 | 92.30 ns/op | 38 B/op | 3 allocs/op | +| BenchmarkImage/package-8 | 50 | 20495942 ns/op | 2457673 B/op | 307202 allocs/op | +| BenchmarkImage/Faker_math-8 | 51 | 20349126 ns/op | 2457780 B/op | 307202 allocs/op | +| BenchmarkImage/Faker_crypto-8 | 3 | 393591549 ns/op | 2457685 B/op | 307202 allocs/op | +| BenchmarkImageJpeg/package-8 | 31 | 32857846 ns/op | 2982318 B/op | 307214 allocs/op | +| BenchmarkImageJpeg/Faker_math-8 | 34 | 31873165 ns/op | 2982479 B/op | 307214 allocs/op | +| BenchmarkImageJpeg/Faker_crypto-8 | 3 | 387670345 ns/op | 2982357 B/op | 307215 allocs/op | +| BenchmarkImagePng/package-8 | 16 | 65425256 ns/op | 5899024 B/op | 307270 allocs/op | +| BenchmarkImagePng/Faker_math-8 | 18 | 67804235 ns/op | 5899314 B/op | 307270 allocs/op | +| BenchmarkImagePng/Faker_crypto-8 | 3 | 396378778 ns/op | 5899005 B/op | 307270 allocs/op | +| BenchmarkDomainName/package-8 | 2344912 | 505.6 ns/op | 95 B/op | 5 allocs/op | +| BenchmarkDomainName/Faker_math-8 | 2265744 | 512.5 ns/op | 95 B/op | 5 allocs/op | +| BenchmarkDomainName/Faker_crypto-8 | 639775 | 1788 ns/op | 95 B/op | 5 allocs/op | +| BenchmarkDomainSuffix/package-8 | 19431498 | 59.95 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDomainSuffix/Faker_math-8 | 20097267 | 59.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDomainSuffix/Faker_crypto-8 | 2498906 | 437.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkURL/package-8 | 1000000 | 1155 ns/op | 277 B/op | 10 allocs/op | +| BenchmarkURL/Faker_math-8 | 1000000 | 1165 ns/op | 277 B/op | 10 allocs/op | +| BenchmarkURL/Faker_crypto-8 | 275793 | 4371 ns/op | 276 B/op | 10 allocs/op | +| BenchmarkHTTPMethod/package-8 | 17651594 | 59.20 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPMethod/Faker_math-8 | 20081227 | 61.28 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPMethod/Faker_crypto-8 | 2844322 | 460.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkIPv4Address/package-8 | 5215255 | 229.2 ns/op | 16 B/op | 1 allocs/op | +| BenchmarkIPv4Address/Faker_math-8 | 4852905 | 224.9 ns/op | 16 B/op | 1 allocs/op | +| BenchmarkIPv4Address/Faker_crypto-8 | 670951 | 1827 ns/op | 16 B/op | 1 allocs/op | +| BenchmarkIPv6Address/package-8 | 2312482 | 510.0 ns/op | 111 B/op | 8 allocs/op | +| BenchmarkIPv6Address/Faker_math-8 | 2261472 | 521.2 ns/op | 111 B/op | 8 allocs/op | +| BenchmarkIPv6Address/Faker_crypto-8 | 338601 | 3623 ns/op | 111 B/op | 8 allocs/op | +| BenchmarkMacAddress/package-8 | 2809762 | 426.2 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkMacAddress/Faker_math-8 | 2863842 | 425.5 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkMacAddress/Faker_crypto-8 | 376604 | 2688 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkHTTPStatusCode/package-8 | 13488582 | 88.27 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCode/Faker_math-8 | 14188726 | 73.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCode/Faker_crypto-8 | 2497014 | 463.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCodeSimple/package-8 | 17822486 | 81.54 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCodeSimple/Faker_math-8 | 16282341 | 70.72 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCodeSimple/Faker_crypto-8 | 2360576 | 451.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLogLevel/package-8 | 19343472 | 67.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLogLevel/Faker_math-8 | 19445798 | 61.84 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLogLevel/Faker_crypto-8 | 2296162 | 468.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkUserAgent/package-8 | 1503814 | 813.9 ns/op | 297 B/op | 5 allocs/op | +| BenchmarkUserAgent/Faker_math-8 | 1462177 | 803.6 ns/op | 298 B/op | 5 allocs/op | +| BenchmarkUserAgent/Faker_crypto-8 | 181178 | 6157 ns/op | 298 B/op | 5 allocs/op | +| BenchmarkChromeUserAgent/package-8 | 1911201 | 596.8 ns/op | 184 B/op | 5 allocs/op | +| BenchmarkChromeUserAgent/Faker_math-8 | 1969712 | 598.1 ns/op | 184 B/op | 5 allocs/op | +| BenchmarkChromeUserAgent/Faker_crypto-8 | 264816 | 4433 ns/op | 184 B/op | 5 allocs/op | +| BenchmarkFirefoxUserAgent/package-8 | 1000000 | 1043 ns/op | 362 B/op | 6 allocs/op | +| BenchmarkFirefoxUserAgent/Faker_math-8 | 1000000 | 1054 ns/op | 362 B/op | 6 allocs/op | +| BenchmarkFirefoxUserAgent/Faker_crypto-8 | 166128 | 7646 ns/op | 362 B/op | 6 allocs/op | +| BenchmarkSafariUserAgent/package-8 | 1000000 | 1022 ns/op | 551 B/op | 7 allocs/op | +| BenchmarkSafariUserAgent/Faker_math-8 | 1000000 | 1017 ns/op | 551 B/op | 7 allocs/op | +| BenchmarkSafariUserAgent/Faker_crypto-8 | 146463 | 7525 ns/op | 551 B/op | 7 allocs/op | +| BenchmarkOperaUserAgent/package-8 | 1844185 | 643.8 ns/op | 212 B/op | 5 allocs/op | +| BenchmarkOperaUserAgent/Faker_math-8 | 1805168 | 654.3 ns/op | 212 B/op | 5 allocs/op | +| BenchmarkOperaUserAgent/Faker_crypto-8 | 219927 | 5257 ns/op | 212 B/op | 5 allocs/op | +| BenchmarkJSONLookup100-8 | 894 | 1194698 ns/op | 537673 B/op | 8141 allocs/op | +| BenchmarkJSONLookup1000-8 | 91 | 12099728 ns/op | 5616708 B/op | 81606 allocs/op | +| BenchmarkJSONLookup10000-8 | 8 | 128144166 ns/op | 62638763 B/op | 817708 allocs/op | +| BenchmarkJSONLookup100000-8 | 1 | 1324756016 ns/op | 616116744 B/op | 8179136 allocs/op | +| BenchmarkLanguage/package-8 | 20946056 | 68.53 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguage/Faker_math-8 | 16884613 | 61.06 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguage/Faker_crypto-8 | 2889944 | 442.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageAbbreviation/package-8 | 20782443 | 53.79 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageAbbreviation/Faker_math-8 | 17936367 | 56.26 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageAbbreviation/Faker_crypto-8 | 2630406 | 423.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageBCP/package-8 | 19858063 | 59.00 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageBCP/Faker_math-8 | 20712447 | 60.02 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageBCP/Faker_crypto-8 | 2654044 | 469.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguage/package-8 | 17849598 | 58.34 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguage/Faker_math-8 | 20090289 | 70.59 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguage/Faker_crypto-8 | 2628798 | 424.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguageBest/package-8 | 1000000000 | 0.4044 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguageBest/Faker_math-8 | 1000000000 | 0.2975 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguageBest/Faker_crypto-8 | 1000000000 | 0.2543 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLoremIpsumWord-8 | 22434632 | 54.96 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLoremIpsumSentence-8 | 1000000 | 1038 ns/op | 219 B/op | 2 allocs/op | +| BenchmarkLoremIpsumParagraph-8 | 59320 | 19442 ns/op | 8479 B/op | 40 allocs/op | +| BenchmarkMinecraftOre/package-8 | 14624242 | 90.01 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftOre/Faker_math-8 | 16379578 | 86.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftOre/Faker_crypto-8 | 2757652 | 477.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWood/package-8 | 15815132 | 83.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWood/Faker_math-8 | 14872902 | 75.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWood/Faker_crypto-8 | 2524514 | 514.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorTier/package-8 | 15296107 | 78.58 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorTier/Faker_math-8 | 14341870 | 86.33 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorTier/Faker_crypto-8 | 2344278 | 473.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorPart/package-8 | 16863422 | 82.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorPart/Faker_math-8 | 14052031 | 76.92 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorPart/Faker_crypto-8 | 2770314 | 474.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeapon/package-8 | 15759004 | 77.42 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeapon/Faker_math-8 | 15945940 | 81.48 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeapon/Faker_crypto-8 | 2254436 | 464.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftTool/package-8 | 15887787 | 76.39 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftTool/Faker_math-8 | 14269508 | 91.01 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftTool/Faker_crypto-8 | 2718507 | 525.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftDye/package-8 | 16131942 | 71.06 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftDye/Faker_math-8 | 16802478 | 73.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftDye/Faker_crypto-8 | 2584966 | 476.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftFood/package-8 | 14680048 | 87.15 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftFood/Faker_math-8 | 13558227 | 86.71 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftFood/Faker_crypto-8 | 2329946 | 435.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftAnimal/package-8 | 15871832 | 85.92 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftAnimal/Faker_math-8 | 12411510 | 83.88 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftAnimal/Faker_crypto-8 | 2528960 | 441.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerJob/package-8 | 13549438 | 80.41 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerJob/Faker_math-8 | 13769702 | 104.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerJob/Faker_crypto-8 | 2397300 | 452.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerStation/package-8 | 15069139 | 93.65 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerStation/Faker_math-8 | 15468883 | 82.27 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerStation/Faker_crypto-8 | 2469778 | 453.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerLevel/package-8 | 13468396 | 102.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerLevel/Faker_math-8 | 14354506 | 92.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerLevel/Faker_crypto-8 | 2416441 | 544.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobPassive/package-8 | 13299806 | 84.84 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobPassive/Faker_math-8 | 14181126 | 87.18 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobPassive/Faker_crypto-8 | 2539264 | 510.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobNeutral/package-8 | 11043175 | 110.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobNeutral/Faker_math-8 | 13059249 | 99.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobNeutral/Faker_crypto-8 | 2394342 | 544.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobHostile/package-8 | 13963809 | 95.66 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobHostile/Faker_math-8 | 15182318 | 96.90 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobHostile/Faker_crypto-8 | 2204600 | 538.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobBoss/package-8 | 12737437 | 89.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobBoss/Faker_math-8 | 13494093 | 90.65 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobBoss/Faker_crypto-8 | 2671172 | 461.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftBiome/package-8 | 13233918 | 81.47 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftBiome/Faker_math-8 | 16109408 | 85.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftBiome/Faker_crypto-8 | 2205704 | 499.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeather/package-8 | 13371518 | 79.93 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeather/Faker_math-8 | 14987182 | 80.69 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeather/Faker_crypto-8 | 2373735 | 473.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBool/package-8 | 75772935 | 15.03 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBool/Faker_math-8 | 76893664 | 19.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBool/Faker_crypto-8 | 3141634 | 376.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkUUID/package-8 | 9382911 | 115.3 ns/op | 64 B/op | 2 allocs/op | +| BenchmarkUUID/Faker_math-8 | 9492183 | 114.1 ns/op | 64 B/op | 2 allocs/op | +| BenchmarkUUID/Faker_crypto-8 | 1000000 | 1039 ns/op | 64 B/op | 2 allocs/op | +| BenchmarkShuffleAnySlice/package-8 | 2234314 | 511.5 ns/op | 24 B/op | 1 allocs/op | \ No newline at end of file diff --git a/vendor/github.com/brianvoe/gofakeit/v6/README.md b/vendor/github.com/brianvoe/gofakeit/v6/README.md index 122b2331c..b42992d1d 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/README.md +++ b/vendor/github.com/brianvoe/gofakeit/v6/README.md @@ -1,24 +1,35 @@ ![alt text](https://raw.githubusercontent.com/brianvoe/gofakeit/master/logo.png) -# Gofakeit [![Go Report Card](https://goreportcard.com/badge/github.com/brianvoe/gofakeit)](https://goreportcard.com/report/github.com/brianvoe/gofakeit) ![Test](https://github.com/brianvoe/gofakeit/workflows/Test/badge.svg?branch=master) [![codecov.io](https://codecov.io/github/brianvoe/gofakeit/branch/master/graph/badge.svg)](https://codecov.io/github/brianvoe/gofakeit) [![GoDoc](https://godoc.org/github.com/brianvoe/gofakeit/v6?status.svg)](https://godoc.org/github.com/brianvoe/gofakeit/v6) [![license](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/brianvoe/gofakeit/master/LICENSE.txt) +# Gofakeit [![Go Report Card](https://goreportcard.com/badge/github.com/brianvoe/gofakeit)](https://goreportcard.com/report/github.com/brianvoe/gofakeit) ![Test](https://github.com/brianvoe/gofakeit/workflows/Test/badge.svg?branch=master) [![GoDoc](https://godoc.org/github.com/brianvoe/gofakeit/v6?status.svg)](https://godoc.org/github.com/brianvoe/gofakeit/v6) [![license](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/brianvoe/gofakeit/master/LICENSE.txt) Random data generator written in go +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G0R5EJT) + Buy Me A Coffee ## Features -- [160+ Functions!!!](#functions) +- [310+ Functions!!!](#functions) - [Random Sources](#random-sources) - [Global Rand](#global-rand-set) - [Struct Generator](#struct) - [Custom Functions](#custom-functions) +- [Templates](#templates) - [Http Server](https://github.com/brianvoe/gofakeit/tree/master/cmd/gofakeitserver) - [Command Line Tool](https://github.com/brianvoe/gofakeit/tree/master/cmd/gofakeit) - Zero dependencies - [Benchmarks](https://github.com/brianvoe/gofakeit/blob/master/BENCHMARKS.md) - [Issue](https://github.com/brianvoe/gofakeit/issues) +## Contributors + +Thank you to all our Gofakeit contributors! + + + + + ## Installation ```go @@ -101,7 +112,7 @@ gofakeit.SetGlobalFaker(faker) ## Struct Gofakeit can generate random data for struct fields. For the most part it covers all the basic type -as well as some non basic like time.Time. +as well as some non-basic like time.Time. Struct fields can also use tags to more specifically generate data for that field type. @@ -110,20 +121,22 @@ import "github.com/brianvoe/gofakeit/v6" // Create structs with random injected data type Foo struct { - Str string - Int int - Pointer *int - Name string `fake:"{firstname}"` // Any available function all lowercase - Sentence string `fake:"{sentence:3}"` // Can call with parameters - RandStr string `fake:"{randomstring:[hello,world]}"` - Number string `fake:"{number:1,10}"` // Comma separated for multiple values - Regex string `fake:"{regex:[abcdef]{5}}"` // Generate string from regex - Map map[string]int `fakesize:"2"` - Array []string `fakesize:"2"` - Bar Bar - Skip *string `fake:"skip"` // Set to "skip" to not generate data for - Created time.Time // Can take in a fake tag as well as a format tag - CreatedFormat time.Time `fake:"{year}-{month}-{day}" format:"2006-01-02"` + Str string + Int int + Pointer *int + Name string `fake:"{firstname}"` // Any available function all lowercase + Sentence string `fake:"{sentence:3}"` // Can call with parameters + RandStr string `fake:"{randomstring:[hello,world]}"` + Number string `fake:"{number:1,10}"` // Comma separated for multiple values + Regex string `fake:"{regex:[abcdef]{5}}"` // Generate string from regex + Map map[string]int `fakesize:"2"` + Array []string `fakesize:"2"` + ArrayRange []string `fakesize:"2,6"` + Bar Bar + Skip *string `fake:"skip"` // Set to "skip" to not generate data for + SkipAlt *string `fake:"-"` // Set to "-" to not generate data for + Created time.Time // Can take in a fake tag as well as a format tag + CreatedFormat time.Time `fake:"{year}-{month}-{day}" format:"2006-01-02"` } type Bar struct { @@ -157,12 +170,53 @@ fmt.Println(f.Created.String()) // 1908-12-07 04:14:25.685339029 +0000 UTC // bool, string, // array, pointers, map // time.Time // If setting time you can also set a format tag -// Nested Struct Fields and Embeded Fields +// Nested Struct Fields and Embedded Fields +``` + +## Fakeable types + +It is possible to extend a struct by implementing the `Fakeable` interface +in order to control the generation. + +For example, this is useful when it is not possible to modify the struct that you want to fake by adding struct tags to a field but you still need to be able to control the generation process. + +```go +// Custom string that you want to generate your own data for +// or just return a static value +type CustomString string + +func (c *CustomString) Fake(faker *gofakeit.Faker) (any, error) { + return CustomString("my custom string") +} + +// Imagine a CustomTime type that is needed to support a custom JSON Marshaler +type CustomTime time.Time + +func (c *CustomTime) Fake(faker *gofakeit.Faker) (any, error) { + return CustomTime(time.Now()) +} + +func (c *CustomTime) MarshalJSON() ([]byte, error) { + //... +} + +// This is the struct that we cannot modify to add struct tags +type NotModifiable struct { + Token string + Value CustomString + Creation *CustomTime +} + +var f NotModifiable +gofakeit.Struct(&f) +fmt.Printf("%s", f.Token) // yvqqdH +fmt.Printf("%s", f.Value) // my custom string +fmt.Printf("%s", f.Creation) // 2023-04-02 23:00:00 +0000 UTC m=+0.000000001 ``` ## Custom Functions -In a lot of sitations you may need to use your own random function usage for your specific needs. +In a lot of situations you may need to use your own random function usage for your specific needs. If you would like to extend the usage of struct tags, generate function, available usages in the gofakeit server or gofakeit command sub packages. You can do so via the AddFuncLookup. Each function has their own lookup, if @@ -170,33 +224,33 @@ you need more reference examples you can look at each files lookups. ```go // Simple -gofakeit.AddFuncLookup("friendname", Info{ +gofakeit.AddFuncLookup("friendname", gofakeit.Info{ Category: "custom", Description: "Random friend name", Example: "bill", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { - return RandomString([]string{"bill", "bob", "sally"}), nil + Generate: func(r *rand.Rand, m *gofakeit.MapParams, info *gofakeit.Info) (any, error) { + return gofakeit.RandomString([]string{"bill", "bob", "sally"}), nil }, }) // With Params -gofakeit.AddFuncLookup("jumbleword", Info{ +gofakeit.AddFuncLookup("jumbleword", gofakeit.Info{ Category: "jumbleword", - Description: "Take a word and jumple it up", + Description: "Take a word and jumble it up", Example: "loredlowlh", Output: "string", - Params: []Param{ + Params: []gofakeit.Param{ {Field: "word", Type: "string", Description: "Word you want to jumble"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *gofakeit.MapParams, info *gofakeit.Info) (any, error) { word, err := info.GetString(m, "word") if err != nil { return nil, err } split := strings.Split(word, "") - ShuffleStrings(split) + gofakeit.ShuffleStrings(split) return strings.Join(split, ""), nil }, }) @@ -212,19 +266,125 @@ fmt.Printf("%s", f.FriendName) // bill fmt.Printf("%s", f.JumbleWord) // loredlowlh ``` +## Templates + +Generate custom outputs using golang's template engine [https://pkg.go.dev/text/template](https://pkg.go.dev/text/template). + +We have added all the available functions to the template engine as well as some additional ones that are useful for template building. + +Additional Available Functions +```go +- ToUpper(s string) string // Make string upper case +- ToLower(s string) string // Make string lower case +- ToString(s any) // Convert to string +- ToDate(s string) time.Time // Convert string to date +- SpliceAny(args ...any) []any // Build a slice of anys, used with Weighted +- SpliceString(args ...string) []string // Build a slice of strings, used with Teams and RandomString +- SpliceUInt(args ...uint) []uint // Build a slice of uint, used with Dice and RandomUint +- SpliceInt(args ...int) []int // Build a slice of int, used with RandomInt +``` + +
+ Unavailable Gofakeit functions + +```go +// Any functions that dont have a return value +- AnythingThatReturnsVoid(): void + +// Not available to use in templates +- Template(co *TemplateOptions) ([]byte, error) +- RandomMapKey(mapI any) any +``` +
+ + +### Example Usages + +```go +import "github.com/brianvoe/gofakeit/v6" + +func main() { + // Accessing the Lines variable from within the template. + template := ` + Subject: {{RandomString (SliceString "Greetings" "Hello" "Hi")}} + + Dear {{LastName}}, + + {{RandomString (SliceString "Greetings!" "Hello there!" "Hi, how are you?")}} + + {{Paragraph 1 5 10 "\n\n"}} + + {{RandomString (SliceString "Warm regards" "Best wishes" "Sincerely")}} + {{$person:=Person}} + {{$person.FirstName}} {{$person.LastName}} + {{$person.Email}} + {{$person.Phone}} + ` + + value, err := gofakeit.Template(template, &TemplateOptions{Data: 5}) + + if err != nil { + fmt.Println(err) + } + + fmt.Println(string(value)) +} +``` + +Output: +```text +Subject: Hello + +Dear Krajcik, + +Greetings! + +Quia voluptatem voluptatem voluptatem. Quia voluptatem voluptatem voluptatem. Quia voluptatem voluptatem voluptatem. + +Warm regards +Kaitlyn Krajcik +kaitlynkrajcik@krajcik +570-245-7485 +``` + ## Functions All functions also exist as methods on the Faker struct ### File +Passing `nil` to `CSV`, `JSON` or `XML` will auto generate data using default values. + ```go +CSV(co *CSVOptions) ([]byte, error) JSON(jo *JSONOptions) ([]byte, error) XML(xo *XMLOptions) ([]byte, error) FileExtension() string FileMimeType() string ``` +### Template + +Passing `nil` will auto generate data using default values. + +```go +Template(co *TemplateOptions) (string, error) +Markdown(co *MarkdownOptions) (string, error) +EmailText(co *EmailOptions) (string, error) +FixedWidth(co *FixedWidthOptions) (string, error) +``` + +### Product + +```go +Product() *ProductInfo +ProductName() string +ProductDescription() string +ProductCategory() string +ProductFeature() string +ProductMaterial() string +``` + ### Person ```go @@ -233,6 +393,7 @@ Name() string NamePrefix() string NameSuffix() string FirstName() string +MiddleName() string LastName() string Gender() string SSN() string @@ -247,9 +408,9 @@ Teams(peopleArray []string, teamsArray []string) map[string][]string ### Generate ```go -Struct(v interface{}) -Slice(v interface{}) -Map() map[string]interface{} +Struct(v any) +Slice(v any) +Map() map[string]any Generate(value string) string Regex(value string) string ``` @@ -315,9 +476,8 @@ CarTransmissionType() string ### Words -#### Noun - ```go +// Nouns Noun() string NounCommon() string NounConcrete() string @@ -327,20 +487,14 @@ NounCollectiveAnimal() string NounCollectiveThing() string NounCountable() string NounUncountable() string -``` - -#### Verb -```go +// Verbs Verb() string VerbAction() string VerbLinking() string VerbHelping() string -``` -#### Adverb - -```go +// Adverbs Adverb() string AdverbManner() string AdverbDegree() string @@ -349,20 +503,14 @@ AdverbTimeDefinite() string AdverbTimeIndefinite() string AdverbFrequencyDefinite() string AdverbFrequencyIndefinite() string -``` - -#### Proposition -```go +// Propositions Preposition() string PrepositionSimple() string PrepositionDouble() string PrepositionCompound() string -``` - -#### Adjective -```go +// Adjectives Adjective() string AdjectiveDescriptive() string AdjectiveQuantitative() string @@ -371,24 +519,18 @@ AdjectiveDemonstrative() string AdjectivePossessive() string AdjectiveInterrogative() string AdjectiveIndefinite() string -``` -#### Pronoun - -```go +// Pronouns Pronoun() string PronounPersonal() string PronounObject() string -PronounPosessive() string +PronounPossessive() string PronounReflective() string PronounDemonstrative() string PronounInterrogative() string PronounRelative() string -``` -#### Connective - -```go +// Connectives Connective() string ConnectiveTime() string ConnectiveComparative() string @@ -396,17 +538,11 @@ ConnectiveComplaint() string ConnectiveListing() string ConnectiveCasual() string ConnectiveExamplify() string -``` - -#### Word -```go +// Words Word() string -``` - -#### Sentences -```go +// Sentences Sentence(wordCount int) string Paragraph(paragraphCount int, sentenceCount int, wordCount int, separator string) string LoremIpsumWord() string @@ -434,9 +570,10 @@ Dessert() string ```go Bool() bool UUID() string +Weighted(options []any, weights []float32) (any, error) FlipACoin() string -RandomMapKey(mapI interface{}) interface{} -ShuffleAnySlice(v interface{}) +RandomMapKey(mapI any) any +ShuffleAnySlice(v any) ``` ### Colors @@ -446,6 +583,16 @@ Color() string HexColor() string RGBColor() []int SafeColor() string +NiceColors() string +``` + +### Images + +```go +ImageURL(width int, height int) string +Image(width int, height int) *img.RGBA +ImageJpeg(width int, height int) []byte +ImagePng(width int, height int) []byte ``` ### Internet @@ -469,10 +616,19 @@ OperaUserAgent() string SafariUserAgent() string ``` +### HTML + +```go +InputName() string +Svg(options *SVGOptions) string +``` + ### Date/Time ```go Date() time.Time +PastDate() time.Time +FutureDate() time.Time DateRange(start, end time.Time) time.Time NanoSecond() int Second() int @@ -508,10 +664,18 @@ BitcoinAddress() string BitcoinPrivateKey() string ``` +### Finance + +```go +Cusip() string +Isin() string +``` + ### Company ```go BS() string +Blurb() string BuzzWord() string Company() string CompanySuffix() string @@ -519,6 +683,7 @@ Job() *JobInfo JobDescriptor() string JobLevel() string JobTitle() string +Slogan() string ``` ### Hacker @@ -557,6 +722,7 @@ AnimalType() string FarmAnimal() string Cat() string Dog() string +Bird() string ``` ### Emoji @@ -647,3 +813,39 @@ MinecraftMobBoss() string MinecraftBiome() string MinecraftWeather() string ``` + +### Book + +```go +Book() *BookInfo +BookTitle() string +BookAuthor() string +BookGenre() string +``` + +### Movie + +```go +Movie() *MovieInfo +MovieName() string +MovieGenre() string +``` + +### Error + +```go +Error() error +ErrorDatabase() error +ErrorGRPC() error +ErrorHTTP() error +ErrorHTTPClient() error +ErrorHTTPServer() error +ErrorInput() error +ErrorRuntime() error +``` + +### School + +```go +School() string +``` diff --git a/vendor/github.com/brianvoe/gofakeit/v6/address.go b/vendor/github.com/brianvoe/gofakeit/v6/address.go index 6a6b36f78..3c8bc96fe 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/address.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/address.go @@ -52,9 +52,9 @@ func street(r *rand.Rand) string { var street = "" switch randInt := randIntRange(r, 1, 2); randInt { case 1: - street = streetNumber(r) + " " + streetPrefix(r) + " " + streetName(r) + " " + streetSuffix(r) + street = streetNumber(r) + " " + streetPrefix(r) + " " + streetName(r) + streetSuffix(r) case 2: - street = streetNumber(r) + " " + streetName(r) + " " + streetSuffix(r) + street = streetNumber(r) + " " + streetName(r) + streetSuffix(r) } return street @@ -198,20 +198,20 @@ func addAddressLookup() { AddFuncLookup("address", Info{ Display: "Address", Category: "address", - Description: "Random set of address info", + Description: "Residential location including street, city, state, country and postal code", Example: `{ - address: "364 East Rapidsborough, Rutherfordstad, New Jersey 36906", - street: "364 East Rapidsborough", - city: "Rutherfordstad", - state: "New Jersey", - zip: "36906", - country: "South Africa", - latitude: "23.058758", - longitude: "89.022594" - }`, - Output: "map[string]interface", + "address": "364 Unionsville, Norfolk, Ohio 99536", + "street": "364 Unionsville", + "city": "Norfolk", + "state": "Ohio", + "zip": "99536", + "country": "Lesotho", + "latitude": 88.792592, + "longitude": 174.504681 +}`, + Output: "map[string]any", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return address(r), nil }, }) @@ -219,10 +219,10 @@ func addAddressLookup() { AddFuncLookup("city", Info{ Display: "City", Category: "address", - Description: "Random city", + Description: "Part of a country with significant population, often a central hub for culture and commerce", Example: "Marcelside", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return city(r), nil }, }) @@ -230,10 +230,10 @@ func addAddressLookup() { AddFuncLookup("country", Info{ Display: "Country", Category: "address", - Description: "Random country", + Description: "Nation with its own government and defined territory", Example: "United States of America", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return country(r), nil }, }) @@ -241,10 +241,10 @@ func addAddressLookup() { AddFuncLookup("countryabr", Info{ Display: "Country Abbreviation", Category: "address", - Description: "Random 2 digit country abbreviation", + Description: "Shortened 2-letter form of a country's name", Example: "US", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return countryAbr(r), nil }, }) @@ -252,10 +252,10 @@ func addAddressLookup() { AddFuncLookup("state", Info{ Display: "State", Category: "address", - Description: "Random state", + Description: "Governmental division within a country, often having its own laws and government", Example: "Illinois", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return state(r), nil }, }) @@ -263,10 +263,10 @@ func addAddressLookup() { AddFuncLookup("stateabr", Info{ Display: "State Abbreviation", Category: "address", - Description: "Random 2 digit state abbreviation", + Description: "Shortened 2-letter form of a country's state", Example: "IL", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return stateAbr(r), nil }, }) @@ -274,10 +274,10 @@ func addAddressLookup() { AddFuncLookup("street", Info{ Display: "Street", Category: "address", - Description: "Random full street", + Description: "Public road in a city or town, typically with houses and buildings on each side", Example: "364 East Rapidsborough", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return street(r), nil }, }) @@ -285,10 +285,10 @@ func addAddressLookup() { AddFuncLookup("streetname", Info{ Display: "Street Name", Category: "address", - Description: "Random street name", + Description: "Name given to a specific road or street", Example: "View", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetName(r), nil }, }) @@ -296,10 +296,10 @@ func addAddressLookup() { AddFuncLookup("streetnumber", Info{ Display: "Street Number", Category: "address", - Description: "Random street number", + Description: "Numerical identifier assigned to a street", Example: "13645", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetNumber(r), nil }, }) @@ -307,10 +307,10 @@ func addAddressLookup() { AddFuncLookup("streetprefix", Info{ Display: "Street Prefix", Category: "address", - Description: "Random street prefix", + Description: "Directional or descriptive term preceding a street name, like 'East' or 'Main'", Example: "Lake", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetPrefix(r), nil }, }) @@ -318,10 +318,10 @@ func addAddressLookup() { AddFuncLookup("streetsuffix", Info{ Display: "Street Suffix", Category: "address", - Description: "Random street suffix", + Description: "Designation at the end of a street name indicating type, like 'Avenue' or 'Street'", Example: "land", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetSuffix(r), nil }, }) @@ -329,10 +329,10 @@ func addAddressLookup() { AddFuncLookup("zip", Info{ Display: "Zip", Category: "address", - Description: "Random street zip", + Description: "Numerical code for postal address sorting, specific to a geographic area", Example: "13645", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return zip(r), nil }, }) @@ -340,10 +340,10 @@ func addAddressLookup() { AddFuncLookup("latitude", Info{ Display: "Latitude", Category: "address", - Description: "Random latitude", + Description: "Geographic coordinate specifying north-south position on Earth's surface", Example: "-73.534056", Output: "float", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return latitude(r), nil }, }) @@ -351,14 +351,14 @@ func addAddressLookup() { AddFuncLookup("latituderange", Info{ Display: "Latitude Range", Category: "address", - Description: "Random latitude between given range", + Description: "Latitude number between the given range (default min=0, max=90)", Example: "22.921026", Output: "float", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Default: "0", Description: "Minimum range"}, {Field: "max", Display: "Max", Type: "float", Default: "90", Description: "Maximum range"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err @@ -381,10 +381,10 @@ func addAddressLookup() { AddFuncLookup("longitude", Info{ Display: "Longitude", Category: "address", - Description: "Random longitude", + Description: "Geographic coordinate indicating east-west position on Earth's surface", Example: "-147.068112", Output: "float", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return longitude(r), nil }, }) @@ -392,14 +392,14 @@ func addAddressLookup() { AddFuncLookup("longituderange", Info{ Display: "Longitude Range", Category: "address", - Description: "Random longitude between given range", + Description: "Longitude number between the given range (default min=0, max=180)", Example: "-8.170450", Output: "float", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Default: "0", Description: "Minimum range"}, {Field: "max", Display: "Max", Type: "float", Default: "180", Description: "Maximum range"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/animal.go b/vendor/github.com/brianvoe/gofakeit/v6/animal.go index fd30b5f00..56772ea98 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/animal.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/animal.go @@ -86,14 +86,28 @@ func dog(r *rand.Rand) string { return getRandValue(r, []string{"animal", "dog"}) } +// Bird will return a random bird species +func Bird() string { + return bird(globalFaker.Rand) +} + +// Bird will return a random bird species +func (f *Faker) Bird() string { + return bird(f.Rand) +} + +func bird(r *rand.Rand) string { + return getRandValue(r, []string{"animal", "bird"}) +} + func addAnimalLookup() { AddFuncLookup("petname", Info{ Display: "Pet Name", Category: "animal", - Description: "Random pet name", + Description: "Affectionate nickname given to a pet", Example: "Ozzy Pawsborne", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return petName(r), nil }, }) @@ -101,10 +115,10 @@ func addAnimalLookup() { AddFuncLookup("animal", Info{ Display: "Animal", Category: "animal", - Description: "Random animal", + Description: "Living creature with the ability to move, eat, and interact with its environment", Example: "elk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return animal(r), nil }, }) @@ -112,10 +126,10 @@ func addAnimalLookup() { AddFuncLookup("animaltype", Info{ Display: "Animal Type", Category: "animal", - Description: "Random animal type", + Description: "Type of animal, such as mammals, birds, reptiles, etc.", Example: "amphibians", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return animalType(r), nil }, }) @@ -123,10 +137,10 @@ func addAnimalLookup() { AddFuncLookup("farmanimal", Info{ Display: "Farm Animal", Category: "animal", - Description: "Random farm animal", + Description: "Animal name commonly found on a farm", Example: "Chicken", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return farmAnimal(r), nil }, }) @@ -134,10 +148,10 @@ func addAnimalLookup() { AddFuncLookup("cat", Info{ Display: "Cat", Category: "animal", - Description: "Random cat type", + Description: "Various breeds that define different cats", Example: "Chausie", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return cat(r), nil }, }) @@ -145,11 +159,22 @@ func addAnimalLookup() { AddFuncLookup("dog", Info{ Display: "Dog", Category: "animal", - Description: "Random dog type", + Description: "Various breeds that define different dogs", Example: "Norwich Terrier", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return dog(r), nil }, }) + + AddFuncLookup("bird", Info{ + Display: "Bird", + Category: "animal", + Description: "Distinct species of birds", + Example: "goose", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return bird(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/app.go b/vendor/github.com/brianvoe/gofakeit/v6/app.go index 195d4b4df..172c81798 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/app.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/app.go @@ -65,10 +65,10 @@ func addAppLookup() { AddFuncLookup("appname", Info{ Display: "App Name", Category: "app", - Description: "Random app name", + Description: "Software program designed for a specific purpose or task on a computer or mobile device", Example: "Parkrespond", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return appName(r), nil }, }) @@ -76,10 +76,10 @@ func addAppLookup() { AddFuncLookup("appversion", Info{ Display: "App Version", Category: "app", - Description: "Random app version", + Description: "Particular release of an application in Semantic Versioning format", Example: "1.12.14", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return appVersion(r), nil }, }) @@ -87,10 +87,10 @@ func addAppLookup() { AddFuncLookup("appauthor", Info{ Display: "App Author", Category: "app", - Description: "Random app author", + Description: "Person or group creating and developing an application", Example: "Qado Energy, Inc.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return appAuthor(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/auth.go b/vendor/github.com/brianvoe/gofakeit/v6/auth.go index ab7631eeb..ae86e3d11 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/auth.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/auth.go @@ -33,45 +33,56 @@ func password(r *rand.Rand, lower bool, upper bool, numeric bool, special bool, if num < 5 { num = 5 } - i := 0 - b := make([]byte, num) - var passString string + // Setup weights + items := make([]any, 0) + weights := make([]float32, 0) if lower { - passString += lowerStr - b[i] = lowerStr[r.Int63()%int64(len(lowerStr))] - i++ + items = append(items, "lower") + weights = append(weights, 4) } if upper { - passString += upperStr - b[i] = upperStr[r.Int63()%int64(len(upperStr))] - i++ + items = append(items, "upper") + weights = append(weights, 4) } if numeric { - passString += numericStr - b[i] = numericStr[r.Int63()%int64(len(numericStr))] - i++ + items = append(items, "numeric") + weights = append(weights, 3) } if special { - passString += specialStr - b[i] = specialStr[r.Int63()%int64(len(specialStr))] - i++ + items = append(items, "special") + weights = append(weights, 2) } if space { - passString += spaceStr - b[i] = spaceStr[r.Int63()%int64(len(spaceStr))] - i++ + items = append(items, "space") + weights = append(weights, 1) } - // Set default if empty - if passString == "" { - passString = lowerStr + numericStr + // If no items are selected then default to lower, upper, numeric + if len(items) == 0 { + items = append(items, "lower", "upper", "numeric") + weights = append(weights, 4, 4, 3) } - // Loop through and add it up - for i <= num-1 { - b[i] = passString[r.Int63()%int64(len(passString))] - i++ + // Create byte slice + b := make([]byte, num) + + for i := 0; i <= num-1; i++ { + // Run weighted + weight, _ := weighted(r, items, weights) + + switch weight.(string) { + case "lower": + b[i] = lowerStr[r.Int63()%int64(len(lowerStr))] + case "upper": + b[i] = upperStr[r.Int63()%int64(len(upperStr))] + case "numeric": + b[i] = numericStr[r.Int63()%int64(len(numericStr))] + case "special": + b[i] = specialSafeStr[r.Int63()%int64(len(specialSafeStr))] + case "space": + b[i] = spaceStr[r.Int63()%int64(len(spaceStr))] + } } // Shuffle bytes @@ -80,6 +91,14 @@ func password(r *rand.Rand, lower bool, upper bool, numeric bool, special bool, b[i], b[j] = b[j], b[i] } + // Replace first or last character if it's a space, and other options are available + if b[0] == ' ' { + b[0] = password(r, lower, upper, numeric, special, false, 1)[0] + } + if b[len(b)-1] == ' ' { + b[len(b)-1] = password(r, lower, upper, numeric, special, false, 1)[0] + } + return string(b) } @@ -87,10 +106,10 @@ func addAuthLookup() { AddFuncLookup("username", Info{ Display: "Username", Category: "auth", - Description: "Generates a random username", + Description: "Unique identifier assigned to a user for accessing an account or system", Example: "Daniel1364", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return username(r), nil }, }) @@ -98,7 +117,7 @@ func addAuthLookup() { AddFuncLookup("password", Info{ Display: "Password", Category: "auth", - Description: "Generates a random password", + Description: "Secret word or phrase used to authenticate access to a system or account", Example: "EEP+wwpk 4lU-eHNXlJZ4n K9%v&TZ9e", Output: "string", Params: []Param{ @@ -109,7 +128,7 @@ func addAuthLookup() { {Field: "space", Display: "Space", Type: "bool", Default: "false", Description: "Whether or not to add spaces"}, {Field: "length", Display: "Length", Type: "int", Default: "12", Description: "Number of characters in password"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { lower, err := info.GetBool(m, "lower") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/beer.go b/vendor/github.com/brianvoe/gofakeit/v6/beer.go index d245fcbe3..292ae6803 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/beer.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/beer.go @@ -121,10 +121,10 @@ func addBeerLookup() { AddFuncLookup("beername", Info{ Display: "Beer Name", Category: "beer", - Description: "Random beer name", + Description: "Specific brand or variety of beer", Example: "Duvel", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerName(r), nil }, }) @@ -132,10 +132,10 @@ func addBeerLookup() { AddFuncLookup("beerstyle", Info{ Display: "Beer Style", Category: "beer", - Description: "Random beer style", + Description: "Distinct characteristics and flavors of beer", Example: "European Amber Lager", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerStyle(r), nil }, }) @@ -143,10 +143,10 @@ func addBeerLookup() { AddFuncLookup("beerhop", Info{ Display: "Beer Hop", Category: "beer", - Description: "Random beer hop type", + Description: "The flower used in brewing to add flavor, aroma, and bitterness to beer", Example: "Glacier", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerHop(r), nil }, }) @@ -154,10 +154,10 @@ func addBeerLookup() { AddFuncLookup("beeryeast", Info{ Display: "Beer Yeast", Category: "beer", - Description: "Random beer yeast value", + Description: "Microorganism used in brewing to ferment sugars, producing alcohol and carbonation in beer", Example: "1388 - Belgian Strong Ale", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerYeast(r), nil }, }) @@ -165,10 +165,10 @@ func addBeerLookup() { AddFuncLookup("beermalt", Info{ Display: "Beer Malt", Category: "beer", - Description: "Random beer malt", + Description: "Processed barley or other grains, provides sugars for fermentation and flavor to beer", Example: "Munich", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerMalt(r), nil }, }) @@ -176,10 +176,10 @@ func addBeerLookup() { AddFuncLookup("beeralcohol", Info{ Display: "Beer Alcohol", Category: "beer", - Description: "Random alcohol percentage", + Description: "Measures the alcohol content in beer", Example: "2.7%", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerAlcohol(r), nil }, }) @@ -187,10 +187,10 @@ func addBeerLookup() { AddFuncLookup("beeribu", Info{ Display: "Beer IBU", Category: "beer", - Description: "Random beer ibu", + Description: "Scale measuring bitterness of beer from hops", Example: "29 IBU", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerIbu(r), nil }, }) @@ -198,10 +198,10 @@ func addBeerLookup() { AddFuncLookup("beerblg", Info{ Display: "Beer BLG", Category: "beer", - Description: "Random beer blg", + Description: "Scale indicating the concentration of extract in worts", Example: "6.4°Blg", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerBlg(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/car.go b/vendor/github.com/brianvoe/gofakeit/v6/car.go index 8b0581600..983e2576c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/car.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/car.go @@ -75,11 +75,18 @@ func addCarLookup() { AddFuncLookup("car", Info{ Display: "Car", Category: "car", - Description: "Random car set of data", - Output: "map[string]interface", + Description: "Wheeled motor vehicle used for transportation", + Example: `{ + "type": "Passenger car mini", + "fuel": "Gasoline", + "transmission": "Automatic", + "brand": "Fiat", + "model": "Freestyle Fwd", + "year": 1991 +}`, + Output: "map[string]any", ContentType: "application/json", - Example: `{type: "Passenger car mini", fuel: "Gasoline", transmission: "Automatic", brand: "Fiat", model: "Freestyle Fwd", year: "1972"}`, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return car(r), nil }, }) @@ -87,10 +94,10 @@ func addCarLookup() { AddFuncLookup("cartype", Info{ Display: "Car Type", Category: "car", - Description: "Random car type", + Description: "Classification of cars based on size, use, or body style", Example: "Passenger car mini", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carType(r), nil }, }) @@ -98,10 +105,10 @@ func addCarLookup() { AddFuncLookup("carfueltype", Info{ Display: "Car Fuel Type", Category: "car", - Description: "Random car fuel type", + Description: "Type of energy source a car uses", Example: "CNG", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carFuelType(r), nil }, }) @@ -109,10 +116,10 @@ func addCarLookup() { AddFuncLookup("cartransmissiontype", Info{ Display: "Car Transmission Type", Category: "car", - Description: "Random car transmission type", + Description: "Mechanism a car uses to transmit power from the engine to the wheels", Example: "Manual", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carTransmissionType(r), nil }, }) @@ -120,10 +127,10 @@ func addCarLookup() { AddFuncLookup("carmaker", Info{ Display: "Car Maker", Category: "car", - Description: "Random car maker", + Description: "Company or brand that manufactures and designs cars", Example: "Nissan", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carMaker(r), nil }, }) @@ -131,10 +138,10 @@ func addCarLookup() { AddFuncLookup("carmodel", Info{ Display: "Car Model", Category: "car", - Description: "Random car model", + Description: "Specific design or version of a car produced by a manufacturer", Example: "Aveo", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carModel(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go b/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go index 36a0c8336..d7400f80a 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go @@ -32,10 +32,10 @@ func addCelebrityLookup() { AddFuncLookup("celebrityactor", Info{ Display: "Celebrity Actor", Category: "celebrity", - Description: "Random celebrity actor", + Description: "Famous person known for acting in films, television, or theater", Example: "Brad Pitt", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return celebrityActor(r), nil }, }) @@ -43,10 +43,10 @@ func addCelebrityLookup() { AddFuncLookup("celebritybusiness", Info{ Display: "Celebrity Business", Category: "celebrity", - Description: "Random celebrity business person", + Description: "High-profile individual known for significant achievements in business or entrepreneurship", Example: "Elon Musk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return celebrityBusiness(r), nil }, }) @@ -54,10 +54,10 @@ func addCelebrityLookup() { AddFuncLookup("celebritysport", Info{ Display: "Celebrity Sport", Category: "celebrity", - Description: "Random celebrity sport person", + Description: "Famous athlete known for achievements in a particular sport", Example: "Michael Phelps", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return celebritySport(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/color.go b/vendor/github.com/brianvoe/gofakeit/v6/color.go index 8e46e9594..dce7db5f3 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/color.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/color.go @@ -1,6 +1,10 @@ package gofakeit -import "math/rand" +import ( + "math/rand" + + "github.com/brianvoe/gofakeit/v6/data" +) // Color will generate a random color string func Color() string { return color(globalFaker.Rand) } @@ -10,6 +14,16 @@ func (f *Faker) Color() string { return color(f.Rand) } func color(r *rand.Rand) string { return getRandValue(r, []string{"color", "full"}) } +// NiceColor will generate a random safe color string +func NiceColors() []string { return niceColors(globalFaker.Rand) } + +// NiceColor will generate a random safe color string +func (f *Faker) NiceColors() []string { return niceColors(f.Rand) } + +func niceColors(r *rand.Rand) []string { + return data.ColorsNice[randIntRange(r, 0, len(data.ColorsNice)-1)] +} + // SafeColor will generate a random safe color string func SafeColor() string { return safeColor(globalFaker.Rand) } @@ -48,10 +62,22 @@ func addColorLookup() { AddFuncLookup("color", Info{ Display: "Color", Category: "color", - Description: "Random color", + Description: "Hue seen by the eye, returns the name of the color like red or blue", Example: "MediumOrchid", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return color(r), nil + }, + }) + + AddFuncLookup("nicecolors", Info{ + Display: "Nice Colors", + Category: "color", + Description: "Attractive and appealing combinations of colors, returns an list of color hex codes", + Example: `["#cfffdd","#b4dec1","#5c5863","#a85163","#ff1f4c"]`, + Output: "[]string", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return color(r), nil }, }) @@ -59,10 +85,10 @@ func addColorLookup() { AddFuncLookup("safecolor", Info{ Display: "Safe Color", Category: "color", - Description: "Random safe color", + Description: "Colors displayed consistently on different web browsers and devices", Example: "black", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return safeColor(r), nil }, }) @@ -70,10 +96,10 @@ func addColorLookup() { AddFuncLookup("hexcolor", Info{ Display: "Hex Color", Category: "color", - Description: "Random hex color", + Description: "Six-digit code representing a color in the color model", Example: "#a99fb4", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexColor(r), nil }, }) @@ -81,10 +107,11 @@ func addColorLookup() { AddFuncLookup("rgbcolor", Info{ Display: "RGB Color", Category: "color", - Description: "Random rgb color", - Example: "[152 23 53]", - Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Description: "Color defined by red, green, and blue light values", + Example: "[85, 224, 195]", + Output: "[]int", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return rgbColor(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/company.go b/vendor/github.com/brianvoe/gofakeit/v6/company.go index 32a328346..ea8af6ca0 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/company.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/company.go @@ -18,6 +18,13 @@ func (f *Faker) CompanySuffix() string { return companySuffix(f.Rand) } func companySuffix(r *rand.Rand) string { return getRandValue(r, []string{"company", "suffix"}) } +// Blurb will generate a random company blurb string +func Blurb() string { return blurb(globalFaker.Rand) } + +func (f *Faker) Blurb() string { return blurb(f.Rand) } + +func blurb(r *rand.Rand) string { return getRandValue(r, []string{"company", "blurb"}) } + // BuzzWord will generate a random company buzz word string func BuzzWord() string { return buzzWord(globalFaker.Rand) } @@ -81,14 +88,38 @@ func (f *Faker) JobLevel() string { return jobLevel(f.Rand) } func jobLevel(r *rand.Rand) string { return getRandValue(r, []string{"job", "level"}) } +// Slogan will generate a random company slogan +func Slogan() string { return slogan(globalFaker.Rand) } + +// Slogan will generate a random company slogan +func (f *Faker) Slogan() string { return slogan(f.Rand) } + +// Slogan will generate a random company slogan +func slogan(r *rand.Rand) string { + slogan := "" + var sloganStyle = number(r, 0, 2) + switch sloganStyle { + // Noun. Buzzword! + case 0: + slogan = getRandValue(r, []string{"company", "blurb"}) + ". " + getRandValue(r, []string{"company", "buzzwords"}) + "!" + // Buzzword Noun, Buzzword Noun. + case 1: + slogan = getRandValue(r, []string{"company", "buzzwords"}) + " " + getRandValue(r, []string{"company", "blurb"}) + ", " + getRandValue(r, []string{"company", "buzzwords"}) + " " + getRandValue(r, []string{"company", "blurb"}) + "." + // Buzzword bs Noun, Buzzword. + case 2: + slogan = getRandValue(r, []string{"company", "buzzwords"}) + " " + getRandValue(r, []string{"company", "bs"}) + " " + getRandValue(r, []string{"company", "blurb"}) + ", " + getRandValue(r, []string{"company", "buzzwords"}) + "." + } + return slogan +} + func addCompanyLookup() { AddFuncLookup("company", Info{ Display: "Company", Category: "company", - Description: "Random company name", + Description: "Designated official name of a business or organization", Example: "Moen, Pagac and Wuckert", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return company(r), nil }, }) @@ -96,10 +127,10 @@ func addCompanyLookup() { AddFuncLookup("companysuffix", Info{ Display: "Company Suffix", Category: "company", - Description: "Random company name suffix", + Description: "Suffix at the end of a company name, indicating business structure, like 'Inc.' or 'LLC'", Example: "Inc", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return companySuffix(r), nil }, }) @@ -110,18 +141,29 @@ func addCompanyLookup() { Description: "Random bs company word", Example: "front-end", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return bs(r), nil }, }) + AddFuncLookup("blurb", Info{ + Display: "Blurb", + Category: "company", + Description: "Brief description or summary of a company's purpose, products, or services", + Example: "word", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return blurb(r), nil + }, + }) + AddFuncLookup("buzzword", Info{ Display: "Buzzword", Category: "company", - Description: "Random company buzzwords", + Description: "Trendy or overused term often used in business to sound impressive", Example: "disintermediate", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return buzzWord(r), nil }, }) @@ -129,10 +171,16 @@ func addCompanyLookup() { AddFuncLookup("job", Info{ Display: "Job", Category: "company", - Description: "Random job data set", - Example: `{company: "Moen, Pagac and Wuckert", title: "Director", descriptor: "Central", level: "Assurance"}`, + Description: "Position or role in employment, involving specific tasks and responsibilities", + Example: `{ + "company": "ClearHealthCosts", + "title": "Agent", + "descriptor": "Future", + "level": "Tactics" +}`, Output: "map[string]string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return job(r), nil }, }) @@ -140,10 +188,10 @@ func addCompanyLookup() { AddFuncLookup("jobtitle", Info{ Display: "Job Title", Category: "company", - Description: "Random job title", + Description: "Specific title for a position or role within a company or organization", Example: "Director", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return jobTitle(r), nil }, }) @@ -151,10 +199,10 @@ func addCompanyLookup() { AddFuncLookup("jobdescriptor", Info{ Display: "Job Descriptor", Category: "company", - Description: "Random job descriptor", + Description: "Word used to describe the duties, requirements, and nature of a job", Example: "Central", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return jobDescriptor(r), nil }, }) @@ -165,8 +213,19 @@ func addCompanyLookup() { Description: "Random job level", Example: "Assurance", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return jobLevel(r), nil }, }) + + AddFuncLookup("slogan", Info{ + Display: "Slogan", + Category: "company", + Description: "Catchphrase or motto used by a company to represent its brand or values", + Example: "Universal seamless Focus, interactive.", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return slogan(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/csv.go b/vendor/github.com/brianvoe/gofakeit/v6/csv.go index 0057d5d7e..6a2310ef6 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/csv.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/csv.go @@ -13,18 +13,28 @@ import ( // CSVOptions defines values needed for csv generation type CSVOptions struct { - Delimiter string `json:"delimiter" xml:"delimiter"` - RowCount int `json:"row_count" xml:"row_count"` - Fields []Field `json:"fields" xml:"fields"` + Delimiter string `json:"delimiter" xml:"delimiter" fake:"{randomstring:[,,tab]}"` + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } // CSV generates an object or an array of objects in json format -func CSV(co *CSVOptions) ([]byte, error) { return csvFunc(globalFaker.Rand, co) } +// A nil CSVOptions returns a randomly structured CSV. +func CSV(co *CSVOptions) ([]byte, error) { return csvFunc(globalFaker, co) } // CSV generates an object or an array of objects in json format -func (f *Faker) CSV(co *CSVOptions) ([]byte, error) { return csvFunc(f.Rand, co) } +// A nil CSVOptions returns a randomly structured CSV. +func (f *Faker) CSV(co *CSVOptions) ([]byte, error) { return csvFunc(f, co) } + +func csvFunc(f *Faker, co *CSVOptions) ([]byte, error) { + if co == nil { + // We didn't get a CSVOptions, so create a new random one + err := f.Struct(&co) + if err != nil { + return nil, err + } + } -func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { // Check delimiter if co.Delimiter == "" { co.Delimiter = "," @@ -32,7 +42,7 @@ func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { if strings.ToLower(co.Delimiter) == "tab" { co.Delimiter = "\t" } - if co.Delimiter != "," && co.Delimiter != "\t" { + if co.Delimiter != "," && co.Delimiter != "\t" && co.Delimiter != ";" { return nil, errors.New("invalid delimiter type") } @@ -61,7 +71,7 @@ func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { for i := 1; i < co.RowCount+1; i++ { vr := make([]string, len(co.Fields)) - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for ii, field := range co.Fields { if field.Function == "autoincrement" { vr[ii] = fmt.Sprintf("%d", i) @@ -74,14 +84,14 @@ func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { return nil, errors.New("invalid function, " + field.Function + " does not exist") } - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } if _, ok := value.([]byte); ok { // If it's a slice of bytes or struct, unmarshal it into an interface - var v interface{} + var v any if err := json.Unmarshal(value.([]byte), &v); err != nil { return nil, err } @@ -119,22 +129,26 @@ func addFileCSVLookup() { AddFuncLookup("csv", Info{ Display: "CSV", Category: "file", - Description: "Generates array of rows in csv format", - Example: ` - id,first_name,last_name,password - 1,Markus,Moen,Dc0VYXjkWABx - 2,Osborne,Hilll,XPJ9OVNbs5lm - `, + Description: "Individual lines or data entries within a CSV (Comma-Separated Values) format", + Example: `id,first_name,last_name,password +1,Markus,Moen,Dc0VYXjkWABx +2,Osborne,Hilll,XPJ9OVNbs5lm`, Output: "[]byte", ContentType: "text/csv", Params: []Param{ + {Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows"}, {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function"}, - {Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { co := CSVOptions{} + delimiter, err := info.GetString(m, "delimiter") + if err != nil { + return nil, err + } + co.Delimiter = delimiter + rowcount, err := info.GetInt(m, "rowcount") if err != nil { return nil, err @@ -159,13 +173,8 @@ func addFileCSVLookup() { } } - delimiter, err := info.GetString(m, "delimiter") - if err != nil { - return nil, err - } - co.Delimiter = delimiter - - csvOut, err := csvFunc(r, &co) + f := &Faker{Rand: r} + csvOut, err := csvFunc(f, &co) if err != nil { return nil, err } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/address.go b/vendor/github.com/brianvoe/gofakeit/v6/data/address.go index 64c7fd511..98d88e821 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/address.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/address.go @@ -6,7 +6,7 @@ var Address = map[string][]string{ "street_prefix": {"North", "East", "West", "South", "New", "Lake", "Port"}, "street_name": {"Alley", "Avenue", "Branch", "Bridge", "Brook", "Brooks", "Burg", "Burgs", "Bypass", "Camp", "Canyon", "Cape", "Causeway", "Center", "Centers", "Circle", "Circles", "Cliff", "Cliffs", "Club", "Common", "Corner", "Corners", "Course", "Court", "Courts", "Cove", "Coves", "Creek", "Crescent", "Crest", "Crossing", "Crossroad", "Curve", "Dale", "Dam", "Divide", "Drive", "Drive", "Drives", "Estate", "Estates", "Expressway", "Extension", "Extensions", "Fall", "Falls", "Ferry", "Field", "Fields", "Flat", "Flats", "Ford", "Fords", "Forest", "Forge", "Forges", "Fork", "Forks", "Fort", "Freeway", "Garden", "Gardens", "Gateway", "Glen", "Glens", "Green", "Greens", "Grove", "Groves", "Harbor", "Harbors", "Haven", "Heights", "Highway", "Hill", "Hills", "Hollow", "Inlet", "Inlet", "Island", "Island", "Islands", "Islands", "Isle", "Isle", "Junction", "Junctions", "Key", "Keys", "Knoll", "Knolls", "Lake", "Lakes", "Land", "Landing", "Lane", "Light", "Lights", "Loaf", "Lock", "Locks", "Locks", "Lodge", "Lodge", "Loop", "Mall", "Manor", "Manors", "Meadow", "Meadows", "Mews", "Mill", "Mills", "Mission", "Mission", "Motorway", "Mount", "Mountain", "Mountain", "Mountains", "Mountains", "Neck", "Orchard", "Oval", "Overpass", "Park", "Parks", "Parkway", "Parkways", "Pass", "Passage", "Path", "Pike", "Pine", "Pines", "Place", "Plain", "Plains", "Plains", "Plaza", "Plaza", "Point", "Points", "Port", "Port", "Ports", "Ports", "Prairie", "Prairie", "Radial", "Ramp", "Ranch", "Rapid", "Rapids", "Rest", "Ridge", "Ridges", "River", "Road", "Road", "Roads", "Roads", "Route", "Row", "Rue", "Run", "Shoal", "Shoals", "Shore", "Shores", "Skyway", "Spring", "Springs", "Springs", "Spur", "Spurs", "Square", "Square", "Squares", "Squares", "Station", "Station", "Stravenue", "Stravenue", "Stream", "Stream", "Street", "Street", "Streets", "Summit", "Summit", "Terrace", "Throughway", "Trace", "Track", "Trafficway", "Trail", "Trail", "Tunnel", "Tunnel", "Turnpike", "Turnpike", "Underpass", "Union", "Unions", "Valley", "Valleys", "Via", "Viaduct", "View", "Views", "Village", "Village", "Villages", "Ville", "Vista", "Vista", "Walk", "Walks", "Wall", "Way", "Ways", "Well", "Wells"}, "street_suffix": {"town", "ton", "land", "ville", "berg", "burgh", "borough", "bury", "view", "port", "mouth", "stad", "furt", "chester", "mouth", "fort", "haven", "side", "shire"}, - "city": {"New York City", "Los Angeles", "Chicago", "Houston", "Philadelphia", "Phoenix", "San Antonio", "San Diego", "Dallas", "San Jose", "Austin", "Jacksonville", "Indianapolis", "San Francisco", "Columbus", "Fort Worth", "Charlotte", "Detroit", "El Paso", "Memphis", "Boston", "Seattle", "Denver", "Washington", "Nashville-Davidson", "Baltimore", "Louisville/Jefferson", "Portland", "Oklahoma ", "Milwaukee", "Las Vegas", "Albuquerque", "Tucson", "Fresno", "Sacramento", "Long Beach", "Kansas ", "Mesa", "Virginia Beach", "Atlanta", "Colorado Springs", "Raleigh", "Omaha", "Miami", "Oakland", "Tulsa", "Minneapolis", "Cleveland", "Wichita", "Arlington", "New Orleans", "Bakersfield", "Tampa", "Honolulu", "Anaheim", "Aurora", "Santa Ana", "St. Louis", "Riverside", "Corpus Christi", "Pittsburgh", "Lexington-Fayette", "Stockton", "Cincinnati", "St. Paul", "Toledo", "Newark", "Greensboro", "Plano", "Henderson", "Lincoln", "Buffalo", "Fort Wayne", "Jersey ", "Chula Vista", "Orlando", "St. Petersburg", "Norfolk", "Chandler", "Laredo", "Madison", "Durham", "Lubbock", "Winston-Salem", "Garland", "Glendale", "Hialeah", "Reno", "Baton Rouge", "Irvine", "Chesapeake", "Irving", "Scottsdale", "North Las Vegas", "Fremont", "San Bernardino", "Boise", "Birmingham"}, + "city": {"New York City", "Los Angeles", "Chicago", "Houston", "Philadelphia", "Phoenix", "San Antonio", "San Diego", "Dallas", "San Jose", "Austin", "Jacksonville", "Indianapolis", "San Francisco", "Columbus", "Fort Worth", "Charlotte", "Detroit", "El Paso", "Memphis", "Boston", "Seattle", "Denver", "Washington", "Nashville-Davidson", "Baltimore", "Louisville/Jefferson", "Portland", "Oklahoma", "Milwaukee", "Las Vegas", "Albuquerque", "Tucson", "Fresno", "Sacramento", "Long Beach", "Kansas", "Mesa", "Virginia Beach", "Atlanta", "Colorado Springs", "Raleigh", "Omaha", "Miami", "Oakland", "Tulsa", "Minneapolis", "Cleveland", "Wichita", "Arlington", "New Orleans", "Bakersfield", "Tampa", "Honolulu", "Anaheim", "Aurora", "Santa Ana", "St. Louis", "Riverside", "Corpus Christi", "Pittsburgh", "Lexington-Fayette", "Stockton", "Cincinnati", "St. Paul", "Toledo", "Newark", "Greensboro", "Plano", "Henderson", "Lincoln", "Buffalo", "Fort Wayne", "Jersey", "Chula Vista", "Orlando", "St. Petersburg", "Norfolk", "Chandler", "Laredo", "Madison", "Durham", "Lubbock", "Winston-Salem", "Garland", "Glendale", "Hialeah", "Reno", "Baton Rouge", "Irvine", "Chesapeake", "Irving", "Scottsdale", "North Las Vegas", "Fremont", "San Bernardino", "Boise", "Birmingham"}, "state": {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"}, "state_abr": {"AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "AE", "AA", "AP"}, "zip": {"#####"}, diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go b/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go index ef68c1891..2e3793744 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go @@ -8,4 +8,5 @@ var Animal = map[string][]string{ "farm": {"Chicken", "Cow", "Donkey", "Duck", "Goat", "Goose", "Horse", "Llama", "Pig", "Sheep", "Turkey"}, "cat": {"Abyssinian", "Aegean", "American Bobtail", "American Curl", "American Shorthair", "American Wirehair", "Arabian Mau", "Asian", "Asian Semi-longhair", "Australian Mist", "Balinese", "Bambino", "Bengal", "Birman", "Bombay", "Brazilian Shorthair", "British Longhair", "British Semipi-longhair", "British Shorthair", "Burmese", "Burmilla", "California Spangled", "Chantilly-Tiffany", "Chartreux", "Chausie", "Cheetoh", "Colorpoint Shorthair", "Cornish Rex", "Cymric, or Manx Longhair", "Cyprus", "Devon Rex", "Donskoy, or Don Sphynx", "Dragon Li", "Dwarf cat, or Dwelf", "Egyptian Mau", "European Shorthair", "Exotic Shorthair", "Foldex Cat", "German Rex", "Havana Brown", "Highlander", "Himalayan, or Colorpoint Persian", "Japanese Bobtail", "Javanese", "Khao Manee", "Korat", "Korean Bobtail", "Korn Ja", "Kurilian Bobtail", "Kurilian Bobtail, or Kuril Islands Bobtail", "LaPerm", "Lykoi", "Maine Coon", "Manx", "Mekong Bobtail", "Minskin", "Munchkin", "Napoleon", "Nebelung", "Norwegian Forest Cat", "Ocicat", "Ojos Azules", "Oregon Rex", "Oriental Bicolor", "Oriental Longhair", "Oriental Shorthair", "Persian", "Peterbald", "Pixie-bob", "Raas", "Ragamuffin", "Ragdoll", "Russian Blue", "Russian White, Black and Tabby", "Sam Sawet", "Savannah", "Scottish Fold", "Selkirk Rex", "Serengeti", "Serrade petit", "Siamese", "Siberian", "Singapura", "Snowshoe", "Sokoke", "Somali", "Sphynx", "Suphalak", "Thai", "Tonkinese", "Toyger", "Turkish Angora", "Turkish Van", "Ukrainian Levkoy"}, "dog": {"Affenpinscher", "African", "Airedale", "Akita", "Appenzeller", "Basenji", "Beagle", "Bluetick", "Borzoi", "Bouvier", "Boxer", "Brabancon", "Briard", "Boston Bulldog", "French Bulldog", "Staffordshire Bullterrier", "Cairn", "Chihuahua", "Chow", "Clumber", "Border Collie", "Coonhound", "Cardigan Corgi", "Dachshund", "Great Dane", "Scottish Deerhound", "Dhole", "Dingo", "Doberman", "Norwegian Elkhound", "Entlebucher", "Eskimo", "Germanshepherd", "Italian Greyhound", "Groenendael", "Ibizan Hound", "Afghan Hound", "Basset Hound", "Blood Hound", "English Hound", "Walker Hound", "Husky", "Keeshond", "Kelpie", "Komondor", "Kuvasz", "Labrador", "Leonberg", "Lhasa", "Malamute", "Malinois", "Maltese", "Bull Mastiff", "Tibetan Mastiff", "Mexicanhairless", "Bernese Mountain", "Swiss Mountain", "Newfoundland", "Otterhound", "Papillon", "Pekinese", "Pembroke", "Miniature Pinscher", "German Pointer", "Pomeranian", "Miniature Poodle", "Standard Poodle", "Toy Poodle", "Pug", "Pyrenees", "Redbone", "Chesapeake Retriever", "Curly Retriever", "Flatcoated Retriever", "Golden Retriever", "Rhodesian Ridgeback", "Rottweiler", "Saluki", "Samoyed", "Schipperke", "Giant Schnauzer", "Miniature Schnauzer", "English Setter", "Gordon Setter", "Irish Setter", "English Sheepdog", "Shetland Sheepdog", "Shiba", "Shihtzu", "Blenheim Spaniel", "Brittany Spaniel", "Cocker Spaniel", "Irish Spaniel", "Japanese Spaniel", "Sussex Spaniel", "Welsh Spaniel", "English Springer", "Stbernard", "American Terrier", "Australian Terrier", "Bedlington Terrier", "Border Terrier", "Dandie Terrier", "Fox Terrier", "Irish Terrier", "Kerryblue Terrier", "Lakeland Terrier", "Norfolk Terrier", "Norwich Terrier", "Patterdale Terrier", "Rat Terrier", "Scottish Terrier", "Sealyham Terrier", "Silky Terrier", "Tibetan Terrier", "Toy Terrier", "Westhighland Terrier", "Wheaten Terrier", "Yorkshire Terrier", "Vizsla", "Weimaraner", "Whippet", "Irish Wolfhound"}, + "bird": {"albatross", "bluejay", "canary", "cardinal", "chicken", "crow", "dove", "duck", "eagle", "emu", "falcon", "flamingo", "goose", "hornbill", "hummingbird", "ibis", "jay", "kingfisher", "lovebird", "mynah", "nightingale", "oriole", "ostrich", "owl", "parrot", "peacock", "penguin", "quail", "rooster", "sparrow", "swan", "thrush", "toucan", "vulture", "woodpecker", "yellow warbler"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/car.go b/vendor/github.com/brianvoe/gofakeit/v6/data/car.go index c144fee8a..8754b1220 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/car.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/car.go @@ -6,5 +6,5 @@ var Car = map[string][]string{ "fuel_type": {"Gasoline", "Methanol", "Ethanol", "Diesel", "LPG", "CNG", "Electric"}, "transmission_type": {"Manual", "Automatic"}, "maker": {"Alfa Romeo", "Aston Martin", "Audi", "Bentley", "Benz", "BMW", "Bugatti", "Cadillac", "Chevrolet", "Chrysler", "Citroen", "Corvette", "DAF", "Dacia", "Daewoo", "Daihatsu", "Datsun", "De Lorean", "Dino", "Dodge", "Farboud", "Ferrari", "Fiat", "Ford", "Honda", "Hummer", "Hyundai", "Jaguar", "Jeep", "KIA", "Koenigsegg", "Lada", "Lamborghini", "Lancia", "Land Rover", "Lexus", "Ligier", "Lincoln", "Lotus", "Martini", "Maserati", "Maybach", "Mazda", "McLaren", "Mercedes", "Mercedes-Benz", "Mini", "Mitsubishi", "Nissan", "Noble", "Opel", "Peugeot", "Pontiac", "Porsche", "Renault", "Rolls-Royce", "Rover", "Saab", "Seat", "Skoda", "Smart", "Spyker", "Subaru", "Suzuki", "Toyota", "Tesla", "Vauxhall", "Volkswagen", "Volvo"}, - "model": {"Db9 Coupe", "Db9 Coupe Manual", "Db9 Volante", "V12 Vanquish S", "V8 Vantage", "A3", "A4", "A4 Avant Quattro", "A4 Cabriolet", "A4 Cabriolet Quattro", "A4 Quattro", "A6", "A6 Avant Quattro", "A6 Quattro", "A8 L", "Gti", "Passat", "S4", "S4 Avant", "S4 Cabriolet", "Tt Coupe", "Tt Roadster", "Bentley Arnage", "Continental Flying Spur", "Continental Gt", " 325ci Convertible", " 325i", " 325xi", " 325xi Sport Wagon", " 330ci Convertible", " 330i", " 330xi", " 525i", " 525xi", " 530i", " 530xi", " 530xi Sport Wagon", " 550i", " 650ci", " 650ci Convertible", " 750li", " 760li", " M3", " M3 Convertible", " M5", " M6", " Mini Cooper", " Mini Cooper Convertible", " Mini Cooper S", " Mini Cooper S Convertible", " X3", " X5", " X5 4.8is", " Z4 3.0 Si Coupe", " Z4 3.0i", " Z4 3.0si", " Z4 M Roadster", "Veyron", "300c/srt-8", "Caravan 2wd", "Charger", "Commander 4wd", "Crossfire Roadster", "Dakota Pickup 2wd", "Dakota Pickup 4wd", "Durango 2wd", "Durango 4wd", "Grand Cherokee 2wd", "Grand Cherokee 4wd", "Liberty/cherokee 2wd", "Liberty/cherokee 4wd", "Pacifica 2wd", "Pacifica Awd", "Pt Cruiser", "Ram 1500 Pickup 2wd", "Ram 1500 Pickup 4wd", "Sebring 4-dr", "Stratus 4-dr", "Town & Country 2wd", "Viper Convertible", "Wrangler/tj 4wd", "F430", "Ferrari 612 Scaglietti", "Ferrari F141", "B4000 4wd", "Crown Victoria Police", "E150 Club Wagon", "E150 Econoline 2wd", "Escape 4wd", "Escape Fwd", "Escape Hybrid 4wd", "Escape Hybrid Fwd", "Expedition 2wd", "Explorer 2wd", "Explorer 4wd", "F150 Ffv 2wd", "F150 Ffv 4wd", "F150 Pickup 2wd", "F150 Pickup 4wd", "Five Hundred Awd", "Focus Fwd", "Focus Station Wag", "Freestar Wagon Fwd", "Freestyle Awd", "Freestyle Fwd", "Grand Marquis", "Gt 2wd", "Ls", "Mark Lt", "Milan", "Monterey Wagon Fwd", "Mountaineer 4wd", "Mustang", "Navigator 2wd", "Ranger Pickup 2wd", "Ranger Pickup 4wd", "Taurus", "Taurus Ethanol Ffv", "Thunderbird", "Town Car", "Zephyr", "B9 Tribeca Awd", "Baja Awd", "Forester Awd", "Impreza Awd", "Impreza Wgn/outback Spt Awd", "Legacy Awd", "Legacy Wagon Awd", "Outback Awd", "Outback Wagon Awd", "9-3 Convertible", "9-3 Sport Sedan", "9-5 Sedan", "C15 Silverado Hybrid 2wd", "C1500 Silverado 2wd", "C1500 Suburban 2wd", "C1500 Tahoe 2wd", "C1500 Yukon 2wd", "Cobalt", "Colorado 2wd", "Colorado 4wd", "Colorado Cab Chassis Inc 2wd", "Colorado Crew Cab 2wd", "Colorado Crew Cab 4wd", "Corvette", "Cts", "Dts", "Envoy 2wd", "Envoy Xl 4wd", "Equinox Awd", "Equinox Fwd", "Escalade 2wd", "Escalade Esv Awd", "G15/25chev Van 2wd Conv", "G1500/2500 Chevy Express 2wd", "G1500/2500 Chevy Van 2wd", "G6", "G6 Gt/gtp Convertible", "Grand Prix", "Gto", "H3 4wd", "Hhr Fwd", "I-280 2wd Ext Cab", "Impala", "K15 Silverado Hybrid 4wd", "K1500 Avalanche 4wd", "K1500 Silverado 4wd", "K1500 Tahoe 4wd", "Lacrosse/allure", "Limousine", "Malibu", "Montana Sv6 Awd", "Monte Carlo", "Rendezvous Awd", "Rendezvous Fwd", "Solstice", "Srx 2wd", "Srx Awd", "Ssr Pickup 2wd", "Sts", "Sts Awd", "Terraza Fwd", "Trailblazer 2wd", "Trailblazer 4wd", "Trailblazer Awd", "Trailblazer Ext 4wd", "Uplander Fwd", "Vue Awd", "Vue Fwd", "Xlr", "Aveo", "Forenza", "Forenza Wagon", "Verona", "Accord", "Accord Hybrid", "Civic", "Civic Hybrid", "Cr-v 4wd", "Element 2wd", "Element 4wd", "Insight", "Mdx 4wd", "Odyssey 2wd", "Pilot 2wd", "Pilot 4wd", "Ridgeline 4wd", "Rl", "Rsx", "S2000", "Tl", "Tsx", "Accent", "Azera", "Elantra", "Santafe 2wd", "Santafe 4wd", "Sonata", "Tiburon", "Tucson 2wd", "Tucson 4wd", "S-type 3.0 Litre", "S-type 4.2 Litre", "S-type R", "Vdp Lwb", "Xj8", "Xk8 Convertible", "Xkr Convertible", "X-type", "X-type Sport Brake", "Amanti", "Optima", "Optima(ms)", "Rio", "Sedona", "Sorento 2wd", "Sorento 4wd", "Spectra(ld)", "Sportage 2wd", "Sportage 4wd", "L-140/715 Gallardo", "L-147/148 Murcielago", "Lr3", "Range Rover", "Range Rover Sport", "Elise/exige", "Coupe Cambiocorsa/gt/g-sport", "Quattroporte", "Mazda 3", "Mazda 5", "Mazda 6", "Mazda 6 Sport Wagon", "Mazda Rx-8", "Mpv", "Mx-5", "C230", "C280", "C280 4matic", "C350", "C350 4matic", "C55 Amg", "Cl65 Amg", "Clk350", "Clk350 (cabriolet)", "Clk55 Amg (cabriolet)", "Cls500", "Cls55 Amg", "E320 Cdi", "E350", "E350 (wagon)", "E350 4matic", "E350 4matic (wagon)", "E500", "E55 Amg", "E55 Amg (wagon)", "Maybach 57s", "Maybach 62", "Ml350", "Ml500", "R350", "R500", "S350", "S430", "Sl500", "Sl600", "Sl65 Amg", "Slk280", "Slk350", "Slr", "Eclipse", "Endeavor 2wd", "Endeavor 4wd", "Galant", "Lancer", "Lancer Evolution", "Lancer Sportback", "Montero", "Outlander 2wd", "Outlander 4wd", "Vibe", "350z", "350z Roadster", "Altima", "Armada 2wd", "Armada 4wd", "Frontier 2wd", "Frontier V6-2wd", "Frontier V6-4wd", "Fx35 Awd", "Fx35 Rwd", "Fx45 Awd", "G35", "M35", "M35x", "M45", "Maxima", "Murano Awd", "Murano Fwd", "Pathfinder 2wd", "Pathfinder 4wd", "Q45", "Q45 Sport", "Quest", "Qx56 4wd", "Sentra", "Titan 2wd", "Titan 4wd", "Xterra 2wd", "Xterra 4wd", "Boxster", "Boxster S", "Carrera 2 Coupe", "Cayenne", "Cayenne S", "Cayenne Turbo", "Cayman S", "Phantom", "F150 Supercrew 4wd", "C8 Spyder", "Aerio", "Aerio Sx", "Aerio Sx Awd", "Grand Vitara Xl-7", "Grand Vitara Xl-7 4wd", "Grand Vitara Xv6", "Grand Vitara Xv6 Awd", "4runner 2wd", "4runner 4wd", "Avalon", "Camry", "Camry Solara", "Camry Solara Convertible", "Corolla", "Corolla Matrix", "Es 330", "Gs 300 4wd", "Gs 300/gs 430", "Gx 470", "Highlander 2wd", "Highlander 4wd", "Highlander Hybrid 2wd", "Highlander Hybrid 4wd", "Is 250", "Is 250 Awd", "Is 350", "Ls 430", "Lx 470", "Prius", "Rav4 2wd", "Rav4 4wd", "Rx 330 2wd", "Rx 330 4wd", "Rx 400h 4wd", "Sc 430", "Scion Tc", "Scion Xa", "Scion Xb", "Sequoia 2wd", "Sequoia 4wd", "Sienna 2wd", "Sienna 4wd", "Toyota Tacoma 2wd", "Toyota Tacoma 4wd", "Toyota Tundra 2wd", "Toyota Tundra 4wd", "Yaris", "A3 Quattro", "Golf", "Jetta", "New Beetle", "New Beetle Convertible", "Passat Wagon 4motion", "Phaeton", "Rabbit", "Touareg", "Tt Coupe Quattro", "Tt Roadster Quattro", "C70 Convertible", "S40 Awd", "S40 Fwd", "S60 Awd", "S60 Fwd", "S60 R Awd", "S80 Fwd", "V50 Awd", "V70 Fwd", "V70 R Awd", "Xc 70 Awd", "Xc 90 Awd", "Xc 90 Fwd"}, + "model": {"Db9 Coupe", "Db9 Coupe Manual", "Db9 Volante", "V12 Vanquish S", "V8 Vantage", "A3", "A4", "A4 Avant Quattro", "A4 Cabriolet", "A4 Cabriolet Quattro", "A4 Quattro", "A6", "A6 Avant Quattro", "A6 Quattro", "A8 L", "Gti", "Passat", "S4", "S4 Avant", "S4 Cabriolet", "Tt Coupe", "Tt Roadster", "Bentley Arnage", "Continental Flying Spur", "Continental Gt", "325ci Convertible", "325i", "325xi", "325xi Sport Wagon", "330ci Convertible", "330i", "330xi", "525i", "525xi", "530i", "530xi", "530xi Sport Wagon", "550i", "650ci", "650ci Convertible", "750li", "760li", "M3", "M3 Convertible", "M5", "M6", "Mini Cooper", "Mini Cooper Convertible", "Mini Cooper S", "Mini Cooper S Convertible", "X3", "X5", "X5 4.8is", "Z4 3.0 Si Coupe", "Z4 3.0i", "Z4 3.0si", "Z4 M Roadster", "Veyron", "300c/srt-8", "Caravan 2wd", "Charger", "Commander 4wd", "Crossfire Roadster", "Dakota Pickup 2wd", "Dakota Pickup 4wd", "Durango 2wd", "Durango 4wd", "Grand Cherokee 2wd", "Grand Cherokee 4wd", "Liberty/cherokee 2wd", "Liberty/cherokee 4wd", "Pacifica 2wd", "Pacifica Awd", "Pt Cruiser", "Ram 1500 Pickup 2wd", "Ram 1500 Pickup 4wd", "Sebring 4-dr", "Stratus 4-dr", "Town & Country 2wd", "Viper Convertible", "Wrangler/tj 4wd", "F430", "Ferrari 612 Scaglietti", "Ferrari F141", "B4000 4wd", "Crown Victoria Police", "E150 Club Wagon", "E150 Econoline 2wd", "Escape 4wd", "Escape Fwd", "Escape Hybrid 4wd", "Escape Hybrid Fwd", "Expedition 2wd", "Explorer 2wd", "Explorer 4wd", "F150 Ffv 2wd", "F150 Ffv 4wd", "F150 Pickup 2wd", "F150 Pickup 4wd", "Five Hundred Awd", "Focus Fwd", "Focus Station Wag", "Freestar Wagon Fwd", "Freestyle Awd", "Freestyle Fwd", "Grand Marquis", "Gt 2wd", "Ls", "Mark Lt", "Milan", "Monterey Wagon Fwd", "Mountaineer 4wd", "Mustang", "Navigator 2wd", "Ranger Pickup 2wd", "Ranger Pickup 4wd", "Taurus", "Taurus Ethanol Ffv", "Thunderbird", "Town Car", "Zephyr", "B9 Tribeca Awd", "Baja Awd", "Forester Awd", "Impreza Awd", "Impreza Wgn/outback Spt Awd", "Legacy Awd", "Legacy Wagon Awd", "Outback Awd", "Outback Wagon Awd", "9-3 Convertible", "9-3 Sport Sedan", "9-5 Sedan", "C15 Silverado Hybrid 2wd", "C1500 Silverado 2wd", "C1500 Suburban 2wd", "C1500 Tahoe 2wd", "C1500 Yukon 2wd", "Cobalt", "Colorado 2wd", "Colorado 4wd", "Colorado Cab Chassis Inc 2wd", "Colorado Crew Cab 2wd", "Colorado Crew Cab 4wd", "Corvette", "Cts", "Dts", "Envoy 2wd", "Envoy Xl 4wd", "Equinox Awd", "Equinox Fwd", "Escalade 2wd", "Escalade Esv Awd", "G15/25chev Van 2wd Conv", "G1500/2500 Chevy Express 2wd", "G1500/2500 Chevy Van 2wd", "G6", "G6 Gt/gtp Convertible", "Grand Prix", "Gto", "H3 4wd", "Hhr Fwd", "I-280 2wd Ext Cab", "Impala", "K15 Silverado Hybrid 4wd", "K1500 Avalanche 4wd", "K1500 Silverado 4wd", "K1500 Tahoe 4wd", "Lacrosse/allure", "Limousine", "Malibu", "Montana Sv6 Awd", "Monte Carlo", "Rendezvous Awd", "Rendezvous Fwd", "Solstice", "Srx 2wd", "Srx Awd", "Ssr Pickup 2wd", "Sts", "Sts Awd", "Terraza Fwd", "Trailblazer 2wd", "Trailblazer 4wd", "Trailblazer Awd", "Trailblazer Ext 4wd", "Uplander Fwd", "Vue Awd", "Vue Fwd", "Xlr", "Aveo", "Forenza", "Forenza Wagon", "Verona", "Accord", "Accord Hybrid", "Civic", "Civic Hybrid", "Cr-v 4wd", "Element 2wd", "Element 4wd", "Insight", "Mdx 4wd", "Odyssey 2wd", "Pilot 2wd", "Pilot 4wd", "Ridgeline 4wd", "Rl", "Rsx", "S2000", "Tl", "Tsx", "Accent", "Azera", "Elantra", "Santafe 2wd", "Santafe 4wd", "Sonata", "Tiburon", "Tucson 2wd", "Tucson 4wd", "S-type 3.0 Litre", "S-type 4.2 Litre", "S-type R", "Vdp Lwb", "Xj8", "Xk8 Convertible", "Xkr Convertible", "X-type", "X-type Sport Brake", "Amanti", "Optima", "Optima(ms)", "Rio", "Sedona", "Sorento 2wd", "Sorento 4wd", "Spectra(ld)", "Sportage 2wd", "Sportage 4wd", "L-140/715 Gallardo", "L-147/148 Murcielago", "Lr3", "Range Rover", "Range Rover Sport", "Elise/exige", "Coupe Cambiocorsa/gt/g-sport", "Quattroporte", "Mazda 3", "Mazda 5", "Mazda 6", "Mazda 6 Sport Wagon", "Mazda Rx-8", "Mpv", "Mx-5", "C230", "C280", "C280 4matic", "C350", "C350 4matic", "C55 Amg", "Cl65 Amg", "Clk350", "Clk350 (cabriolet)", "Clk55 Amg (cabriolet)", "Cls500", "Cls55 Amg", "E320 Cdi", "E350", "E350 (wagon)", "E350 4matic", "E350 4matic (wagon)", "E500", "E55 Amg", "E55 Amg (wagon)", "Maybach 57s", "Maybach 62", "Ml350", "Ml500", "R350", "R500", "S350", "S430", "Sl500", "Sl600", "Sl65 Amg", "Slk280", "Slk350", "Slr", "Eclipse", "Endeavor 2wd", "Endeavor 4wd", "Galant", "Lancer", "Lancer Evolution", "Lancer Sportback", "Montero", "Outlander 2wd", "Outlander 4wd", "Vibe", "350z", "350z Roadster", "Altima", "Armada 2wd", "Armada 4wd", "Frontier 2wd", "Frontier V6-2wd", "Frontier V6-4wd", "Fx35 Awd", "Fx35 Rwd", "Fx45 Awd", "G35", "M35", "M35x", "M45", "Maxima", "Murano Awd", "Murano Fwd", "Pathfinder 2wd", "Pathfinder 4wd", "Q45", "Q45 Sport", "Quest", "Qx56 4wd", "Sentra", "Titan 2wd", "Titan 4wd", "Xterra 2wd", "Xterra 4wd", "Boxster", "Boxster S", "Carrera 2 Coupe", "Cayenne", "Cayenne S", "Cayenne Turbo", "Cayman S", "Phantom", "F150 Supercrew 4wd", "C8 Spyder", "Aerio", "Aerio Sx", "Aerio Sx Awd", "Grand Vitara Xl-7", "Grand Vitara Xl-7 4wd", "Grand Vitara Xv6", "Grand Vitara Xv6 Awd", "4runner 2wd", "4runner 4wd", "Avalon", "Camry", "Camry Solara", "Camry Solara Convertible", "Corolla", "Corolla Matrix", "Es 330", "Gs 300 4wd", "Gs 300/gs 430", "Gx 470", "Highlander 2wd", "Highlander 4wd", "Highlander Hybrid 2wd", "Highlander Hybrid 4wd", "Is 250", "Is 250 Awd", "Is 350", "Ls 430", "Lx 470", "Prius", "Rav4 2wd", "Rav4 4wd", "Rx 330 2wd", "Rx 330 4wd", "Rx 400h 4wd", "Sc 430", "Scion Tc", "Scion Xa", "Scion Xb", "Sequoia 2wd", "Sequoia 4wd", "Sienna 2wd", "Sienna 4wd", "Toyota Tacoma 2wd", "Toyota Tacoma 4wd", "Toyota Tundra 2wd", "Toyota Tundra 4wd", "Yaris", "A3 Quattro", "Golf", "Jetta", "New Beetle", "New Beetle Convertible", "Passat Wagon 4motion", "Phaeton", "Rabbit", "Touareg", "Tt Coupe Quattro", "Tt Roadster Quattro", "C70 Convertible", "S40 Awd", "S40 Fwd", "S60 Awd", "S60 Fwd", "S60 R Awd", "S80 Fwd", "V50 Awd", "V70 Fwd", "V70 R Awd", "Xc 70 Awd", "Xc 90 Awd", "Xc 90 Fwd"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go b/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go index 597c99d56..ae4fcffd8 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go @@ -3,5 +3,5 @@ package data var Celebrity = map[string][]string{ "actor": {"Arnold Schwarzenegger", "Jim Carrey", "Emma Watson", "Robert Downey Jr.", "Daniel Radcliffe", "Chris Evans", "Leonardo DiCaprio", "Tom Cruise", "Brad Pitt", "Charles Chaplin", "Morgan Freeman", "Tom Hanks", "Hugh Jackman", "Matt Damon", "Sylvester Stallone", "Will Smith", "Clint Eastwood", "Cameron Diaz", "George Clooney", "Steven Spielberg", "Harrison Ford", "Robert De Niro", "Al Pacino", "Robert Downey Jr.", "Russell Crowe", "Liam Neeson", "Kate Winslet", "Mark Wahlberg", "Natalie Portman", "Pierce Brosnan", "Sean Connery", "Orlando Bloom", "Dwayne Johnson", "Jackie Chan", "Angelina Jolie", "Adam Sandler", "Scarlett Johansson", "Heath Ledger", "Anne Hathaway", "Jessica Alba", "Edward Norton", "Keira Knightley", "Bradley Cooper", "Will Ferrell", "Julia Roberts", "Nicolas Cage", "Daniel Craig", "Keanu Reeves", "Ian McKellen", "Halle Berry", "Bruce Willis", "Ben Stiller", "Tommy Lee Jones", "Antonio Banderas", "Denzel Washington", "Steve Carell", "Shia LaBeouf", "Megan Fox", "James Franco", "Mel Gibson", "Vin Diesel", "Tim Allen", "Robin Williams", "Kevin Spacey", "Jason Biggs", "Seann William Scott", "Jean-Claude Van Damme", "Zach Galifianakis", "Owen Wilson", "Christian Bale", "Peter Jackson", "Sandra Bullock", "Bruce Lee", "Drew Barrymore", "Macaulay Culkin", "Jack Nicholson", "Bill Murray", "Sigourney Weaver", "Jake Gyllenhaal", "Jason Statham", "Jet Li", "Kate Beckinsale", "Rowan Atkinson", "Marlon Brando", "John Travolta", "Channing Tatum", "Ben Affleck", "Shah Rukh Khan", "Jennifer Aniston", "Emma Stone", "Chris Hemsworth", "James McAvoy", "James Cameron", "Amitabh Bachchan", "Brendan Fraser", "Rachel McAdams", "Tom Hiddleston", "Aamir Khan"}, "business": {"Elon Musk", "Steve Jobs", "Jeff Bezos", "Bill Gates", "Mark Zuckerberg", "Sundar Pichai", "Walt Disney", "Warren Buffett", "Mukesh Ambani", "P. T. Barnum", "Colonel Sanders", "Ray Kroc", "Richard Branson", "Henry Ford", "Larry Page", "Steve Wozniak", "Ratan Tata", "John D. Rockefeller", "Madam C. J. Walker", "Tim Cook", "Andrew Carnegie", "Paul Allen", "Bobby Flay", "J. P. Morgan", "Satya Nadella", "Dhirubhai Ambani", "Carlos Slim", "Ross Perot", "Jamie Oliver", "Jack Ma", "Larry Ellison", "Sam Walton", "Sheryl Sandberg", "Marco Pierre White", "Indra Nooyi", "David Rockefeller", "Steve Ballmer", "Beyonce Knowles", "N. R. Narayana Murthy", "Mark Wahlberg", "Cameron Diaz", "Sergey Brin", "Howard Hughes", "Jessica Alba", "Dustin Moskovitz", "Eva Mendes", "Amancio Ortega Gaona", "Fred Trump", "Jamsetji Tata", "Kate Hudson", "Martha Stewart", "Peter Jones", "Marco Polo", "Susan Wojcicki", "Oskar Schindler", "Elizabeth Hurley", "Sean Combs", "Kate Spade", "Vincent McMahon", "David Chang", "Coco Chanel", "Vera Wang", "Arianna Huffington", "John McAfee", "Dany Garcia", "Richard Attenborough", "Donatella Versace", "Chris Hughes", "Alexis Ohanian", "J. Paul Getty", "Sharon Osbourne", "Bob Iger", "Kate Walsh", "Chris Gardner", "Jessica Simpson", "Guy Fieri", "Joy Mangano", "Wolfgang Puck", "Christie Brinkley", "Tom Steyer", "Evan Spiegel", "Hugh Hefner", "Preity Zinta", "Shane McMahon", "Salt Bae", "Mario Batali", "Bernard Arnault", "Michael Bloomberg", "Portia de Rossi", "Kevin O'Leary", "Roman Abramovich", "Jamie Dimon", "Rob Dyrdek", "Emeril Lagasse", "Kat Von D", "Karlie Kloss", "Antoni Porowski", "Edmond James de Rothschild", "Mitt Romney", "Aristotle Onassis", "Richard Benjamin Harrison", "Ben Bernanke", "Mark Cuban", "William Randolph Hearst", "Nate Robinson", "Alan Shepard", "Christina Anstead", "Laurene Powell Jobs", "Adam Weitsman", "Gladys Knight", "Gary Vaynerchuk", "Robert Kraft", "John Paul DeJoria", "Lori Greiner", "Carly Fiorina", "Lakshmi Mittal", "Jerry Jones", "Meg Whitman", "Azim Premji", "Lisa Vanderpump", "Dana White", "Russell Simmons", "Jennifer Flavin", "Harry Hamlin", "Conrad Hilton", "Prescott Bush", "Alvaro Morte", "Shigeru Miyamoto", "Phil Knight", "Jack Dorsey", "Barbara Bush", "Lee Iacocca", "Ma Huateng", "Rick Harrison", "Drew Scott", "Jawed Karim", "Daymond John", "Jaclyn Smith", "Maryse Ouellet", "Allegra Versace"}, - "sport": {"Pele", "Usain Bolt", "Muhammad Ali", "Carl Lewis", "Jesse Owens", "Sir Donald Bradman", "Billie Jean King", "Eddy Merckx", "Jackie Joyner-Kersee", "Lionel Messi", "Babe Didrikson Zaharias", "Michael Jordan", "Larisa Latynina", "Diego Maradona", "Serena Williams", "Babe Ruth", "Roger Federer", "Martina Navratilova", "Michael Phelps", "Lottie Dod", "Sachin Tendulkar", "Johan Cruyff", "Tiger Woods ", "Sonja Henie", "Aryton Senna", "Nadia Comaneci", "Sergei Bubka", "Emil Zatopek", "Manny Pacquiao", "Imran Khan", "Jackie Robinson", "Shane Warne", "Dhyan Chand", "Fred Perry", "Lin Dan", "Abebe Bikila", "Clara Hughes", "Jan-Ove Waldner", "Bobby Moore", "Bjorn Borg ", "Karch Kiraly", "Bradley Wiggins", "Seve Ballesteros", "David Beckham", "Michael Schumacher", "Greg Lemond", "Mia Hamm", "Jacques Anquetil", "Jack Nicklaus", "Steve Davis", "John McEnroe", "Monica Seles", "Magic Johnson", "Joe DiMaggio", "Roger Bannister", "Mo Farah", "Mark Spitz", "Chris Evert", "Al Oerter", "Jimmy Connors", "Michael Johnson", "Ian Botham ", "Jim Thorpe", "Sir Steve Redgrave", "Steffi Graf", "Sebastian Coe", "Hicham El Guerrouj", "Eric Liddell", "W.G Grace", "Kenenisa Bekele", "Bernard Hinault ", "Bob Beamon", "Paavo Nurmi", "David Campese", "Kelly Slater", "Haile Gebreselassie", "Rafael Nadal", "Brian Lara", "Chris Hoy", "Serge Blanco", "Cristiano Ronaldo", "Sir Gary Sobers", "Andy Murray", "George Best", "Sir Viv Richards", "Fausto Coppi", "Eusebio", "Rod Laver", "Grete Waitz", "Margaret Smith Court", "Tegla Laroupe", "Fanny Blankers-Koen", "Asbel Kiprop", "Lewis Hamilton", "C.B.Fry", "Annika Sörenstam", "Wilma Rudolph", "Alberta Tomba", "Bo Jackson"}, + "sport": {"Pele", "Usain Bolt", "Muhammad Ali", "Carl Lewis", "Jesse Owens", "Sir Donald Bradman", "Billie Jean King", "Eddy Merckx", "Jackie Joyner-Kersee", "Lionel Messi", "Babe Didrikson Zaharias", "Michael Jordan", "Larisa Latynina", "Diego Maradona", "Serena Williams", "Babe Ruth", "Roger Federer", "Martina Navratilova", "Michael Phelps", "Lottie Dod", "Sachin Tendulkar", "Johan Cruyff", "Tiger Woods", "Sonja Henie", "Aryton Senna", "Nadia Comaneci", "Sergei Bubka", "Emil Zatopek", "Manny Pacquiao", "Imran Khan", "Jackie Robinson", "Shane Warne", "Dhyan Chand", "Fred Perry", "Lin Dan", "Abebe Bikila", "Clara Hughes", "Jan-Ove Waldner", "Bobby Moore", "Bjorn Borg", "Karch Kiraly", "Bradley Wiggins", "Seve Ballesteros", "David Beckham", "Michael Schumacher", "Greg Lemond", "Mia Hamm", "Jacques Anquetil", "Jack Nicklaus", "Steve Davis", "John McEnroe", "Monica Seles", "Magic Johnson", "Joe DiMaggio", "Roger Bannister", "Mo Farah", "Mark Spitz", "Chris Evert", "Al Oerter", "Jimmy Connors", "Michael Johnson", "Ian Botham", "Jim Thorpe", "Sir Steve Redgrave", "Steffi Graf", "Sebastian Coe", "Hicham El Guerrouj", "Eric Liddell", "W.G Grace", "Kenenisa Bekele", "Bernard Hinault", "Bob Beamon", "Paavo Nurmi", "David Campese", "Kelly Slater", "Haile Gebreselassie", "Rafael Nadal", "Brian Lara", "Chris Hoy", "Serge Blanco", "Cristiano Ronaldo", "Sir Gary Sobers", "Andy Murray", "George Best", "Sir Viv Richards", "Fausto Coppi", "Eusebio", "Rod Laver", "Grete Waitz", "Margaret Smith Court", "Tegla Laroupe", "Fanny Blankers-Koen", "Asbel Kiprop", "Lewis Hamilton", "C.B.Fry", "Annika Sörenstam", "Wilma Rudolph", "Alberta Tomba", "Bo Jackson"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go b/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go index 3aca817d6..96761aad2 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go @@ -3,5 +3,108 @@ package data // Colors consists of color information var Colors = map[string][]string{ "safe": {"black", "maroon", "green", "navy", "olive", "purple", "teal", "lime", "blue", "silver", "gray", "yellow", "fuchsia", "aqua", "white"}, - "full": {"AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenRod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "Darkorange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "GoldenRod", "Gray", "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed ", "Indigo ", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenRodYellow", "LightGray", "LightGreen", "LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquaMarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenRod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen"}, + "full": {"AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenRod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "Darkorange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "GoldenRod", "Gray", "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed", "Indigo", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenRodYellow", "LightGray", "LightGreen", "LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquaMarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenRod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen"}, +} + +var ColorsNice = [][]string{ + {"#69d2e7", "#a7dbd8", "#e0e4cc", "#f38630", "#fa6900"}, + {"#fe4365", "#fc9d9a", "#f9cdad", "#c8c8a9", "#83af9b"}, + {"#ecd078", "#d95b43", "#c02942", "#542437", "#53777a"}, + {"#556270", "#4ecdc4", "#c7f464", "#ff6b6b", "#c44d58"}, + {"#774f38", "#e08e79", "#f1d4af", "#ece5ce", "#c5e0dc"}, + {"#e8ddcb", "#cdb380", "#036564", "#033649", "#031634"}, + {"#490a3d", "#bd1550", "#e97f02", "#f8ca00", "#8a9b0f"}, + {"#594f4f", "#547980", "#45ada8", "#9de0ad", "#e5fcc2"}, + {"#00a0b0", "#6a4a3c", "#cc333f", "#eb6841", "#edc951"}, + {"#e94e77", "#d68189", "#c6a49a", "#c6e5d9", "#f4ead5"}, + {"#3fb8af", "#7fc7af", "#dad8a7", "#ff9e9d", "#ff3d7f"}, + {"#d9ceb2", "#948c75", "#d5ded9", "#7a6a53", "#99b2b7"}, + {"#ffffff", "#cbe86b", "#f2e9e1", "#1c140d", "#cbe86b"}, + {"#efffcd", "#dce9be", "#555152", "#2e2633", "#99173c"}, + {"#343838", "#005f6b", "#008c9e", "#00b4cc", "#00dffc"}, + {"#413e4a", "#73626e", "#b38184", "#f0b49e", "#f7e4be"}, + {"#ff4e50", "#fc913a", "#f9d423", "#ede574", "#e1f5c4"}, + {"#99b898", "#fecea8", "#ff847c", "#e84a5f", "#2a363b"}, + {"#655643", "#80bca3", "#f6f7bd", "#e6ac27", "#bf4d28"}, + {"#00a8c6", "#40c0cb", "#f9f2e7", "#aee239", "#8fbe00"}, + {"#351330", "#424254", "#64908a", "#e8caa4", "#cc2a41"}, + {"#554236", "#f77825", "#d3ce3d", "#f1efa5", "#60b99a"}, + {"#5d4157", "#838689", "#a8caba", "#cad7b2", "#ebe3aa"}, + {"#8c2318", "#5e8c6a", "#88a65e", "#bfb35a", "#f2c45a"}, + {"#fad089", "#ff9c5b", "#f5634a", "#ed303c", "#3b8183"}, + {"#ff4242", "#f4fad2", "#d4ee5e", "#e1edb9", "#f0f2eb"}, + {"#f8b195", "#f67280", "#c06c84", "#6c5b7b", "#355c7d"}, + {"#d1e751", "#ffffff", "#000000", "#4dbce9", "#26ade4"}, + {"#1b676b", "#519548", "#88c425", "#bef202", "#eafde6"}, + {"#5e412f", "#fcebb6", "#78c0a8", "#f07818", "#f0a830"}, + {"#bcbdac", "#cfbe27", "#f27435", "#f02475", "#3b2d38"}, + {"#452632", "#91204d", "#e4844a", "#e8bf56", "#e2f7ce"}, + {"#eee6ab", "#c5bc8e", "#696758", "#45484b", "#36393b"}, + {"#f0d8a8", "#3d1c00", "#86b8b1", "#f2d694", "#fa2a00"}, + {"#2a044a", "#0b2e59", "#0d6759", "#7ab317", "#a0c55f"}, + {"#f04155", "#ff823a", "#f2f26f", "#fff7bd", "#95cfb7"}, + {"#b9d7d9", "#668284", "#2a2829", "#493736", "#7b3b3b"}, + {"#bbbb88", "#ccc68d", "#eedd99", "#eec290", "#eeaa88"}, + {"#b3cc57", "#ecf081", "#ffbe40", "#ef746f", "#ab3e5b"}, + {"#a3a948", "#edb92e", "#f85931", "#ce1836", "#009989"}, + {"#300030", "#480048", "#601848", "#c04848", "#f07241"}, + {"#67917a", "#170409", "#b8af03", "#ccbf82", "#e33258"}, + {"#aab3ab", "#c4cbb7", "#ebefc9", "#eee0b7", "#e8caaf"}, + {"#e8d5b7", "#0e2430", "#fc3a51", "#f5b349", "#e8d5b9"}, + {"#ab526b", "#bca297", "#c5ceae", "#f0e2a4", "#f4ebc3"}, + {"#607848", "#789048", "#c0d860", "#f0f0d8", "#604848"}, + {"#b6d8c0", "#c8d9bf", "#dadabd", "#ecdbbc", "#fedcba"}, + {"#a8e6ce", "#dcedc2", "#ffd3b5", "#ffaaa6", "#ff8c94"}, + {"#3e4147", "#fffedf", "#dfba69", "#5a2e2e", "#2a2c31"}, + {"#fc354c", "#29221f", "#13747d", "#0abfbc", "#fcf7c5"}, + {"#cc0c39", "#e6781e", "#c8cf02", "#f8fcc1", "#1693a7"}, + {"#1c2130", "#028f76", "#b3e099", "#ffeaad", "#d14334"}, + {"#a7c5bd", "#e5ddcb", "#eb7b59", "#cf4647", "#524656"}, + {"#dad6ca", "#1bb0ce", "#4f8699", "#6a5e72", "#563444"}, + {"#5c323e", "#a82743", "#e15e32", "#c0d23e", "#e5f04c"}, + {"#edebe6", "#d6e1c7", "#94c7b6", "#403b33", "#d3643b"}, + {"#fdf1cc", "#c6d6b8", "#987f69", "#e3ad40", "#fcd036"}, + {"#230f2b", "#f21d41", "#ebebbc", "#bce3c5", "#82b3ae"}, + {"#b9d3b0", "#81bda4", "#b28774", "#f88f79", "#f6aa93"}, + {"#3a111c", "#574951", "#83988e", "#bcdea5", "#e6f9bc"}, + {"#5e3929", "#cd8c52", "#b7d1a3", "#dee8be", "#fcf7d3"}, + {"#1c0113", "#6b0103", "#a30006", "#c21a01", "#f03c02"}, + {"#000000", "#9f111b", "#b11623", "#292c37", "#cccccc"}, + {"#382f32", "#ffeaf2", "#fcd9e5", "#fbc5d8", "#f1396d"}, + {"#e3dfba", "#c8d6bf", "#93ccc6", "#6cbdb5", "#1a1f1e"}, + {"#f6f6f6", "#e8e8e8", "#333333", "#990100", "#b90504"}, + {"#1b325f", "#9cc4e4", "#e9f2f9", "#3a89c9", "#f26c4f"}, + {"#a1dbb2", "#fee5ad", "#faca66", "#f7a541", "#f45d4c"}, + {"#c1b398", "#605951", "#fbeec2", "#61a6ab", "#accec0"}, + {"#5e9fa3", "#dcd1b4", "#fab87f", "#f87e7b", "#b05574"}, + {"#951f2b", "#f5f4d7", "#e0dfb1", "#a5a36c", "#535233"}, + {"#8dccad", "#988864", "#fea6a2", "#f9d6ac", "#ffe9af"}, + {"#2d2d29", "#215a6d", "#3ca2a2", "#92c7a3", "#dfece6"}, + {"#413d3d", "#040004", "#c8ff00", "#fa023c", "#4b000f"}, + {"#eff3cd", "#b2d5ba", "#61ada0", "#248f8d", "#605063"}, + {"#ffefd3", "#fffee4", "#d0ecea", "#9fd6d2", "#8b7a5e"}, + {"#cfffdd", "#b4dec1", "#5c5863", "#a85163", "#ff1f4c"}, + {"#9dc9ac", "#fffec7", "#f56218", "#ff9d2e", "#919167"}, + {"#4e395d", "#827085", "#8ebe94", "#ccfc8e", "#dc5b3e"}, + {"#a8a7a7", "#cc527a", "#e8175d", "#474747", "#363636"}, + {"#f8edd1", "#d88a8a", "#474843", "#9d9d93", "#c5cfc6"}, + {"#046d8b", "#309292", "#2fb8ac", "#93a42a", "#ecbe13"}, + {"#f38a8a", "#55443d", "#a0cab5", "#cde9ca", "#f1edd0"}, + {"#a70267", "#f10c49", "#fb6b41", "#f6d86b", "#339194"}, + {"#ff003c", "#ff8a00", "#fabe28", "#88c100", "#00c176"}, + {"#ffedbf", "#f7803c", "#f54828", "#2e0d23", "#f8e4c1"}, + {"#4e4d4a", "#353432", "#94ba65", "#2790b0", "#2b4e72"}, + {"#0ca5b0", "#4e3f30", "#fefeeb", "#f8f4e4", "#a5b3aa"}, + {"#4d3b3b", "#de6262", "#ffb88c", "#ffd0b3", "#f5e0d3"}, + {"#fffbb7", "#a6f6af", "#66b6ab", "#5b7c8d", "#4f2958"}, + {"#edf6ee", "#d1c089", "#b3204d", "#412e28", "#151101"}, + {"#9d7e79", "#ccac95", "#9a947c", "#748b83", "#5b756c"}, + {"#fcfef5", "#e9ffe1", "#cdcfb7", "#d6e6c3", "#fafbe3"}, + {"#9cddc8", "#bfd8ad", "#ddd9ab", "#f7af63", "#633d2e"}, + {"#30261c", "#403831", "#36544f", "#1f5f61", "#0b8185"}, + {"#aaff00", "#ffaa00", "#ff00aa", "#aa00ff", "#00aaff"}, + {"#d1313d", "#e5625c", "#f9bf76", "#8eb2c5", "#615375"}, + {"#ffe181", "#eee9e5", "#fad3b2", "#ffba7f", "#ff9c97"}, + {"#73c8a9", "#dee1b6", "#e1b866", "#bd5532", "#373b44"}, + {"#805841", "#dcf7f3", "#fffcdd", "#ffd8d8", "#f5a2a2"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/company.go b/vendor/github.com/brianvoe/gofakeit/v6/data/company.go index 858a1a464..43b6a2dc9 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/company.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/company.go @@ -6,4 +6,5 @@ var Company = map[string][]string{ "suffix": {"Inc", "and Sons", "LLC", "Group"}, "buzzwords": {"Adaptive", "Advanced", "Ameliorated", "Assimilated", "Automated", "Balanced", "Business-focused", "Centralized", "Cloned", "Compatible", "Configurable", "Cross-group", "Cross-platform", "Customer-focused", "Customizable", "De-engineered", "Decentralized", "Devolved", "Digitized", "Distributed", "Diverse", "Down-sized", "Enhanced", "Enterprise-wide", "Ergonomic", "Exclusive", "Expanded", "Extended", "Face to face", "Focused", "Front-line", "Fully-configurable", "Function-based", "Fundamental", "Future-proofed", "Grass-roots", "Horizontal", "Implemented", "Innovative", "Integrated", "Intuitive", "Inverse", "Managed", "Mandatory", "Monitored", "Multi-channelled", "Multi-lateral", "Multi-layered", "Multi-tiered", "Networked", "Object-based", "Open-architected", "Open-source", "Operative", "Optimized", "Optional", "Organic", "Organized", "Persevering", "Persistent", "Phased", "Polarised", "Pre-emptive", "Proactive", "Profit-focused", "Profound", "Programmable", "Progressive", "Public-key", "Quality-focused", "Re-contextualized", "Re-engineered", "Reactive", "Realigned", "Reduced", "Reverse-engineered", "Right-sized", "Robust", "Seamless", "Secured", "Self-enabling", "Sharable", "Stand-alone", "Streamlined", "Switchable", "Synchronised", "Synergistic", "Synergized", "Team-oriented", "Total", "Triple-buffered", "Universal", "Up-sized", "Upgradable", "User-centric", "User-friendly", "Versatile", "Virtual", "Vision-oriented", "Visionary", "24 hour", "24/7", "3rd generation", "4th generation", "5th generation", "6th generation", "actuating", "analyzing", "asymmetric", "asynchronous", "attitude-oriented", "background", "bandwidth-monitored", "bi-directional", "bifurcated", "bottom-line", "clear-thinking", "client-driven", "client-server", "coherent", "cohesive", "composite", "content-based", "context-sensitive", "contextually-based", "dedicated", "demand-driven", "didactic", "directional", "discrete", "disintermediate", "dynamic", "eco-centric", "empowering", "encompassing", "even-keeled", "executive", "explicit", "exuding", "fault-tolerant", "foreground", "fresh-thinking", "full-range", "global", "grid-enabled", "heuristic", "high-level", "holistic", "homogeneous", "human-resource", "hybrid", "impactful", "incremental", "intangible", "interactive", "intermediate", "leading edge", "local", "logistical", "maximized", "methodical", "mission-critical", "mobile", "modular", "motivating", "multi-state", "multi-tasking", "multimedia", "national", "needs-based", "neutral", "next generation", "non-volatile", "object-oriented", "optimal", "optimizing", "radical", "real-time", "reciprocal", "regional", "responsive", "scalable", "secondary", "solution-oriented", "stable", "static", "system-worthy", "systematic", "systemic", "tangible", "tertiary", "transitional", "uniform", "upward-trending", "user-facing", "value-added", "web-enabled", "well-modulated", "zero administration", "zero defect", "zero tolerance", "Graphic Interface", "Graphical User Interface", "ability", "access", "adapter", "algorithm", "alliance", "analyzer", "application", "approach", "architecture", "archive", "array", "artificial intelligence", "attitude", "benchmark", "budgetary management", "capability", "capacity", "challenge", "circuit", "collaboration", "complexity", "concept", "conglomeration", "contingency", "core", "customer loyalty", "data-warehouse", "database", "definition", "emulation", "encoding", "encryption", "extranet", "firmware", "flexibility", "focus group", "forecast", "frame", "framework", "function", "functionalities", "groupware", "hardware", "help-desk", "hierarchy", "hub", "implementation", "info-mediaries", "infrastructure", "initiative", "installation", "instruction set", "interface", "internet solution", "intranet", "knowledge base", "knowledge user", "leverage", "local area network", "matrices", "matrix", "methodology", "middleware", "migration", "model", "moderator", "monitoring", "moratorium", "neural-net", "open architecture", "open system", "orchestration", "paradigm", "parallelism", "policy", "portal", "pricing structure", "process improvement", "product", "productivity", "project", "projection", "protocol", "secured line", "service-desk", "software", "solution", "standardization", "strategy", "structure", "success", "superstructure", "support", "synergy", "system engine", "task-force", "throughput", "time-frame", "toolset", "utilisation", "website", "workforce"}, "bs": {"aggregate", "architect", "benchmark", "brand", "cultivate", "deliver", "deploy", "disintermediate", "drive", "e-enable", "embrace", "empower", "enable", "engage", "engineer", "enhance", "envisioneer", "evolve", "expedite", "exploit", "extend", "facilitate", "generate", "grow", "harness", "implement", "incentivize", "incubate", "innovate", "integrate", "iterate", "leverage", "matrix", "maximize", "mesh", "monetize", "morph", "optimize", "orchestrate", "productize", "recontextualize", "redefine", "reintermediate", "reinvent", "repurpose", "revolutionize", "scale", "seize", "strategize", "streamline", "syndicate", "synergize", "synthesize", "target", "transform", "transition", "unleash", "utilize", "visualize", "whiteboard", "24-365", "24-7", "B2B", "B2C", "back-end", "best-of-breed", "bleeding-edge", "bricks-and-clicks", "clicks-and-mortar", "collaborative", "compelling", "cross-media", "cross-platform", "customized", "cutting-edge", "distributed", "dot-com", "dynamic", "e-business", "efficient", "end-to-end", "enterprise", "extensible", "frictionless", "front-end", "global", "granular", "holistic", "impactful", "innovative", "integrated", "interactive", "intuitive", "killer", "leading-edge", "magnetic", "mission-critical", "next-generation", "one-to-one", "open-source", "out-of-the-box", "plug-and-play", "proactive", "real-time", "revolutionary", "rich", "robust", "scalable", "seamless", "sexy", "sticky", "strategic", "synergistic", "transparent", "turn-key", "ubiquitous", "user-centric", "value-added", "vertical", "viral", "virtual", "visionary", "web-enabled", "wireless", "world-class", "ROI", "action-items", "applications", "architectures", "bandwidth", "channels", "communities", "content", "convergence", "deliverables", "e-business", "e-commerce", "e-markets", "e-services", "e-tailers", "experiences", "eyeballs", "functionalities", "infomediaries", "infrastructures", "initiatives", "interfaces", "markets", "methodologies", "metrics", "mindshare", "models", "networks", "niches", "paradigms", "partnerships", "platforms", "portals", "relationships", "schemas", "solutions", "supply-chains", "synergies", "systems", "technologies", "users", "vortals", "web services", "web-readiness"}, + "blurb": {"Advancement", "Advantage", "Ambition", "Balance", "Belief", "Benefits", "Care", "Challenge", "Change", "Choice", "Commitment", "Comfort", "Connection", "Consistency", "Creativity", "Dedication", "Discovery", "Diversity", "Dream", "Dreams", "Drive", "Ease", "Efficiency", "Empowerment", "Endurance", "Energy", "Engagement", "Environment", "Enterprise", "Excellence", "Exclusivity", "Experience", "Exploration", "Expression", "Family", "Flexibility", "Focus", "Freedom", "Future", "Future", "Growth", "Harmony", "Health", "Heart", "History", "Home", "Honesty", "Hope", "Impact", "Innovation", "Inspiration", "Integrity", "Joy", "Journey", "Knowledge", "Leadership", "Legacy", "Life", "Luxury", "Money", "Motivation", "Optimism", "Partnership", "Passion", "Peace", "People", "Performance", "Perseverance", "Pleasure", "Power", "Pride", "Progress", "Promise", "Quality", "Quality", "Reliability", "Resilience", "Respect", "Revolution", "Safety", "Service", "Simplicity", "Solutions", "Solidarity", "Strength", "Style", "Success", "Sustainability", "Taste", "Teamwork", "Technology", "Time", "Transformation", "Trust", "Unity", "Value", "Versatility", "Vision", "Wellness", "World"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/data.go b/vendor/github.com/brianvoe/gofakeit/v6/data/data.go index 6e1701bea..51a4f496b 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/data.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/data.go @@ -26,6 +26,12 @@ var Data = map[string]map[string][]string{ "food": Food, "minecraft": Minecraft, "celebrity": Celebrity, + "error": Error, + "html": Html, + "book": Books, + "movie": Movies, + "school": School, + "product": Product, } func List() map[string][]string { diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go b/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go index a29e438f8..08a5f86ad 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go @@ -5,7 +5,7 @@ var Hacker = map[string][]string{ "abbreviation": {"TCP", "HTTP", "SDD", "RAM", "GB", "CSS", "SSL", "AGP", "SQL", "FTP", "PCI", "AI", "ADP", "RSS", "XML", "EXE", "COM", "HDD", "THX", "SMTP", "SMS", "USB", "PNG", "SAS", "IB", "SCSI", "JSON", "XSS", "JBOD"}, "adjective": {"auxiliary", "primary", "back-end", "digital", "open-source", "virtual", "cross-platform", "redundant", "online", "haptic", "multi-byte", "bluetooth", "wireless", "1080p", "neural", "optical", "solid state", "mobile"}, "noun": {"driver", "protocol", "bandwidth", "panel", "microchip", "program", "port", "card", "array", "interface", "system", "sensor", "firewall", "hard drive", "pixel", "alarm", "feed", "monitor", "application", "transmitter", "bus", "circuit", "capacitor", "matrix"}, - "verb": {"back up", "bypass", "hack", "override", "compress", "copy", "navigate", "index", "connect", "generate", "quantify", "calculate", "synthesize", "input", "transmit", "program", "reboot", "parse"}, + "verb": {"back up", "bypass", "hack", "override", "compress", "copy", "navigate", "index", "connect", "generate", "quantify", "calculate", "synthesize", "input", "transmit", "program", "reboot", "parse", "read", "write", "load", "render", "validate", "verify", "sign", "decrypt", "encrypt", "construct", "deconstruct", "compile", "transpile", "bundle", "lock", "unlock", "buffer", "format"}, "ingverb": {"backing up", "bypassing", "hacking", "overriding", "compressing", "copying", "navigating", "indexing", "connecting", "generating", "quantifying", "calculating", "synthesizing", "transmitting", "programming", "parsing"}, "phrase": { "If we {hackerverb} the {hackernoun}, we can get to the {hackerabbreviation} {hackernoun} through the {hackeradjective} {hackerabbreviation} {hackernoun}!", diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/person.go b/vendor/github.com/brianvoe/gofakeit/v6/data/person.go index 0930c65e4..8f65a16bf 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/person.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/person.go @@ -5,6 +5,7 @@ var Person = map[string][]string{ "prefix": {"Mr.", "Mrs.", "Ms.", "Miss", "Dr."}, "suffix": {"Jr.", "Sr.", "I", "II", "III", "IV", "V", "MD", "DDS", "PhD", "DVM"}, "first": {"Aaliyah", "Aaron", "Abagail", "Abbey", "Abbie", "Abbigail", "Abby", "Abdiel", "Abdul", "Abdullah", "Abe", "Abel", "Abelardo", "Abigail", "Abigale", "Abigayle", "Abner", "Abraham", "Ada", "Adah", "Adalberto", "Adaline", "Adam", "Adan", "Addie", "Addison", "Adela", "Adelbert", "Adele", "Adelia", "Adeline", "Adell", "Adella", "Adelle", "Aditya", "Adolf", "Adolfo", "Adolph", "Adolphus", "Adonis", "Adrain", "Adrian", "Adriana", "Adrianna", "Adriel", "Adrien", "Adrienne", "Afton", "Aglae", "Agnes", "Agustin", "Agustina", "Ahmad", "Ahmed", "Aida", "Aidan", "Aiden", "Aileen", "Aimee", "Aisha", "Aiyana", "Akeem", "Al", "Alaina", "Alan", "Alana", "Alanis", "Alanna", "Alayna", "Alba", "Albert", "Alberta", "Albertha", "Alberto", "Albin", "Albina", "Alda", "Alden", "Alec", "Aleen", "Alejandra", "Alejandrin", "Alek", "Alena", "Alene", "Alessandra", "Alessandro", "Alessia", "Aletha", "Alex", "Alexa", "Alexander", "Alexandra", "Alexandre", "Alexandrea", "Alexandria", "Alexandrine", "Alexandro", "Alexane", "Alexanne", "Alexie", "Alexis", "Alexys", "Alexzander", "Alf", "Alfonso", "Alfonzo", "Alford", "Alfred", "Alfreda", "Alfredo", "Ali", "Alia", "Alice", "Alicia", "Alisa", "Alisha", "Alison", "Alivia", "Aliya", "Aliyah", "Aliza", "Alize", "Allan", "Allen", "Allene", "Allie", "Allison", "Ally", "Alphonso", "Alta", "Althea", "Alva", "Alvah", "Alvena", "Alvera", "Alverta", "Alvina", "Alvis", "Alyce", "Alycia", "Alysa", "Alysha", "Alyson", "Alysson", "Amalia", "Amanda", "Amani", "Amara", "Amari", "Amaya", "Amber", "Ambrose", "Amelia", "Amelie", "Amely", "America", "Americo", "Amie", "Amina", "Amir", "Amira", "Amiya", "Amos", "Amparo", "Amy", "Amya", "Ana", "Anabel", "Anabelle", "Anahi", "Anais", "Anastacio", "Anastasia", "Anderson", "Andre", "Andreane", "Andreanne", "Andres", "Andrew", "Andy", "Angel", "Angela", "Angelica", "Angelina", "Angeline", "Angelita", "Angelo", "Angie", "Angus", "Anibal", "Anika", "Anissa", "Anita", "Aniya", "Aniyah", "Anjali", "Anna", "Annabel", "Annabell", "Annabelle", "Annalise", "Annamae", "Annamarie", "Anne", "Annetta", "Annette", "Annie", "Ansel", "Ansley", "Anthony", "Antoinette", "Antone", "Antonetta", "Antonette", "Antonia", "Antonietta", "Antonina", "Antonio", "Antwan", "Antwon", "Anya", "April", "Ara", "Araceli", "Aracely", "Arch", "Archibald", "Ardella", "Arden", "Ardith", "Arely", "Ari", "Ariane", "Arianna", "Aric", "Ariel", "Arielle", "Arjun", "Arlene", "Arlie", "Arlo", "Armand", "Armando", "Armani", "Arnaldo", "Arne", "Arno", "Arnold", "Arnoldo", "Arnulfo", "Aron", "Art", "Arthur", "Arturo", "Arvel", "Arvid", "Arvilla", "Aryanna", "Asa", "Asha", "Ashlee", "Ashleigh", "Ashley", "Ashly", "Ashlynn", "Ashton", "Ashtyn", "Asia", "Assunta", "Astrid", "Athena", "Aubree", "Aubrey", "Audie", "Audra", "Audreanne", "Audrey", "August", "Augusta", "Augustine", "Augustus", "Aurelia", "Aurelie", "Aurelio", "Aurore", "Austen", "Austin", "Austyn", "Autumn", "Ava", "Avery", "Avis", "Axel", "Ayana", "Ayden", "Ayla", "Aylin", "Baby", "Bailee", "Bailey", "Barbara", "Barney", "Baron", "Barrett", "Barry", "Bart", "Bartholome", "Barton", "Baylee", "Beatrice", "Beau", "Beaulah", "Bell", "Bella", "Belle", "Ben", "Benedict", "Benjamin", "Bennett", "Bennie", "Benny", "Benton", "Berenice", "Bernadette", "Bernadine", "Bernard", "Bernardo", "Berneice", "Bernhard", "Bernice", "Bernie", "Berniece", "Bernita", "Berry", "Bert", "Berta", "Bertha", "Bertram", "Bertrand", "Beryl", "Bessie", "Beth", "Bethany", "Bethel", "Betsy", "Bette", "Bettie", "Betty", "Bettye", "Beulah", "Beverly", "Bianka", "Bill", "Billie", "Billy", "Birdie", "Blair", "Blaise", "Blake", "Blanca", "Blanche", "Blaze", "Bo", "Bobbie", "Bobby", "Bonita", "Bonnie", "Boris", "Boyd", "Brad", "Braden", "Bradford", "Bradley", "Bradly", "Brady", "Braeden", "Brain", "Brandi", "Brando", "Brandon", "Brandt", "Brandy", "Brandyn", "Brannon", "Branson", "Brant", "Braulio", "Braxton", "Brayan", "Breana", "Breanna", "Breanne", "Brenda", "Brendan", "Brenden", "Brendon", "Brenna", "Brennan", "Brennon", "Brent", "Bret", "Brett", "Bria", "Brian", "Briana", "Brianne", "Brice", "Bridget", "Bridgette", "Bridie", "Brielle", "Brigitte", "Brionna", "Brisa", "Britney", "Brittany", "Brock", "Broderick", "Brody", "Brook", "Brooke", "Brooklyn", "Brooks", "Brown", "Bruce", "Bryana", "Bryce", "Brycen", "Bryon", "Buck", "Bud", "Buddy", "Buford", "Bulah", "Burdette", "Burley", "Burnice", "Buster", "Cade", "Caden", "Caesar", "Caitlyn", "Cale", "Caleb", "Caleigh", "Cali", "Calista", "Callie", "Camden", "Cameron", "Camila", "Camilla", "Camille", "Camren", "Camron", "Camryn", "Camylle", "Candace", "Candelario", "Candice", "Candida", "Candido", "Cara", "Carey", "Carissa", "Carlee", "Carleton", "Carley", "Carli", "Carlie", "Carlo", "Carlos", "Carlotta", "Carmel", "Carmela", "Carmella", "Carmelo", "Carmen", "Carmine", "Carol", "Carolanne", "Carole", "Carolina", "Caroline", "Carolyn", "Carolyne", "Carrie", "Carroll", "Carson", "Carter", "Cary", "Casandra", "Casey", "Casimer", "Casimir", "Casper", "Cassandra", "Cassandre", "Cassidy", "Cassie", "Catalina", "Caterina", "Catharine", "Catherine", "Cathrine", "Cathryn", "Cathy", "Cayla", "Ceasar", "Cecelia", "Cecil", "Cecile", "Cecilia", "Cedrick", "Celestine", "Celestino", "Celia", "Celine", "Cesar", "Chad", "Chadd", "Chadrick", "Chaim", "Chance", "Chandler", "Chanel", "Chanelle", "Charity", "Charlene", "Charles", "Charley", "Charlie", "Charlotte", "Chase", "Chasity", "Chauncey", "Chaya", "Chaz", "Chelsea", "Chelsey", "Chelsie", "Chesley", "Chester", "Chet", "Cheyanne", "Cheyenne", "Chloe", "Chris", "Christ", "Christa", "Christelle", "Christian", "Christiana", "Christina", "Christine", "Christop", "Christophe", "Christopher", "Christy", "Chyna", "Ciara", "Cicero", "Cielo", "Cierra", "Cindy", "Citlalli", "Clair", "Claire", "Clara", "Clarabelle", "Clare", "Clarissa", "Clark", "Claud", "Claude", "Claudia", "Claudie", "Claudine", "Clay", "Clemens", "Clement", "Clementina", "Clementine", "Clemmie", "Cleo", "Cleora", "Cleta", "Cletus", "Cleve", "Cleveland", "Clifford", "Clifton", "Clint", "Clinton", "Clotilde", "Clovis", "Cloyd", "Clyde", "Coby", "Cody", "Colby", "Cole", "Coleman", "Colin", "Colleen", "Collin", "Colt", "Colten", "Colton", "Columbus", "Concepcion", "Conner", "Connie", "Connor", "Conor", "Conrad", "Constance", "Constantin", "Consuelo", "Cooper", "Cora", "Coralie", "Corbin", "Cordelia", "Cordell", "Cordia", "Cordie", "Corene", "Corine", "Cornelius", "Cornell", "Corrine", "Cortez", "Cortney", "Cory", "Coty", "Courtney", "Coy", "Craig", "Crawford", "Creola", "Cristal", "Cristian", "Cristina", "Cristobal", "Cristopher", "Cruz", "Crystal", "Crystel", "Cullen", "Curt", "Curtis", "Cydney", "Cynthia", "Cyril", "Cyrus", "Dagmar", "Dahlia", "Daija", "Daisha", "Daisy", "Dakota", "Dale", "Dallas", "Dallin", "Dalton", "Damaris", "Dameon", "Damian", "Damien", "Damion", "Damon", "Dan", "Dana", "Dandre", "Dane", "Dangelo", "Dangelo", "Danial", "Daniela", "Daniella", "Danielle", "Danika", "Dannie", "Danny", "Dante", "Danyka", "Daphne", "Daphnee", "Daphney", "Darby", "Daren", "Darian", "Dariana", "Darien", "Dario", "Darion", "Darius", "Darlene", "Daron", "Darrel", "Darrell", "Darren", "Darrick", "Darrin", "Darrion", "Darron", "Darryl", "Darwin", "Daryl", "Dashawn", "Dasia", "Dave", "David", "Davin", "Davion", "Davon", "Davonte", "Dawn", "Dawson", "Dax", "Dayana", "Dayna", "Dayne", "Dayton", "Dean", "Deangelo", "Deanna", "Deborah", "Declan", "Dedric", "Dedrick", "Dee", "Deion", "Deja", "Dejah", "Dejon", "Dejuan", "Delaney", "Delbert", "Delfina", "Delia", "Delilah", "Dell", "Della", "Delmer", "Delores", "Delpha", "Delphia", "Delphine", "Delta", "Demarco", "Demarcus", "Demario", "Demetris", "Demetrius", "Demond", "Dena", "Denis", "Dennis", "Deon", "Deondre", "Deontae", "Deonte", "Dereck", "Derek", "Derick", "Deron", "Derrick", "Deshaun", "Deshawn", "Desiree", "Desmond", "Dessie", "Destany", "Destin", "Destinee", "Destiney", "Destini", "Destiny", "Devan", "Devante", "Deven", "Devin", "Devon", "Devonte", "Devyn", "Dewayne", "Dewitt", "Dexter", "Diamond", "Diana", "Dianna", "Diego", "Dillan", "Dillon", "Dimitri", "Dina", "Dino", "Dion", "Dixie", "Dock", "Dolly", "Dolores", "Domenic", "Domenica", "Domenick", "Domenico", "Domingo", "Dominic", "Dominique", "Don", "Donald", "Donato", "Donavon", "Donna", "Donnell", "Donnie", "Donny", "Dora", "Dorcas", "Dorian", "Doris", "Dorothea", "Dorothy", "Dorris", "Dortha", "Dorthy", "Doug", "Douglas", "Dovie", "Doyle", "Drake", "Drew", "Duane", "Dudley", "Dulce", "Duncan", "Durward", "Dustin", "Dusty", "Dwight", "Dylan", "Earl", "Earlene", "Earline", "Earnest", "Earnestine", "Easter", "Easton", "Ebba", "Ebony", "Ed", "Eda", "Edd", "Eddie", "Eden", "Edgar", "Edgardo", "Edison", "Edmond", "Edmund", "Edna", "Eduardo", "Edward", "Edwardo", "Edwin", "Edwina", "Edyth", "Edythe", "Effie", "Efrain", "Efren", "Eileen", "Einar", "Eino", "Eladio", "Elaina", "Elbert", "Elda", "Eldon", "Eldora", "Eldred", "Eldridge", "Eleanora", "Eleanore", "Eleazar", "Electa", "Elena", "Elenor", "Elenora", "Eleonore", "Elfrieda", "Eli", "Elian", "Eliane", "Elias", "Eliezer", "Elijah", "Elinor", "Elinore", "Elisa", "Elisabeth", "Elise", "Eliseo", "Elisha", "Elissa", "Eliza", "Elizabeth", "Ella", "Ellen", "Ellie", "Elliot", "Elliott", "Ellis", "Ellsworth", "Elmer", "Elmira", "Elmo", "Elmore", "Elna", "Elnora", "Elody", "Eloisa", "Eloise", "Elouise", "Eloy", "Elroy", "Elsa", "Else", "Elsie", "Elta", "Elton", "Elva", "Elvera", "Elvie", "Elvis", "Elwin", "Elwyn", "Elyse", "Elyssa", "Elza", "Emanuel", "Emelia", "Emelie", "Emely", "Emerald", "Emerson", "Emery", "Emie", "Emil", "Emile", "Emilia", "Emiliano", "Emilie", "Emilio", "Emily", "Emma", "Emmalee", "Emmanuel", "Emmanuelle", "Emmet", "Emmett", "Emmie", "Emmitt", "Emmy", "Emory", "Ena", "Enid", "Enoch", "Enola", "Enos", "Enrico", "Enrique", "Ephraim", "Era", "Eriberto", "Eric", "Erica", "Erich", "Erick", "Ericka", "Erik", "Erika", "Erin", "Erling", "Erna", "Ernest", "Ernestina", "Ernestine", "Ernesto", "Ernie", "Ervin", "Erwin", "Eryn", "Esmeralda", "Esperanza", "Esta", "Esteban", "Estefania", "Estel", "Estell", "Estella", "Estelle", "Estevan", "Esther", "Estrella", "Etha", "Ethan", "Ethel", "Ethelyn", "Ethyl", "Ettie", "Eudora", "Eugene", "Eugenia", "Eula", "Eulah", "Eulalia", "Euna", "Eunice", "Eusebio", "Eva", "Evalyn", "Evan", "Evangeline", "Evans", "Eve", "Eveline", "Evelyn", "Everardo", "Everett", "Everette", "Evert", "Evie", "Ewald", "Ewell", "Ezekiel", "Ezequiel", "Ezra", "Fabian", "Fabiola", "Fae", "Fannie", "Fanny", "Fatima", "Faustino", "Fausto", "Favian", "Fay", "Faye", "Federico", "Felicia", "Felicita", "Felicity", "Felipa", "Felipe", "Felix", "Felton", "Fermin", "Fern", "Fernando", "Ferne", "Fidel", "Filiberto", "Filomena", "Finn", "Fiona", "Flavie", "Flavio", "Fleta", "Fletcher", "Flo", "Florence", "Florencio", "Florian", "Florida", "Florine", "Flossie", "Floy", "Floyd", "Ford", "Forest", "Forrest", "Foster", "Frances", "Francesca", "Francesco", "Francis", "Francisca", "Francisco", "Franco", "Frank", "Frankie", "Franz", "Fred", "Freda", "Freddie", "Freddy", "Frederic", "Frederick", "Frederik", "Frederique", "Fredrick", "Fredy", "Freeda", "Freeman", "Freida", "Frida", "Frieda", "Friedrich", "Fritz", "Furman", "Gabe", "Gabriel", "Gabriella", "Gabrielle", "Gaetano", "Gage", "Gail", "Gardner", "Garett", "Garfield", "Garland", "Garnet", "Garnett", "Garret", "Garrett", "Garrick", "Garrison", "Garry", "Garth", "Gaston", "Gavin", "Gay", "Gayle", "Gaylord", "Gene", "General", "Genesis", "Genevieve", "Gennaro", "Genoveva", "Geo", "Geoffrey", "George", "Georgette", "Georgiana", "Georgianna", "Geovanni", "Geovanny", "Geovany", "Gerald", "Geraldine", "Gerard", "Gerardo", "Gerda", "Gerhard", "Germaine", "German", "Gerry", "Gerson", "Gertrude", "Gia", "Gianni", "Gideon", "Gilbert", "Gilberto", "Gilda", "Giles", "Gillian", "Gina", "Gino", "Giovani", "Giovanna", "Giovanni", "Giovanny", "Gisselle", "Giuseppe", "Gladyce", "Gladys", "Glen", "Glenda", "Glenna", "Glennie", "Gloria", "Godfrey", "Golda", "Golden", "Gonzalo", "Gordon", "Grace", "Gracie", "Graciela", "Grady", "Graham", "Grant", "Granville", "Grayce", "Grayson", "Green", "Greg", "Gregg", "Gregoria", "Gregorio", "Gregory", "Greta", "Gretchen", "Greyson", "Griffin", "Grover", "Guadalupe", "Gudrun", "Guido", "Guillermo", "Guiseppe", "Gunnar", "Gunner", "Gus", "Gussie", "Gust", "Gustave", "Guy", "Gwen", "Gwendolyn", "Hadley", "Hailee", "Hailey", "Hailie", "Hal", "Haleigh", "Haley", "Halie", "Halle", "Hallie", "Hank", "Hanna", "Hannah", "Hans", "Hardy", "Harley", "Harmon", "Harmony", "Harold", "Harrison", "Harry", "Harvey", "Haskell", "Hassan", "Hassie", "Hattie", "Haven", "Hayden", "Haylee", "Hayley", "Haylie", "Hazel", "Hazle", "Heath", "Heather", "Heaven", "Heber", "Hector", "Heidi", "Helen", "Helena", "Helene", "Helga", "Hellen", "Helmer", "Heloise", "Henderson", "Henri", "Henriette", "Henry", "Herbert", "Herman", "Hermann", "Hermina", "Herminia", "Herminio", "Hershel", "Herta", "Hertha", "Hester", "Hettie", "Hilario", "Hilbert", "Hilda", "Hildegard", "Hillard", "Hillary", "Hilma", "Hilton", "Hipolito", "Hiram", "Hobart", "Holden", "Hollie", "Hollis", "Holly", "Hope", "Horace", "Horacio", "Hortense", "Hosea", "Houston", "Howard", "Howell", "Hoyt", "Hubert", "Hudson", "Hugh", "Hulda", "Humberto", "Hunter", "Hyman", "Ian", "Ibrahim", "Icie", "Ida", "Idell", "Idella", "Ignacio", "Ignatius", "Ike", "Ila", "Ilene", "Iliana", "Ima", "Imani", "Imelda", "Immanuel", "Imogene", "Ines", "Irma", "Irving", "Irwin", "Isaac", "Isabel", "Isabell", "Isabella", "Isabelle", "Isac", "Isadore", "Isai", "Isaiah", "Isaias", "Isidro", "Ismael", "Isobel", "Isom", "Israel", "Issac", "Itzel", "Iva", "Ivah", "Ivory", "Ivy", "Izabella", "Izaiah", "Jabari", "Jace", "Jacey", "Jacinthe", "Jacinto", "Jack", "Jackeline", "Jackie", "Jacklyn", "Jackson", "Jacky", "Jaclyn", "Jacquelyn", "Jacques", "Jacynthe", "Jada", "Jade", "Jaden", "Jadon", "Jadyn", "Jaeden", "Jaida", "Jaiden", "Jailyn", "Jaime", "Jairo", "Jakayla", "Jake", "Jakob", "Jaleel", "Jalen", "Jalon", "Jalyn", "Jamaal", "Jamal", "Jamar", "Jamarcus", "Jamel", "Jameson", "Jamey", "Jamie", "Jamil", "Jamir", "Jamison", "Jammie", "Jan", "Jana", "Janae", "Jane", "Janelle", "Janessa", "Janet", "Janice", "Janick", "Janie", "Janis", "Janiya", "Jannie", "Jany", "Jaquan", "Jaquelin", "Jaqueline", "Jared", "Jaren", "Jarod", "Jaron", "Jarred", "Jarrell", "Jarret", "Jarrett", "Jarrod", "Jarvis", "Jasen", "Jasmin", "Jason", "Jasper", "Jaunita", "Javier", "Javon", "Javonte", "Jay", "Jayce", "Jaycee", "Jayda", "Jayde", "Jayden", "Jaydon", "Jaylan", "Jaylen", "Jaylin", "Jaylon", "Jayme", "Jayne", "Jayson", "Jazlyn", "Jazmin", "Jazmyn", "Jazmyne", "Jean", "Jeanette", "Jeanie", "Jeanne", "Jed", "Jedediah", "Jedidiah", "Jeff", "Jefferey", "Jeffery", "Jeffrey", "Jeffry", "Jena", "Jenifer", "Jennie", "Jennifer", "Jennings", "Jennyfer", "Jensen", "Jerad", "Jerald", "Jeramie", "Jeramy", "Jerel", "Jeremie", "Jeremy", "Jermain", "Jermaine", "Jermey", "Jerod", "Jerome", "Jeromy", "Jerrell", "Jerrod", "Jerrold", "Jerry", "Jess", "Jesse", "Jessica", "Jessie", "Jessika", "Jessy", "Jessyca", "Jesus", "Jett", "Jettie", "Jevon", "Jewel", "Jewell", "Jillian", "Jimmie", "Jimmy", "Jo", "Joan", "Joana", "Joanie", "Joanne", "Joannie", "Joanny", "Joany", "Joaquin", "Jocelyn", "Jodie", "Jody", "Joe", "Joel", "Joelle", "Joesph", "Joey", "Johan", "Johann", "Johanna", "Johathan", "John", "Johnathan", "Johnathon", "Johnnie", "Johnny", "Johnpaul", "Johnson", "Jolie", "Jon", "Jonas", "Jonatan", "Jonathan", "Jonathon", "Jordan", "Jordane", "Jordi", "Jordon", "Jordy", "Jordyn", "Jorge", "Jose", "Josefa", "Josefina", "Joseph", "Josephine", "Josh", "Joshua", "Joshuah", "Josiah", "Josiane", "Josianne", "Josie", "Josue", "Jovan", "Jovani", "Jovanny", "Jovany", "Joy", "Joyce", "Juana", "Juanita", "Judah", "Judd", "Jude", "Judge", "Judson", "Judy", "Jules", "Julia", "Julian", "Juliana", "Julianne", "Julie", "Julien", "Juliet", "Julio", "Julius", "June", "Junior", "Junius", "Justen", "Justice", "Justina", "Justine", "Juston", "Justus", "Justyn", "Juvenal", "Juwan", "Kacey", "Kaci", "Kacie", "Kade", "Kaden", "Kadin", "Kaela", "Kaelyn", "Kaia", "Kailee", "Kailey", "Kailyn", "Kaitlin", "Kaitlyn", "Kale", "Kaleb", "Kaleigh", "Kaley", "Kali", "Kallie", "Kameron", "Kamille", "Kamren", "Kamron", "Kamryn", "Kane", "Kara", "Kareem", "Karelle", "Karen", "Kari", "Kariane", "Karianne", "Karina", "Karine", "Karl", "Karlee", "Karley", "Karli", "Karlie", "Karolann", "Karson", "Kasandra", "Kasey", "Kassandra", "Katarina", "Katelin", "Katelyn", "Katelynn", "Katharina", "Katherine", "Katheryn", "Kathleen", "Kathlyn", "Kathryn", "Kathryne", "Katlyn", "Katlynn", "Katrina", "Katrine", "Kattie", "Kavon", "Kay", "Kaya", "Kaycee", "Kayden", "Kayla", "Kaylah", "Kaylee", "Kayleigh", "Kayley", "Kayli", "Kaylie", "Kaylin", "Keagan", "Keanu", "Keara", "Keaton", "Keegan", "Keeley", "Keely", "Keenan", "Keira", "Keith", "Kellen", "Kelley", "Kelli", "Kellie", "Kelly", "Kelsi", "Kelsie", "Kelton", "Kelvin", "Ken", "Kendall", "Kendra", "Kendrick", "Kenna", "Kennedi", "Kennedy", "Kenneth", "Kennith", "Kenny", "Kenton", "Kenya", "Kenyatta", "Kenyon", "Keon", "Keshaun", "Keshawn", "Keven", "Kevin", "Kevon", "Keyon", "Keyshawn", "Khalid", "Khalil", "Kian", "Kiana", "Kianna", "Kiara", "Kiarra", "Kiel", "Kiera", "Kieran", "Kiley", "Kim", "Kimberly", "King", "Kip", "Kira", "Kirk", "Kirsten", "Kirstin", "Kitty", "Kobe", "Koby", "Kody", "Kolby", "Kole", "Korbin", "Korey", "Kory", "Kraig", "Kris", "Krista", "Kristian", "Kristin", "Kristina", "Kristofer", "Kristoffer", "Kristopher", "Kristy", "Krystal", "Krystel", "Krystina", "Kurt", "Kurtis", "Kyla", "Kyle", "Kylee", "Kyleigh", "Kyler", "Kylie", "Kyra", "Lacey", "Lacy", "Ladarius", "Lafayette", "Laila", "Laisha", "Lamar", "Lambert", "Lamont", "Lance", "Landen", "Lane", "Laney", "Larissa", "Laron", "Larry", "Larue", "Laura", "Laurel", "Lauren", "Laurence", "Lauretta", "Lauriane", "Laurianne", "Laurie", "Laurine", "Laury", "Lauryn", "Lavada", "Lavern", "Laverna", "Laverne", "Lavina", "Lavinia", "Lavon", "Lavonne", "Lawrence", "Lawson", "Layla", "Layne", "Lazaro", "Lea", "Leann", "Leanna", "Leanne", "Leatha", "Leda", "Lee", "Leif", "Leila", "Leilani", "Lela", "Lelah", "Leland", "Lelia", "Lempi", "Lemuel", "Lenna", "Lennie", "Lenny", "Lenora", "Lenore", "Leo", "Leola", "Leon", "Leonard", "Leonardo", "Leone", "Leonel", "Leonie", "Leonor", "Leonora", "Leopold", "Leopoldo", "Leora", "Lera", "Lesley", "Leslie", "Lesly", "Lessie", "Lester", "Leta", "Letha", "Letitia", "Levi", "Lew", "Lewis", "Lexi", "Lexie", "Lexus", "Lia", "Liam", "Liana", "Libbie", "Libby", "Lila", "Lilian", "Liliana", "Liliane", "Lilla", "Lillian", "Lilliana", "Lillie", "Lilly", "Lily", "Lilyan", "Lina", "Lincoln", "Linda", "Lindsay", "Lindsey", "Linnea", "Linnie", "Linwood", "Lionel", "Lisa", "Lisandro", "Lisette", "Litzy", "Liza", "Lizeth", "Lizzie", "Llewellyn", "Lloyd", "Logan", "Lois", "Lola", "Lolita", "Loma", "Lon", "London", "Lonie", "Lonnie", "Lonny", "Lonzo", "Lora", "Loraine", "Loren", "Lorena", "Lorenz", "Lorenza", "Lorenzo", "Lori", "Lorine", "Lorna", "Lottie", "Lou", "Louie", "Louisa", "Lourdes", "Louvenia", "Lowell", "Loy", "Loyal", "Loyce", "Lucas", "Luciano", "Lucie", "Lucienne", "Lucile", "Lucinda", "Lucio", "Lucious", "Lucius", "Lucy", "Ludie", "Ludwig", "Lue", "Luella", "Luigi", "Luis", "Luisa", "Lukas", "Lula", "Lulu", "Luna", "Lupe", "Lura", "Lurline", "Luther", "Luz", "Lyda", "Lydia", "Lyla", "Lynn", "Lyric", "Lysanne", "Mabel", "Mabelle", "Mable", "Mac", "Macey", "Maci", "Macie", "Mack", "Mackenzie", "Macy", "Madaline", "Madalyn", "Maddison", "Madeline", "Madelyn", "Madelynn", "Madge", "Madie", "Madilyn", "Madisen", "Madison", "Madisyn", "Madonna", "Madyson", "Mae", "Maegan", "Maeve", "Mafalda", "Magali", "Magdalen", "Magdalena", "Maggie", "Magnolia", "Magnus", "Maia", "Maida", "Maiya", "Major", "Makayla", "Makenna", "Makenzie", "Malachi", "Malcolm", "Malika", "Malinda", "Mallie", "Mallory", "Malvina", "Mandy", "Manley", "Manuel", "Manuela", "Mara", "Marc", "Marcel", "Marcelina", "Marcelino", "Marcella", "Marcelle", "Marcellus", "Marcelo", "Marcia", "Marco", "Marcos", "Marcus", "Margaret", "Margarete", "Margarett", "Margaretta", "Margarette", "Margarita", "Marge", "Margie", "Margot", "Margret", "Marguerite", "Maria", "Mariah", "Mariam", "Marian", "Mariana", "Mariane", "Marianna", "Marianne", "Mariano", "Maribel", "Marie", "Mariela", "Marielle", "Marietta", "Marilie", "Marilou", "Marilyne", "Marina", "Mario", "Marion", "Marisa", "Marisol", "Maritza", "Marjolaine", "Marjorie", "Marjory", "Mark", "Markus", "Marlee", "Marlen", "Marlene", "Marley", "Marlin", "Marlon", "Marques", "Marquis", "Marquise", "Marshall", "Marta", "Martin", "Martina", "Martine", "Marty", "Marvin", "Mary", "Maryam", "Maryjane", "Maryse", "Mason", "Mateo", "Mathew", "Mathias", "Mathilde", "Matilda", "Matilde", "Matt", "Matteo", "Mattie", "Maud", "Maude", "Maudie", "Maureen", "Maurice", "Mauricio", "Maurine", "Maverick", "Mavis", "Max", "Maxie", "Maxime", "Maximilian", "Maximillia", "Maximillian", "Maximo", "Maximus", "Maxine", "Maxwell", "May", "Maya", "Maybell", "Maybelle", "Maye", "Maymie", "Maynard", "Mayra", "Mazie", "Mckayla", "Mckenna", "Mckenzie", "Meagan", "Meaghan", "Meda", "Megane", "Meggie", "Meghan", "Mekhi", "Melany", "Melba", "Melisa", "Melissa", "Mellie", "Melody", "Melvin", "Melvina", "Melyna", "Melyssa", "Mercedes", "Meredith", "Merl", "Merle", "Merlin", "Merritt", "Mertie", "Mervin", "Meta", "Mia", "Micaela", "Micah", "Michael", "Michaela", "Michale", "Micheal", "Michel", "Michele", "Michelle", "Miguel", "Mikayla", "Mike", "Mikel", "Milan", "Miles", "Milford", "Miller", "Millie", "Milo", "Milton", "Mina", "Minerva", "Minnie", "Miracle", "Mireille", "Mireya", "Misael", "Missouri", "Misty", "Mitchel", "Mitchell", "Mittie", "Modesta", "Modesto", "Mohamed", "Mohammad", "Mohammed", "Moises", "Mollie", "Molly", "Mona", "Monica", "Monique", "Monroe", "Monserrat", "Monserrate", "Montana", "Monte", "Monty", "Morgan", "Moriah", "Morris", "Mortimer", "Morton", "Mose", "Moses", "Moshe", "Mossie", "Mozell", "Mozelle", "Muhammad", "Muriel", "Murl", "Murphy", "Murray", "Mustafa", "Mya", "Myah", "Mylene", "Myles", "Myra", "Myriam", "Myrl", "Myrna", "Myron", "Myrtice", "Myrtie", "Myrtis", "Myrtle", "Nadia", "Nakia", "Name", "Nannie", "Naomi", "Naomie", "Napoleon", "Narciso", "Nash", "Nasir", "Nat", "Natalia", "Natalie", "Natasha", "Nathan", "Nathanael", "Nathanial", "Nathaniel", "Nathen", "Nayeli", "Neal", "Ned", "Nedra", "Neha", "Neil", "Nelda", "Nella", "Nelle", "Nellie", "Nels", "Nelson", "Neoma", "Nestor", "Nettie", "Neva", "Newell", "Newton", "Nia", "Nicholas", "Nicholaus", "Nichole", "Nick", "Nicklaus", "Nickolas", "Nico", "Nicola", "Nicolas", "Nicole", "Nicolette", "Nigel", "Nikita", "Nikki", "Nikko", "Niko", "Nikolas", "Nils", "Nina", "Noah", "Noble", "Noe", "Noel", "Noelia", "Noemi", "Noemie", "Noemy", "Nola", "Nolan", "Nona", "Nora", "Norbert", "Norberto", "Norene", "Norma", "Norris", "Norval", "Norwood", "Nova", "Novella", "Nya", "Nyah", "Nyasia", "Obie", "Oceane", "Ocie", "Octavia", "Oda", "Odell", "Odessa", "Odie", "Ofelia", "Okey", "Ola", "Olaf", "Ole", "Olen", "Oleta", "Olga", "Olin", "Oliver", "Ollie", "Oma", "Omari", "Omer", "Ona", "Onie", "Opal", "Ophelia", "Ora", "Oral", "Oran", "Oren", "Orie", "Orin", "Orion", "Orland", "Orlando", "Orlo", "Orpha", "Orrin", "Orval", "Orville", "Osbaldo", "Osborne", "Oscar", "Osvaldo", "Oswald", "Oswaldo", "Otha", "Otho", "Otilia", "Otis", "Ottilie", "Ottis", "Otto", "Ova", "Owen", "Ozella", "Pablo", "Paige", "Palma", "Pamela", "Pansy", "Paolo", "Paris", "Parker", "Pascale", "Pasquale", "Pat", "Patience", "Patricia", "Patrick", "Patsy", "Pattie", "Paul", "Paula", "Pauline", "Paxton", "Payton", "Pearl", "Pearlie", "Pearline", "Pedro", "Peggie", "Penelope", "Percival", "Percy", "Perry", "Pete", "Peter", "Petra", "Peyton", "Philip", "Phoebe", "Phyllis", "Pierce", "Pierre", "Pietro", "Pink", "Pinkie", "Piper", "Polly", "Porter", "Precious", "Presley", "Preston", "Price", "Prince", "Princess", "Priscilla", "Providenci", "Prudence", "Queen", "Queenie", "Quentin", "Quincy", "Quinn", "Quinten", "Quinton", "Rachael", "Rachel", "Rachelle", "Rae", "Raegan", "Rafael", "Rafaela", "Raheem", "Rahsaan", "Rahul", "Raina", "Raleigh", "Ralph", "Ramiro", "Ramon", "Ramona", "Randal", "Randall", "Randi", "Randy", "Ransom", "Raoul", "Raphael", "Raphaelle", "Raquel", "Rashad", "Rashawn", "Rasheed", "Raul", "Raven", "Ray", "Raymond", "Raymundo", "Reagan", "Reanna", "Reba", "Rebeca", "Rebecca", "Rebeka", "Rebekah", "Reece", "Reed", "Reese", "Regan", "Reggie", "Reginald", "Reid", "Reilly", "Reina", "Reinhold", "Remington", "Rene", "Renee", "Ressie", "Reta", "Retha", "Retta", "Reuben", "Reva", "Rex", "Rey", "Reyes", "Reymundo", "Reyna", "Reynold", "Rhea", "Rhett", "Rhianna", "Rhiannon", "Rhoda", "Ricardo", "Richard", "Richie", "Richmond", "Rick", "Rickey", "Rickie", "Ricky", "Rico", "Rigoberto", "Riley", "Rita", "River", "Robb", "Robbie", "Robert", "Roberta", "Roberto", "Robin", "Robyn", "Rocio", "Rocky", "Rod", "Roderick", "Rodger", "Rodolfo", "Rodrick", "Rodrigo", "Roel", "Rogelio", "Roger", "Rogers", "Rolando", "Rollin", "Roma", "Romaine", "Roman", "Ron", "Ronaldo", "Ronny", "Roosevelt", "Rory", "Rosa", "Rosalee", "Rosalia", "Rosalind", "Rosalinda", "Rosalyn", "Rosamond", "Rosanna", "Rosario", "Roscoe", "Rose", "Rosella", "Roselyn", "Rosemarie", "Rosemary", "Rosendo", "Rosetta", "Rosie", "Rosina", "Roslyn", "Ross", "Rossie", "Rowan", "Rowena", "Rowland", "Roxane", "Roxanne", "Roy", "Royal", "Royce", "Rozella", "Ruben", "Rubie", "Ruby", "Rubye", "Rudolph", "Rudy", "Rupert", "Russ", "Russel", "Russell", "Rusty", "Ruth", "Ruthe", "Ruthie", "Ryan", "Ryann", "Ryder", "Rylan", "Rylee", "Ryleigh", "Ryley", "Sabina", "Sabrina", "Sabryna", "Sadie", "Sadye", "Sage", "Saige", "Sallie", "Sally", "Salma", "Salvador", "Salvatore", "Sam", "Samanta", "Samantha", "Samara", "Samir", "Sammie", "Sammy", "Samson", "Sandra", "Sandrine", "Sandy", "Sanford", "Santa", "Santiago", "Santina", "Santino", "Santos", "Sarah", "Sarai", "Sarina", "Sasha", "Saul", "Savanah", "Savanna", "Savannah", "Savion", "Scarlett", "Schuyler", "Scot", "Scottie", "Scotty", "Seamus", "Sean", "Sebastian", "Sedrick", "Selena", "Selina", "Selmer", "Serena", "Serenity", "Seth", "Shad", "Shaina", "Shakira", "Shana", "Shane", "Shanel", "Shanelle", "Shania", "Shanie", "Shaniya", "Shanna", "Shannon", "Shanny", "Shanon", "Shany", "Sharon", "Shaun", "Shawn", "Shawna", "Shaylee", "Shayna", "Shayne", "Shea", "Sheila", "Sheldon", "Shemar", "Sheridan", "Sherman", "Sherwood", "Shirley", "Shyann", "Shyanne", "Sibyl", "Sid", "Sidney", "Sienna", "Sierra", "Sigmund", "Sigrid", "Sigurd", "Silas", "Sim", "Simeon", "Simone", "Sincere", "Sister", "Skye", "Skyla", "Skylar", "Sofia", "Soledad", "Solon", "Sonia", "Sonny", "Sonya", "Sophia", "Sophie", "Spencer", "Stacey", "Stacy", "Stan", "Stanford", "Stanley", "Stanton", "Stefan", "Stefanie", "Stella", "Stephan", "Stephania", "Stephanie", "Stephany", "Stephen", "Stephon", "Sterling", "Steve", "Stevie", "Stewart", "Stone", "Stuart", "Summer", "Sunny", "Susan", "Susana", "Susanna", "Susie", "Suzanne", "Sven", "Syble", "Sydnee", "Sydney", "Sydni", "Sydnie", "Sylvan", "Sylvester", "Sylvia", "Tabitha", "Tad", "Talia", "Talon", "Tamara", "Tamia", "Tania", "Tanner", "Tanya", "Tara", "Taryn", "Tate", "Tatum", "Tatyana", "Taurean", "Tavares", "Taya", "Taylor", "Teagan", "Ted", "Telly", "Terence", "Teresa", "Terrance", "Terrell", "Terrence", "Terrill", "Terry", "Tess", "Tessie", "Tevin", "Thad", "Thaddeus", "Thalia", "Thea", "Thelma", "Theo", "Theodora", "Theodore", "Theresa", "Therese", "Theresia", "Theron", "Thomas", "Thora", "Thurman", "Tia", "Tiana", "Tianna", "Tiara", "Tierra", "Tiffany", "Tillman", "Timmothy", "Timmy", "Timothy", "Tina", "Tito", "Titus", "Tobin", "Toby", "Tod", "Tom", "Tomas", "Tomasa", "Tommie", "Toney", "Toni", "Tony", "Torey", "Torrance", "Torrey", "Toy", "Trace", "Tracey", "Tracy", "Travis", "Travon", "Tre", "Tremaine", "Tremayne", "Trent", "Trenton", "Tressa", "Tressie", "Treva", "Trever", "Trevion", "Trevor", "Trey", "Trinity", "Trisha", "Tristian", "Tristin", "Triston", "Troy", "Trudie", "Trycia", "Trystan", "Turner", "Twila", "Tyler", "Tyra", "Tyree", "Tyreek", "Tyrel", "Tyrell", "Tyrese", "Tyrique", "Tyshawn", "Tyson", "Ubaldo", "Ulices", "Ulises", "Una", "Unique", "Urban", "Uriah", "Uriel", "Ursula", "Vada", "Valentin", "Valentina", "Valentine", "Valerie", "Vallie", "Van", "Vance", "Vanessa", "Vaughn", "Veda", "Velda", "Vella", "Velma", "Velva", "Vena", "Verda", "Verdie", "Vergie", "Verla", "Verlie", "Vern", "Verna", "Verner", "Vernice", "Vernie", "Vernon", "Verona", "Veronica", "Vesta", "Vicenta", "Vicente", "Vickie", "Vicky", "Victor", "Victoria", "Vida", "Vidal", "Vilma", "Vince", "Vincent", "Vincenza", "Vincenzo", "Vinnie", "Viola", "Violet", "Violette", "Virgie", "Virgil", "Virginia", "Virginie", "Vita", "Vito", "Viva", "Vivian", "Viviane", "Vivianne", "Vivien", "Vivienne", "Vladimir", "Wade", "Waino", "Waldo", "Walker", "Wallace", "Walter", "Walton", "Wanda", "Ward", "Warren", "Watson", "Wava", "Waylon", "Wayne", "Webster", "Weldon", "Wellington", "Wendell", "Wendy", "Werner", "Westley", "Weston", "Whitney", "Wilber", "Wilbert", "Wilburn", "Wiley", "Wilford", "Wilfred", "Wilfredo", "Wilfrid", "Wilhelm", "Wilhelmine", "Will", "Willa", "Willard", "William", "Willie", "Willis", "Willow", "Willy", "Wilma", "Wilmer", "Wilson", "Wilton", "Winfield", "Winifred", "Winnifred", "Winona", "Winston", "Woodrow", "Wyatt", "Wyman", "Xander", "Xavier", "Xzavier", "Yadira", "Yasmeen", "Yasmin", "Yasmine", "Yazmin", "Yesenia", "Yessenia", "Yolanda", "Yoshiko", "Yvette", "Yvonne", "Zachariah", "Zachary", "Zachery", "Zack", "Zackary", "Zackery", "Zakary", "Zander", "Zane", "Zaria", "Zechariah", "Zelda", "Zella", "Zelma", "Zena", "Zetta", "Zion", "Zita", "Zoe", "Zoey", "Zoie", "Zoila", "Zola", "Zora", "Zula"}, + "middle": {"Abdul", "Abdullah", "Abigail", "Ada", "Adam", "Adelaide", "Adele", "Adelina", "Adrian", "Adriana", "Agnes", "Agnolo", "Ahmed", "Aida", "Aileen", "Aimee", "Akilesh", "Akio", "Alan", "Alana", "Alejandro", "Alex", "Ali", "Alice", "Alicia", "Alina", "Alison", "Alita", "Allegretta", "Alonzo", "Alyssa", "Aman", "Amara", "Amelda", "Amelia", "Amenra", "Amina", "Amir", "Amitabh", "Amy", "Ana", "Anastasia", "André", "Andrea", "Andrei", "Andrew", "Andy", "Angel", "Angela", "Anita", "Ann", "Anna", "Anne", "Annette", "Anthony", "Antioco", "Antonio", "Arduino", "Aria", "Ariana", "Ariel", "Aris", "Arjun", "Armando", "Asha", "Ashton", "Asong", "Athena", "Audrey", "August", "Aura", "Aurelia", "Austen", "Ava", "Avery", "Avril", "Badru", "Bailey", "Bakul", "Baldwin", "Bao", "Barack", "Bear", "Beatrice", "Beau", "Belinda", "Bella", "Belle", "Ben", "Benjamin", "Bertha", "Beverly", "Bharati", "Bhoja", "Bhuma", "Bianca", "Bird", "Birdie", "Bishvajit", "Bjorn", "Blair", "Blake", "Blanca", "Bliss", "Blue", "Bo", "Bobbie", "Bonnie", "Boris", "Bradley", "Brandt", "Braulia", "Breck", "Bree", "Brett", "Brianna", "Bridget", "Brie", "Brielle", "Brittany", "Brizio", "Brook", "Brooke", "Brooks", "Bruce", "Bryce", "Bryn", "Brynn", "Burke", "Cajetan", "Calvin", "Cameron", "Camilla", "Candice", "Carla", "Carlos", "Carmen", "Caroline", "Carson", "Casey", "Cash", "Cassandra", "Cassidy", "Catherine", "Cecelia", "Cecilia", "Cedric", "Celeste", "Celia", "Celso", "Chahna", "Chance", "Chander", "Chandler", "Chang", "Charles", "Charlie", "Charlotte", "Chen", "Chintak", "Chloe", "Chris", "Christine", "Chung", "Cimeron", "Cindy", "Ciprianna", "Ciro", "Claire", "Clara", "Clarissa", "Clark", "Clarke", "Claude", "Claudia", "Clay", "Clementine", "Clint", "Cody", "Cole", "Colette", "Cora", "Cordelia", "Corey", "Corinne", "Cory", "Cosme", "Courtney", "Cree", "Crew", "Cynthia", "Cyprienne", "Cyrus", "Daan", "Dada", "Daisy", "Dakota", "Dale", "Damodar", "Dan", "Dana", "Dane", "Daniel", "Danielle", "Danveer", "Daphne", "Darla", "David", "Davide", "Dawn", "Dax", "Dean", "Deborah", "Delilah", "Denise", "Denver", "Deshal", "Deshawn", "Dev", "Devin", "Dhavala", "Diana", "Diane", "Diego", "Dmitri", "Dolores", "Dolorita", "Donato", "Dong", "Donna", "Donte", "Donya", "Dora", "Doris", "Dorothy", "Drake", "Drew", "Dru", "Dylan", "Ean", "Edith", "Eduardo", "Edward", "Eila", "Eileen", "Elaine", "Elda", "Eleanor", "Elena", "Eliana", "Elias", "Elise", "Eliza", "Elizabeth", "Ella", "Elle", "Ellen", "Ellie", "Ellis", "Eloise", "Elsa", "Elsie", "Em", "Emerson", "Emery", "Emilie", "Emilio", "Emily", "Emma", "Emmett", "Enrico", "Enrique", "Epifania", "Erica", "Erik", "Erin", "Eroica", "Esperanza", "Estelle", "Esther", "Etta", "Ettore", "Eva", "Evan", "Eve", "Evelyn", "Everett", "Faith", "Farid", "Faye", "Federico", "Felicity", "Felipe", "Felix", "Fern", "Fernando", "Finley", "Finn", "Fiona", "Fitz", "Flint", "Flora", "Florence", "Flynn", "Folke", "Fonzo", "Fox", "Frances", "Francis", "Francisco", "Francois", "François", "Frank", "Frankie", "Freya", "Fumio", "Fynn", "Gabriel", "Gabriella", "Gael", "Gage", "Gail", "Gemma", "Genevieve", "George", "Georgia", "Geraldine", "Giannino", "Ginetta", "Gioia", "Giselle", "Giuseppe", "Giustino", "Glenn", "Gloria", "Glory", "Grace", "Grant", "Gray", "Greer", "Greta", "Guido", "Guillermo", "Gulshan", "Gus", "Gwen", "Gyula", "Hank", "Hannah", "Hans", "Harley", "Harper", "Harriet", "Harrison", "Harshad", "Haruki", "Hayden", "Hayes", "Haze", "Hazel", "Heath", "Heather", "Hector", "Helen", "Helena", "Henry", "Hideki", "Hidetoshi", "Himesh", "Hiro", "Hiroaki", "Hirofumi", "Hirokazu", "Hiroshi", "Hiroto", "Hiroyuki", "Holly", "Honor", "Hope", "Hugh", "Hugo", "Hunter", "Ida", "Ignacio", "Imogen", "Ingrid", "Irene", "Iris", "Isaac", "Isabel", "Isabella", "Isabelle", "Ivan", "Ivy", "Jace", "Jack", "Jacqueline", "Jade", "Jaden", "Jae", "Jai", "Jaime", "Jamal", "James", "Jamie", "Jan", "Janak", "Jane", "Janet", "Janice", "Jasmine", "Jasper", "Javier", "Jax", "Jay", "Jayden", "Jayne", "Jean", "Jeanne", "Jed", "Jenna", "Jennifer", "Jesse", "Jessica", "Jill", "Jin", "Joan", "Joanna", "João", "Jocelyn", "Jodi", "Jody", "Joe", "Joey", "Johanna", "Johar", "John", "Jolene", "Jordan", "Jorge", "Jose", "José", "Joseph", "Josephine", "Josie", "Joy", "Joyce", "Juan", "Juanita", "Judd", "Jude", "Judith", "Jules", "Julia", "Julian", "Juliana", "Julianne", "Julie", "June", "Justine", "Kael", "Kai", "Kane", "Karen", "Kate", "Katherine", "Kathleen", "Kathryn", "Katie", "Katrina", "Kay", "Kayla", "Kazuki", "Keira", "Kelly", "Kelsey", "Kendall", "Kendra", "Kennedy", "Kent", "Kenta", "Kerry", "Khaled", "Khloe", "Kiara", "Kim", "Kimberly", "Kit", "Kiyoshi", "Klaus", "Knight", "Knox", "Koen", "Koi", "Koichi", "Koji", "Kolt", "Kristen", "Kristina", "Kurt", "Kwame", "Kye", "Kylie", "Lacey", "Laine", "Lake", "Lakshman", "Lalika", "Lane", "Lark", "Lars", "Laurel", "Layne", "Lee", "Leif", "Lennon", "Leo", "Leon", "Leslie", "Liam", "Liberty", "Lilian", "Lillian", "Lillie", "Link", "Liz", "Locke", "Logan", "Lona", "Lorena", "Lorenzo", "Lou", "Louise", "Love", "Lucia", "Lucy", "Luis", "Luiz", "Luke", "Lupita", "Lux", "Luz", "Lydia", "Lynn", "Mabel", "Mac", "Mack", "Mackenzie", "Madeline", "Madison", "Madona", "Mae", "Mael", "Makoto", "Manuel", "Manuela", "Maple", "Marc", "Marco", "Margaret", "Margo", "Margot", "Maria", "Mariano", "Maricela", "Marilyn", "Mario", "Mark", "Marley", "Mars", "Marti", "Mary", "Mason", "Matthew", "Mavis", "Max", "May", "Mazie", "Mei", "Melody", "Mercy", "Merle", "Micah", "Michael", "Miguel", "Mina", "Ming", "Mohamed", "Mollie", "Monroe", "Morgan", "Muhammad", "Musetta", "Myra", "Nadine", "Naomi", "Nardo", "Nat", "Natalie", "Neal", "Neil", "Nellie", "Nerola", "Nevada", "Neve", "Nikolai", "Niles", "Noel", "Nola", "Nora", "Nuru", "Oakley", "Olive", "Oliver", "Opal", "Orazio", "Ortensa", "Ortensia", "Osamu", "Oscar", "Otto", "Pablo", "Paige", "Pancho", "Paris", "Parker", "Pat", "Patrick", "Paul", "Pauli", "Pax", "Peace", "Pearl", "Pedro", "Penelope", "Penn", "Penny", "Peter", "Petra", "Peyton", "Phoenix", "Pierce", "Pierre", "Pilar", "Porter", "Praise", "Pratap", "Presley", "Priscilla", "Quinn", "Rachanna", "Radames", "Rae", "Rafael", "Rain", "Raine", "Ramiro", "Ramon", "Ramona", "Raphael", "Raul", "Ravi", "Ray", "Rayne", "Reagan", "Reece", "Reed", "Reese", "Rei", "Reid", "Reilly", "Remy", "Ren", "Reyes", "Rhodes", "Ricardo", "Richard", "Riley", "Rita", "River", "Rivera", "Roan", "Robert", "Roberto", "Robin", "Robt", "Rodrigo", "Roma", "Romelia", "Rory", "Rosa", "Rosalee", "Rosalie", "Rosalynn", "Rosario", "Rose", "Ross", "Rowan", "Ruben", "Ruby", "Rue", "Rush", "Russell", "Ruth", "Ryan", "Saad", "Saariq", "Sade", "Sadie", "Sagara", "Sage", "Saige", "Saint", "Salvadora", "Sam", "Samir", "Samuel", "Sante", "Santiago", "Sara", "Sasha", "Satoshi", "Scott", "Sean", "Sebastian", "Sergei", "Sergio", "Seth", "Shae", "Shai", "Shane", "Shannon", "Shashi", "Shaun", "Shawn", "Shawnee", "Shay", "Shea", "Shelby", "Shin", "Sidney", "Simon", "Sky", "Skye", "Skyler", "Sol", "Sophie", "Spencer", "Star", "Starr", "Stella", "Steve", "Stevie", "Storm", "Susan", "Sven", "Sybil", "Sydney", "Tahj", "Takashi", "Takeshi", "Taryn", "Tatum", "Taylor", "Teagan", "Terry", "Tess", "Thea", "Theodore", "Thomas", "Tilly", "Timothy", "Tosca", "Trent", "Tripp", "Tristan", "Truth", "Tyler", "Tyrone", "Uberto", "Ursus", "Val", "Vandelia", "Vaughn", "Vera", "Vernon", "Verona", "Vianna", "Victoria", "Vida", "Vieda", "Vince", "Vincent", "Violet", "Virginia", "Vivian", "Vladimir", "Wade", "Wayne", "Wes", "Wesley", "West", "Whitney", "Will", "Willa", "William", "Willie", "Winston", "Winter", "Wolf", "Wren", "Wynn", "Xavier", "Yasuo", "Yoel", "Yolanda", "Yoshi", "Yoshiaki", "Yoshihiro", "Yoshiki", "Yoshinori", "Yoshio", "Yusuf", "Yutaka", "Zain", "Zane", "Zayd", "Zelda", "Zeus", "Zev", "Zhang", "Zhen", "Zola", "Zora", "Zuni"}, "last": {"Abbott", "Abernathy", "Abshire", "Adams", "Altenwerth", "Anderson", "Ankunding", "Armstrong", "Auer", "Aufderhar", "Bahringer", "Bailey", "Balistreri", "Barrows", "Bartell", "Bartoletti", "Barton", "Bashirian", "Batz", "Bauch", "Baumbach", "Bayer", "Beahan", "Beatty", "Bechtelar", "Becker", "Bednar", "Beer", "Beier", "Berge", "Bergnaum", "Bergstrom", "Bernhard", "Bernier", "Bins", "Blanda", "Blick", "Block", "Bode", "Boehm", "Bogan", "Bogisich", "Borer", "Bosco", "Botsford", "Boyer", "Boyle", "Bradtke", "Brakus", "Braun", "Breitenberg", "Brekke", "Brown", "Bruen", "Buckridge", "Carroll", "Carter", "Cartwright", "Casper", "Cassin", "Champlin", "Christiansen", "Cole", "Collier", "Collins", "Conn", "Connelly", "Conroy", "Considine", "Corkery", "Cormier", "Corwin", "Cremin", "Crist", "Crona", "Cronin", "Crooks", "Cruickshank", "Cummerata", "Cummings", "Dach", "Damore", "Daniel", "Dare", "Daugherty", "Davis", "Deckow", "Denesik", "Dibbert", "Dickens", "Dicki", "Dickinson", "Dietrich", "Donnelly", "Dooley", "Douglas", "Doyle", "DuBuque", "Durgan", "Ebert", "Effertz", "Eichmann", "Emard", "Emmerich", "Erdman", "Ernser", "Fadel", "Fahey", "Farrell", "Fay", "Feeney", "Feest", "Feil", "Ferry", "Fisher", "Flatley", "Frami", "Franecki", "Friesen", "Fritsch", "Funk", "Gaylord", "Gerhold", "Gerlach", "Gibson", "Gislason", "Gleason", "Gleichner", "Glover", "Goldner", "Goodwin", "Gorczany", "Gottlieb", "Goyette", "Grady", "Graham", "Grant", "Green", "Greenfelder", "Greenholt", "Grimes", "Gulgowski", "Gusikowski", "Gutkowski", "Gutmann", "Haag", "Hackett", "Hagenes", "Hahn", "Haley", "Halvorson", "Hamill", "Hammes", "Hand", "Hane", "Hansen", "Harber", "Harris", "Hartmann", "Harvey", "Hauck", "Hayes", "Heaney", "Heathcote", "Hegmann", "Heidenreich", "Heller", "Herman", "Hermann", "Hermiston", "Herzog", "Hessel", "Hettinger", "Hickle", "Hilll", "Hills", "Hilpert", "Hintz", "Hirthe", "Hodkiewicz", "Hoeger", "Homenick", "Hoppe", "Howe", "Howell", "Hudson", "Huel", "Huels", "Hyatt", "Jacobi", "Jacobs", "Jacobson", "Jakubowski", "Jaskolski", "Jast", "Jenkins", "Jerde", "Jewess", "Johns", "Johnson", "Johnston", "Jones", "Kassulke", "Kautzer", "Keebler", "Keeling", "Kemmer", "Kerluke", "Kertzmann", "Kessler", "Kiehn", "Kihn", "Kilback", "King", "Kirlin", "Klein", "Kling", "Klocko", "Koch", "Koelpin", "Koepp", "Kohler", "Konopelski", "Koss", "Kovacek", "Kozey", "Krajcik", "Kreiger", "Kris", "Kshlerin", "Kub", "Kuhic", "Kuhlman", "Kuhn", "Kulas", "Kunde", "Kunze", "Kuphal", "Kutch", "Kuvalis", "Labadie", "Lakin", "Lang", "Langosh", "Langworth", "Larkin", "Larson", "Leannon", "Lebsack", "Ledner", "Leffler", "Legros", "Lehner", "Lemke", "Lesch", "Leuschke", "Lind", "Lindgren", "Littel", "Little", "Lockman", "Lowe", "Lubowitz", "Lueilwitz", "Luettgen", "Lynch", "Macejkovic", "Maggio", "Mann", "Mante", "Marks", "Marquardt", "Marvin", "Mayer", "Mayert", "McClure", "McCullough", "McDermott", "McGlynn", "McKenzie", "McLaughlin", "Medhurst", "Mertz", "Metz", "Miller", "Mills", "Mitchell", "Moen", "Mohr", "Monahan", "Moore", "Morar", "Morissette", "Mosciski", "Mraz", "Mueller", "Muller", "Murazik", "Murphy", "Murray", "Nader", "Nicolas", "Nienow", "Nikolaus", "Nitzsche", "Nolan", "Oberbrunner", "Okuneva", "Olson", "Ondricka", "OReilly", "Orn", "Ortiz", "Osinski", "Pacocha", "Padberg", "Pagac", "Parisian", "Parker", "Paucek", "Pfannerstill", "Pfeffer", "Pollich", "Pouros", "Powlowski", "Predovic", "Price", "Prohaska", "Prosacco", "Purdy", "Quigley", "Quitzon", "Rath", "Ratke", "Rau", "Raynor", "Reichel", "Reichert", "Reilly", "Reinger", "Rempel", "Renner", "Reynolds", "Rice", "Rippin", "Ritchie", "Robel", "Roberts", "Rodriguez", "Rogahn", "Rohan", "Rolfson", "Romaguera", "Roob", "Rosenbaum", "Rowe", "Ruecker", "Runolfsdottir", "Runolfsson", "Runte", "Russel", "Rutherford", "Ryan", "Sanford", "Satterfield", "Sauer", "Sawayn", "Schaden", "Schaefer", "Schamberger", "Schiller", "Schimmel", "Schinner", "Schmeler", "Schmidt", "Schmitt", "Schneider", "Schoen", "Schowalter", "Schroeder", "Schulist", "Schultz", "Schumm", "Schuppe", "Schuster", "Senger", "Shanahan", "Shields", "Simonis", "Sipes", "Skiles", "Smith", "Smitham", "Spencer", "Spinka", "Sporer", "Stamm", "Stanton", "Stark", "Stehr", "Steuber", "Stiedemann", "Stokes", "Stoltenberg", "Stracke", "Streich", "Stroman", "Strosin", "Swaniawski", "Swift", "Terry", "Thiel", "Thompson", "Tillman", "Torp", "Torphy", "Towne", "Toy", "Trantow", "Tremblay", "Treutel", "Tromp", "Turcotte", "Turner", "Ullrich", "Upton", "Vandervort", "Veum", "Volkman", "Von", "VonRueden", "Waelchi", "Walker", "Walsh", "Walter", "Ward", "Waters", "Watsica", "Weber", "Wehner", "Weimann", "Weissnat", "Welch", "West", "White", "Wiegand", "Wilderman", "Wilkinson", "Will", "Williamson", "Willms", "Windler", "Wintheiser", "Wisoky", "Wisozk", "Witting", "Wiza", "Wolf", "Wolff", "Wuckert", "Wunsch", "Wyman", "Yost", "Yundt", "Zboncak", "Zemlak", "Ziemann", "Zieme", "Zulauf"}, "hobby": {"3D printing", "Acrobatics", "Acting", "Amateur radio", "Animation", "Aquascaping", "Astrology", "Astronomy", "Baking", "Baton twirling", "Blogging", "Building", "Board/tabletop games", "Book discussion clubs", "Book restoration", "Bowling", "Brazilian jiu-jitsu", "Breadmaking", "Bullet journaling", "Cabaret", "Calligraphy", "Candle making", "Candy making", "Car fixing & building", "Card games", "Cheesemaking", "Cleaning", "Clothesmaking", "Coffee roasting", "Collecting", "Coloring", "Computer programming", "Confectionery", "Cooking", "Cosplaying", "Couponing", "Craft", "Creative writing", "Crocheting", "Cross-stitch", "Crossword puzzles", "Cryptography", "Cue sports", "Dance", "Digital arts", "Distro Hopping", "DJing", "Do it yourself", "Drama", "Drawing", "Drink mixing", "Drinking", "Electronic games", "Electronics", "Embroidery", "Experimenting", "Fantasy sports", "Fashion", "Fashion design", "Fishkeeping", "Filmmaking", "Flower arranging", "Fly tying", "Foreign language learning", "Furniture building", "Gaming", "Genealogy", "Gingerbread house making", "Glassblowing", "Graphic design", "Gunsmithing", "Gymnastics", "Hacking", "Herp keeping", "Home improvement", "Homebrewing", "Houseplant care", "Hula hooping", "Humor", "Hydroponics", "Ice skating", "Jewelry making", "Jigsaw puzzles", "Journaling", "Juggling", "Karaoke", "Karate", "Kendama", "Knife making", "Knitting", "Knot tying", "Kombucha brewing", "Lace making", "Lapidary", "Leather crafting", "Lego building", "Lock picking", "Listening to music", "Listening to podcasts", "Machining", "Macrame", "Magic", "Makeup", "Mazes (indoor/outdoor)", "Metalworking", "Model building", "Model engineering", "Nail art", "Needlepoint", "Origami", "Painting", "Palmistry", "Pet adoption & fostering", "Philately", "Photography", "Practical jokes", "Pressed flower craft", "Playing musical instruments", "Poi", "Pottery", "Powerlifting", "Puzzles", "Quilling", "Quilting", "Quizzes", "Radio-controlled model", "Rail transport modeling", "Rapping", "Reading", "Refinishing", "Reiki", "Robot combat", "Rubik's Cube", "Scrapbooking", "Sculpting", "Sewing", "Shoemaking", "Singing", "Sketching", "Skipping rope", "Slot car", "Soapmaking", "Social media", "Spreadsheets", "Stand-up comedy", "Stamp collecting", "Table tennis", "Tarot", "Taxidermy", "Thrifting", "Video editing", "Video game developing", "Video gaming", "Watching movies", "Watching television", "Videography", "Virtual reality", "Waxing", "Weaving", "Weight training", "Welding", "Whittling", "Wikipedia editing", "Winemaking", "Wood carving", "Woodworking", "Worldbuilding", "Writing", "Word searches", "Yo-yoing", "Yoga", "Zumba", "Amusement park visiting", "Air sports", "Airsoft", "Amateur geology", "Archery", "Astronomy", "Backpacking", "Badminton", "BASE jumping", "Baseball", "Basketball", "Beekeeping", "Birdwatching", "Blacksmithing", "BMX", "Board sports", "Bodybuilding", "Bonsai", "Butterfly watching", "Bus riding", "Camping", "Canoeing", "Canyoning", "Car riding", "Caving", "Composting", "Cycling", "Dowsing", "Driving", "Farming", "Fishing", "Flag football", "Flower growing", "Flying", "Flying disc", "Foraging", "Fossicking", "Freestyle football", "Gardening", "Geocaching", "Ghost hunting", "Gold prospecting", "Graffiti", "Handball", "Herbalism", "Herping", "High-power rocketry", "Hiking", "Hobby horsing", "Hobby tunneling", "Hooping", "Horseback riding", "Hunting", "Inline skating", "Jogging", "Jumping rope", "Kayaking", "Kite flying", "Kitesurfing", "Lacrosse", "LARPing", "Letterboxing", "Longboarding", "Martial arts", "Metal detecting", "Meteorology", "Motor sports", "Mountain biking", "Mountaineering", "Museum visiting", "Mushroom hunting", "Netball", "Nordic skating", "Orienteering", "Paintball", "Parkour", "Photography", "Podcast hosting", "Polo", "Public transport riding", "Rafting", "Railway journeys", "Rappelling", "Road biking", "Rock climbing", "Roller skating", "Rugby", "Running", "Radio-controlled model", "Sailing", "Sand art", "Scouting", "Scuba diving", "Sculling", "Shooting", "Shopping", "Shuffleboard", "Skateboarding", "Skiing", "Skimboarding", "Skydiving", "Slacklining", "Snowboarding", "Snowmobiling", "Snowshoeing", "Soccer", "Stone skipping", "Sun bathing", "Surfing", "Survivalism", "Swimming", "Taekwondo", "Tai chi", "Tennis", "Topiary", "Tourism", "Thru-hiking", "Trade fair visiting", "Travel", "Urban exploration", "Vacation", "Vegetable farming", "Videography", "Vehicle restoration", "Walking", "Water sports", "Astronomy", "Biology", "Chemistry", "Electrochemistry", "Physics", "Psychology", "Sports science", "Geography", "History", "Mathematics", "Railway studies", "Action figure", "Antiquing", "Ant-keeping", "Art collecting", "Book collecting", "Button collecting", "Cartophily", "Coin collecting", "Comic book collecting", "Deltiology", "Die-cast toy", "Digital hoarding", "Dolls", "Element collecting", "Ephemera collecting", "Fusilately", "Knife collecting", "Lotology", "Movie and movie memorabilia collecting", "Fingerprint collecting", "Perfume", "Phillumeny", "Radio-controlled model", "Rail transport modelling", "Record collecting", "Rock tumbling", "Scutelliphily", "Shoes", "Slot car", "Sports memorabilia", "Stamp collecting", "Stuffed toy collecting", "Tea bag collecting", "Ticket collecting", "Toys", "Transit map collecting", "Video game collecting", "Vintage cars", "Vintage clothing", "Vinyl Records", "Antiquities", "Auto audiophilia", "Flower collecting and pressing", "Fossil hunting", "Insect collecting", "Magnet fishing", "Metal detecting", "Mineral collecting", "Rock balancing", "Sea glass collecting", "Seashell collecting", "Stone collecting", "Animal fancy", "Axe throwing", "Backgammon", "Badminton", "Baton twirling", "Beauty pageants", "Billiards", "Bowling", "Boxing", "Bridge", "Checkers (draughts)", "Cheerleading", "Chess", "Color guard", "Cribbage", "Curling", "Dancing", "Darts", "Debate", "Dominoes", "Eating", "Esports", "Fencing", "Go", "Gymnastics", "Ice hockey", "Ice skating", "Judo", "Jujitsu", "Kabaddi", "Knowledge/word games", "Laser tag", "Longboarding", "Mahjong", "Marbles", "Martial arts", "Model United Nations", "Poker", "Pool", "Role-playing games", "Shogi", "Slot car racing", "Speedcubing", "Sport stacking", "Table football", "Table tennis", "Volleyball", "Weightlifting", "Wrestling", "Airsoft", "Archery", "Association football", "Australian rules football", "Auto racing", "Baseball", "Beach volleyball", "Breakdancing", "Climbing", "Cricket", "Croquet", "Cycling", "Disc golf", "Dog sport", "Equestrianism", "Exhibition drill", "Field hockey", "Figure skating", "Fishing", "Footbag", "Frisbee", "Golfing", "Handball", "Horseback riding", "Horseshoes", "Iceboat racing", "Jukskei", "Kart racing", "Knife throwing", "Lacrosse", "Longboarding", "Long-distance running", "Marching band", "Model aircraft", "Orienteering", "Pickleball", "Quidditch", "Race walking", "Racquetball", "Radio-controlled car racing", "Roller derby", "Rugby league football", "Sculling", "Shooting sport", "Skateboarding", "Skiing", "Sled dog racing", "Softball", "Speed skating", "Squash", "Surfing", "Swimming", "Table tennis", "Tennis", "Tennis polo", "Tether car", "Tour skating", "Tourism", "Trapshooting", "Triathlon", "Ultimate frisbee", "Volleyball", "Water polo", "Fishkeeping", "Learning", "Meditation", "Microscopy", "Reading", "Research", "Shortwave listening", "Audiophile", "Aircraft spotting", "Amateur astronomy", "Birdwatching", "Bus spotting", "Geocaching", "Gongoozling", "Herping", "Hiking", "Meteorology", "Photography", "Satellite watching", "Trainspotting", "Whale watching"}, "phone": {"###-###-####", "(###)###-####", "1-###-###-####", "###.###.####"}, diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/word.go b/vendor/github.com/brianvoe/gofakeit/v6/data/word.go index 3dfc66f42..87b48dc88 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/word.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/word.go @@ -27,6 +27,7 @@ var Word = map[string][]string{ "noun_collective_thing": {"wad", "pair", "album", "string", "anthology", "reel", "outfit", "fleet", "comb", "archipelago", "quiver", "bale", "packet", "hedge", "basket", "orchard", "batch", "library", "battery", "set", "harvest", "block", "forest", "book", "group", "bouquet", "collection", "bowl", "stack", "bunch", "hand", "bundle", "catalog", "shower", "ream", "chest", "heap", "range", "cluster", "pack", "hail", "cloud", "galaxy", "sheaf", "clump"}, "noun_countable": {"camp", "hospital", "shirt", "sock", "plant", "cup", "fork", "spoon", "plate", "straw", "town", "box", "bird", "father", "answer", "egg", "purse", "mirror", "mistake", "toilet", "toothbrush", "shower", "towel", "pool", "corner", "card", "lawn", "city", "egg", "yard", "burger", "kilometer", "mile", "father", "film", "actor", "issue", "machine", "liter", "room", "station", "journey", "castle", "hour", "finger", "boy", "book", "year", "second", "son", "month", "group", "hall", "cat", "week", "picture", "day", "village", "effect", "baby", "weekend", "class", "meal", "river", "grade", "bush", "desk", "stream", "method", "brother", "sister", "factory", "aunt", "bush", "program", "uncle", "ball", "cousin", "wall", "grandmother", "cup", "grandfather", "week", "school", "shirt", "child", "king", "road", "judge", "bridge", "car", "line", "book", "eye", "teacher", "foot", "party", "face", "day", "chest", "handle", "week", "hotel", "eye", "animal", "doctor", "adult", "village", "key", "bird", "bank", "program", "idea", "gun", "card", "brother", "dress", "room", "door", "mouth", "club", "game", "ring", "project", "sister", "road", "coat", "account", "group", "cigarette", "farm", "river", "college", "computer", "walk", "corner", "cat", "head", "street", "election", "country", "chair", "crowd", "cup", "plant", "farm", "handle", "model", "book", "message", "battle", "pen", "pencil", "elephant", "carrot", "onion", "garden", "country", "engine", "bill", "apple", "noun", "club", "crowd", "window", "field", "friend", "verb", "class", "flower", "seed", "lake", "plant", "animal", "ocean", "whale", "fish", "stream", "cloud", "couch", "steak", "problem", "light", "door", "room", "painting", "shop", "apartment", "candle", "adult", "building", "plan", "page", "ball", "game", "animal", "apartment", "box", "thought", "walk", "lady", "bottle", "article", "game", "kettle", "car", "house", "hoses", "orange", "phone", "app", "window", "door", "dollar", "foot", "cent", "library", "cat", "bed", "pound", "gate", "tomatoes", "gun", "holiday", "woman", "job", "shock", "salary", "tax", "coat", "scooter", "dog", "problem", "field", "answer", "ear", "camp", "case", "road", "woman", "product", "bridge", "man", "dream", "idea", "scheme", "invention", "cigarette", "mother", "friend", "chapter", "computer", "dream", "father", "child", "motor", "deskpath", "factory", "park", "newspaper", "hat", "dream", "table", "kitchen", "student", "captain", "doctor", "bus", "neck", "class", "list", "member", "chest", "valley", "product", "horse", "captain", "star", "hour", "page", "bus", "girl", "month", "child", "house", "boy", "bill", "kitchen", "chapter", "boat", "hand", "dress", "table", "wall", "chair", "train", "minute", "magazine", "bus", "party", "bird", "lake", "job", "nation", "bike", "election", "hand", "box", "beach", "address", "project", "task", "park", "face", "college", "bell", "plane", "store", "hall", "accident", "daughter", "ship", "candy", "smile", "city", "island", "case", "spot", "film", "husband", "artist", "tour", "bag", "boat", "driver", "office", "chair", "path", "dog", "bag", "finger", "apartment", "garden", "heart", "year", "engine", "girl", "day", "castle", "plane", "ring", "brother", "edge", "picture", "meeting", "tent", "dog", "hat", "head", "bottle", "hill"}, "noun_uncountable": {"accommodation", "advertising", "air", "aid", "advice", "anger", "art", "assistance", "bread", "business", "butter", "calm", "cash", "chaos", "cheese", "childhood", "clothing", "coffee", "content", "corruption", "courage", "currency", "damage", "danger", "darkness", "data", "determination", "economics", "education", "electricity", "employment", "energy", "entertainment", "enthusiasm", "equipment", "evidence", "failure", "fame", "fire", "flour", "food", "freedom", "friendship", "fuel", "furniture", "fun", "genetics", "gold", "grammar", "guilt", "hair", "happiness", "harm", "health", "heat", "help", "homework", "honesty", "hospitality", "housework", "humour", "imagination", "importance", "information", "innocence", "intelligence", "jealousy", "juice", "justice", "kindness", "knowledge", "labour", "lack", "laughter", "leisure", "literature", "litter", "logic", "love", "luck", "magic", "management", "metal", "milk", "money", "motherhood", "motivation", "music", "nature", "news", "nutrition", "obesity", "oil", "old age", "oxygen", "paper", "patience", "permission", "pollution", "poverty", "power", "pride", "production", "progress", "pronunciation", "publicity", "punctuation", "quality", "quantity", "racism", "rain", "relaxation", "research", "respect", "rice", "room (space)", "rubbish", "safety", "salt", "sand", "seafood", "shopping", "silence", "smoke", "snow", "software", "soup", "speed", "spelling", "stress", "sugar", "sunshine", "tea", "tennis", "time", "tolerance", "trade", "traffic", "transportation", "travel", "trust", "understanding", "unemployment", "usage", "violence", "vision", "warmth", "water", "wealth", "weather", "weight", "welfare", "wheat", "width", "wildlife", "wisdom", "wood", "work", "yoga", "youth"}, + "noun_determiner": {"the", "a", "an", "this", "that", "these", "those", "my", "your", "his", "her", "its", "our", "their", "some", "any", "each", "every", "certain"}, //"noun_proper": {}, // This refers to an actual person(John Doe), place(Chipotle, Tennessee) // Verbs @@ -71,9 +72,12 @@ var Word = map[string][]string{ // Connectives "connective_time": {"after a while", "afterwards", "at once", "at this moment", "at this point", "before that", "finally", "first", "here", "in the end", "lastly", "later on", "meanwhile", "next", "next time", "now", "on another occasion", "previously", "since", "soon", "straightaway", "then", "until then", "when", "whenever", "while"}, - "connective_comparitive": {"additionally", "also", "as well", "even", "furthermore", "in addition", "indeed", "let alone", "moreover", "not only", "alternatively", "anyway", "but", "by contrast", "differs from", "elsewhere", "even so", "however", "in contrast", "in fact", "in other respects", "in spite of this", "in that respect", "instead", "nevertheless", "on the contrary", "on the other hand", "rather", "though", "whereas", "yet", "after all", "anyway", "besides", "moreover"}, + "connective_comparative": {"additionally", "also", "as well", "even", "furthermore", "in addition", "indeed", "let alone", "moreover", "not only", "alternatively", "anyway", "but", "by contrast", "differs from", "elsewhere", "even so", "however", "in contrast", "in fact", "in other respects", "in spite of this", "in that respect", "instead", "nevertheless", "on the contrary", "on the other hand", "rather", "though", "whereas", "yet", "after all", "anyway", "besides", "moreover"}, "connective_complaint": {"besides", "e.g.", "for example", "for instance", "i.e.", "in other words", "in that", "that is to say"}, "connective_listing": {"firstly", "secondly", "first of all", "finally", "lastly", "for one thing", "for another", "in the first place", "to begin with", "next", "in summation", "to conclude"}, "connective_casual": {"accordingly", "all the same", "an effect of", "an outcome of", "an upshot of", "as a consequence of", "as a result of", "because", "caused by", "consequently", "despite this", "even though", "hence", "however", "in that case", "moreover", "nevertheless", "otherwise", "so", "so as", "stemmed from", "still", "then", "therefore", "though", "under the circumstances", "yet"}, "connective_examplify": {"accordingly", "as a result", "as exemplified by", "consequently", "for example", "for instance", "for one thing", "including", "provided that", "since", "so", "such as", "then", "therefore", "these include", "through", "unless", "without"}, + + // Misc + "interjection": {"wow", "hey", "oops", "ouch", "yay", "aha", "eek", "huh", "hmm", "whoa", "yikes", "phew", "gee", "alas", "bravo"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/emoji.go b/vendor/github.com/brianvoe/gofakeit/v6/emoji.go index f40f630f9..5eb4372ec 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/emoji.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/emoji.go @@ -46,10 +46,10 @@ func addEmojiLookup() { AddFuncLookup("emoji", Info{ Display: "Emoji", Category: "emoji", - Description: "Random emoji", + Description: "Digital symbol expressing feelings or ideas in text messages and online chats", Example: "🤣", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emoji(r), nil }, }) @@ -57,10 +57,10 @@ func addEmojiLookup() { AddFuncLookup("emojidescription", Info{ Display: "Emoji Description", Category: "emoji", - Description: "Random emoji description", + Description: "Brief explanation of the meaning or emotion conveyed by an emoji", Example: "face vomiting", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiDescription(r), nil }, }) @@ -68,10 +68,10 @@ func addEmojiLookup() { AddFuncLookup("emojicategory", Info{ Display: "Emoji Category", Category: "emoji", - Description: "Random emoji category", + Description: "Group or classification of emojis based on their common theme or use, like 'smileys' or 'animals'", Example: "Smileys & Emotion", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiCategory(r), nil }, }) @@ -79,10 +79,10 @@ func addEmojiLookup() { AddFuncLookup("emojialias", Info{ Display: "Emoji Alias", Category: "emoji", - Description: "Random emoji alias", + Description: "Alternative name or keyword used to represent a specific emoji in text or code", Example: "smile", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiAlias(r), nil }, }) @@ -90,10 +90,10 @@ func addEmojiLookup() { AddFuncLookup("emojitag", Info{ Display: "Emoji Tag", Category: "emoji", - Description: "Random emoji tag", + Description: "Label or keyword associated with an emoji to categorize or search for it easily", Example: "happy", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiTag(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/file.go b/vendor/github.com/brianvoe/gofakeit/v6/file.go index 05ebc50d9..3812021e1 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/file.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/file.go @@ -22,10 +22,10 @@ func addFileLookup() { AddFuncLookup("fileextension", Info{ Display: "File Extension", Category: "file", - Description: "Random file extension", + Description: "Suffix appended to a filename indicating its format or type", Example: "nes", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return fileExtension(r), nil }, }) @@ -33,10 +33,10 @@ func addFileLookup() { AddFuncLookup("filemimetype", Info{ Display: "File Mime Type", Category: "file", - Description: "Random file mime type", + Description: "Defines file format and nature for browsers and email clients using standardized identifiers", Example: "application/json", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return fileMimeType(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/food.go b/vendor/github.com/brianvoe/gofakeit/v6/food.go index a8b7e7c9f..ae1bb2fd6 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/food.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/food.go @@ -91,10 +91,10 @@ func addFoodLookup() { AddFuncLookup("fruit", Info{ Display: "Fruit", Category: "food", - Description: "Random fruit", + Description: "Edible plant part, typically sweet, enjoyed as a natural snack or dessert", Example: "Peach", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return fruit(r), nil }, }) @@ -102,10 +102,10 @@ func addFoodLookup() { AddFuncLookup("vegetable", Info{ Display: "Vegetable", Category: "food", - Description: "Random vegetable", + Description: "Edible plant or part of a plant, often used in savory cooking or salads", Example: "Amaranth Leaves", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return vegetable(r), nil }, }) @@ -113,10 +113,10 @@ func addFoodLookup() { AddFuncLookup("breakfast", Info{ Display: "Breakfast", Category: "food", - Description: "Random breakfast", + Description: "First meal of the day, typically eaten in the morning", Example: "Blueberry banana happy face pancakes", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return breakfast(r), nil }, }) @@ -124,10 +124,10 @@ func addFoodLookup() { AddFuncLookup("lunch", Info{ Display: "Lunch", Category: "food", - Description: "Random lunch", + Description: "Midday meal, often lighter than dinner, eaten around noon", Example: "No bake hersheys bar pie", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return lunch(r), nil }, }) @@ -135,10 +135,10 @@ func addFoodLookup() { AddFuncLookup("dinner", Info{ Display: "Dinner", Category: "food", - Description: "Random dinner", + Description: "Evening meal, typically the day's main and most substantial meal", Example: "Wild addicting dip", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return dinner(r), nil }, }) @@ -146,10 +146,10 @@ func addFoodLookup() { AddFuncLookup("drink", Info{ Display: "Drink", Category: "food", - Description: "Random drink", + Description: "Liquid consumed for hydration, pleasure, or nutritional benefits", Example: "Soda", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return drink(r), nil }, }) @@ -158,9 +158,9 @@ func addFoodLookup() { Display: "Snack", Category: "food", Description: "Random snack", - Example: "Hoisin marinated wing pieces", + Example: "Small, quick food item eaten between meals", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return snack(r), nil }, }) @@ -168,10 +168,10 @@ func addFoodLookup() { AddFuncLookup("dessert", Info{ Display: "Dessert", Category: "food", - Description: "Random dessert", + Description: "Sweet treat often enjoyed after a meal", Example: "French napoleons", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return dessert(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/game.go b/vendor/github.com/brianvoe/gofakeit/v6/game.go index aedd95026..5c1bc3691 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/game.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/game.go @@ -67,10 +67,10 @@ func addGameLookup() { AddFuncLookup("gamertag", Info{ Display: "Gamertag", Category: "game", - Description: "Random gamertag", + Description: "User-selected online username or alias used for identification in games", Example: "footinterpret63", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return gamertag(r), nil }, }) @@ -78,14 +78,14 @@ func addGameLookup() { AddFuncLookup("dice", Info{ Display: "Dice", Category: "game", - Description: "Random dice outputs", - Example: "footinterpret63", + Description: "Small, cube-shaped objects used in games of chance for random outcomes", + Example: "[5, 2, 3]", Output: "[]uint", Params: []Param{ {Field: "numdice", Display: "Number of Dice", Type: "uint", Default: "1", Description: "Number of dice to roll"}, {Field: "sides", Display: "Number of Sides", Type: "[]uint", Default: "[6]", Description: "Number of sides on each dice"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { numDice, err := info.GetUint(m, "numdice") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/generate.go b/vendor/github.com/brianvoe/gofakeit/v6/generate.go index 4f6043121..342a3a594 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/generate.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/generate.go @@ -1,6 +1,7 @@ package gofakeit import ( + "encoding/json" "errors" "fmt" "math" @@ -46,6 +47,11 @@ func generate(r *rand.Rand, dataVal string) string { dataVal = replaceWithNumbers(r, dataVal) dataVal = replaceWithLetters(r, dataVal) + // Check if string has any replaceable values + if !strings.Contains(dataVal, "{") && !strings.Contains(dataVal, "}") { + return dataVal + } + // Variables to identify the index in which it exists startCurly := -1 startCurlyIgnore := []int{} @@ -146,22 +152,147 @@ func generate(r *rand.Rand, dataVal string) string { return dataVal } +// FixedWidthOptions defines values needed for csv generation +type FixedWidthOptions struct { + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` +} + +// FixedWidth generates an table of random data in fixed width format +// A nil FixedWidthOptions returns a randomly structured FixedWidth. +func FixedWidth(co *FixedWidthOptions) (string, error) { return fixeWidthFunc(globalFaker.Rand, co) } + +// FixedWidth generates an table of random data in fixed width format +// A nil FixedWidthOptions returns a randomly structured FixedWidth. +func (f *Faker) FixedWidth(co *FixedWidthOptions) (string, error) { return fixeWidthFunc(f.Rand, co) } + +// Function to generate a fixed width document +func fixeWidthFunc(r *rand.Rand, co *FixedWidthOptions) (string, error) { + // If we didn't get FixedWidthOptions, create a new random one + if co == nil { + co = &FixedWidthOptions{} + } + + // Make sure you set a row count + if co.RowCount <= 0 { + co.RowCount = r.Intn(10) + 1 + } + + // Check fields + if len(co.Fields) <= 0 { + // Create random fields + co.Fields = []Field{ + {Name: "Name", Function: "{firstname} {lastname}"}, + {Name: "Email", Function: "email"}, + {Name: "Password", Function: "password", Params: MapParams{"special": {"false"}, "space": {"false"}}}, + } + } + + data := [][]string{} + hasHeader := false + + // Loop through fields, generate data and add to data array + for _, field := range co.Fields { + // Start new row + row := []string{} + + // Add name to first value + if field.Name != "" { + hasHeader = true + } + row = append(row, field.Name) + + // Get function + funcInfo := GetFuncLookup(field.Function) + var value any + if funcInfo == nil { + // Try to run the function through generate + for i := 0; i < co.RowCount; i++ { + row = append(row, generate(r, field.Function)) + } + } else { + // Generate function value + var err error + for i := 0; i < co.RowCount; i++ { + value, err = funcInfo.Generate(r, &field.Params, funcInfo) + if err != nil { + value = "" + } + + // Add value to row + row = append(row, anyToString(value)) + } + } + + // Add row to data + data = append(data, row) + } + + var result strings.Builder + + // Calculate column widths + colWidths := make([]int, len(data)) + for i, row := range data { + for _, value := range row { + width := len(value) + 5 + if width > colWidths[i] { + colWidths[i] = width + } + } + } + + // Append table rows to the string, excluding the entire row if the first value is empty + for i := 0; i < len(data[0]); i++ { + if !hasHeader && i == 0 { + continue // Skip the entire column if the first value is empty + } + + var resultRow strings.Builder + for j, row := range data { + resultRow.WriteString(fmt.Sprintf("%-*s", colWidths[j], row[i])) + } + + // Trim trailing spaces + result.WriteString(strings.TrimRight(resultRow.String(), " ")) + + // Only add new line if not the last row + if i != len(data[0])-1 { + result.WriteString("\n") + } + } + + return result.String(), nil +} + // Regex will generate a string based upon a RE2 syntax func Regex(regexStr string) string { return regex(globalFaker.Rand, regexStr) } // Regex will generate a string based upon a RE2 syntax func (f *Faker) Regex(regexStr string) string { return regex(f.Rand, regexStr) } -func regex(r *rand.Rand, regexStr string) string { +func regex(r *rand.Rand, regexStr string) (gen string) { re, err := syntax.Parse(regexStr, syntax.Perl) if err != nil { return "Could not parse regex string" } - return regexGenerate(r, re) + // Panic catch + defer func() { + if r := recover(); r != nil { + gen = fmt.Sprint(r) + return + + } + }() + + return regexGenerate(r, re, len(regexStr)*100) } -func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { +func regexGenerate(ra *rand.Rand, re *syntax.Regexp, limit int) string { + if limit <= 0 { + panic("Length limit reached when generating output") + } + op := re.Op switch op { case syntax.OpNoMatch: // matches no strings @@ -226,12 +357,12 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { case syntax.OpWordBoundary: // matches word boundary `\b` case syntax.OpNoWordBoundary: // matches word non-boundary `\B` case syntax.OpCapture: // capturing subexpression with index Cap, optional name Name - return regexGenerate(ra, re.Sub0[0]) + return regexGenerate(ra, re.Sub0[0], limit) case syntax.OpStar: // matches Sub[0] zero or more times var b strings.Builder for i := 0; i < number(ra, 0, 10); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() @@ -239,7 +370,7 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { var b strings.Builder for i := 0; i < number(ra, 1, 10); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() @@ -247,7 +378,7 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { var b strings.Builder for i := 0; i < number(ra, 0, 1); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() @@ -260,31 +391,31 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { } for i := 0; i < re.Min || i < (re.Min+count); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() case syntax.OpConcat: // matches concatenation of Subs var b strings.Builder for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } return b.String() case syntax.OpAlternate: // matches alternation of Subs - return regexGenerate(ra, re.Sub[number(ra, 0, len(re.Sub)-1)]) + return regexGenerate(ra, re.Sub[number(ra, 0, len(re.Sub)-1)], limit) } return "" } // Map will generate a random set of map data -func Map() map[string]interface{} { return mapFunc(globalFaker.Rand) } +func Map() map[string]any { return mapFunc(globalFaker.Rand) } // Map will generate a random set of map data -func (f *Faker) Map() map[string]interface{} { return mapFunc(f.Rand) } +func (f *Faker) Map() map[string]any { return mapFunc(f.Rand) } -func mapFunc(r *rand.Rand) map[string]interface{} { - m := map[string]interface{}{} +func mapFunc(r *rand.Rand) map[string]any { + m := map[string]any{} randWordType := func() string { s := randomString(r, []string{"lorem", "bs", "job", "name", "address"}) @@ -321,7 +452,7 @@ func mapFunc(r *rand.Rand) map[string]interface{} { case "slice": m[word(r)] = randSlice() case "map": - mm := map[string]interface{}{} + mm := map[string]any{} tt := randomString(r, []string{"string", "int", "float", "slice"}) switch tt { case "string": @@ -350,7 +481,7 @@ func addGenerateLookup() { Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "String value to generate from"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -358,23 +489,72 @@ func addGenerateLookup() { // Limit the length of the string passed if len(str) > 1000 { - return nil, errors.New("string length is too large. Limit to 1000 characters") + return nil, errors.New("string length is too large. limit to 1000 characters") } return generate(r, str), nil }, }) + AddFuncLookup("fixed_width", Info{ + Display: "Fixed Width", + Category: "generate", + Description: "Fixed width rows of output data based on input fields", + Example: `Name Email Password Age +Markus Moen sylvanmraz@murphy.net 6VlvH6qqXc7g 13 +Alayna Wuckert santinostanton@carroll.biz g7sLrS0gEwLO 46 +Lura Lockman zacherykuhic@feil.name S8gV7Z64KlHG 12`, + Output: "[]byte", + ContentType: "text/plain", + Params: []Param{ + {Field: "rowcount", Display: "Row Count", Type: "int", Default: "10", Description: "Number of rows"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields name, function and params"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + co := FixedWidthOptions{} + + rowCount, err := info.GetInt(m, "rowcount") + if err != nil { + return nil, err + } + + co.RowCount = rowCount + + fields, _ := info.GetStringArray(m, "fields") + + // Check to make sure fields has length + if len(fields) > 0 { + co.Fields = make([]Field, len(fields)) + for i, f := range fields { + // Unmarshal fields string into fields array + err = json.Unmarshal([]byte(f), &co.Fields[i]) + if err != nil { + return nil, err + } + } + } else { + return nil, errors.New("missing fields") + } + + out, err := fixeWidthFunc(r, &co) + if err != nil { + return nil, err + } + + return out, nil + }, + }) + AddFuncLookup("regex", Info{ Display: "Regex", Category: "generate", - Description: "Random string generated from regex RE2 syntax string", + Description: "Pattern-matching tool used in text processing to search and manipulate strings", Example: "[abcdef]{5} - affec", Output: "string", Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "Regex RE2 syntax string"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -382,7 +562,7 @@ func addGenerateLookup() { // Limit the length of the string passed if len(str) > 500 { - return nil, errors.New("string length is too large. Limit to 500 characters") + return nil, errors.New("string length is too large. limit to 500 characters") } return regex(r, str), nil @@ -392,11 +572,17 @@ func addGenerateLookup() { AddFuncLookup("map", Info{ Display: "Map", Category: "generate", - Description: "Random map of generated data", - Example: `map[consult:respond context:9285735]`, - Output: "map[string]interface{}", + Description: "Data structure that stores key-value pairs", + Example: `{ + "software": 7518355, + "that": ["despite", "pack", "whereas", "recently", "there", "anyone", "time", "read"], + "use": 683598, + "whom": "innovate", + "yourselves": 1987784 +}`, + Output: "map[string]any", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return mapFunc(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/hacker.go b/vendor/github.com/brianvoe/gofakeit/v6/hacker.go index 07ce8fdd8..393c558ec 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/hacker.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/hacker.go @@ -71,10 +71,10 @@ func addHackerLookup() { AddFuncLookup("hackerphrase", Info{ Display: "Hacker Phrase", Category: "hacker", - Description: "Random hacker phrase", + Description: "Informal jargon and slang used in the hacking and cybersecurity community", Example: "If we calculate the program, we can get to the AI pixel through the redundant XSS matrix!", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerPhrase(r), nil }, }) @@ -82,10 +82,10 @@ func addHackerLookup() { AddFuncLookup("hackerabbreviation", Info{ Display: "Hacker Abbreviation", Category: "hacker", - Description: "Random hacker abbreviation", + Description: "Abbreviations and acronyms commonly used in the hacking and cybersecurity community", Example: "ADP", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerAbbreviation(r), nil }, }) @@ -93,10 +93,10 @@ func addHackerLookup() { AddFuncLookup("hackeradjective", Info{ Display: "Hacker Adjective", Category: "hacker", - Description: "Random hacker adjective", + Description: "Adjectives describing terms often associated with hackers and cybersecurity experts", Example: "wireless", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerAdjective(r), nil }, }) @@ -104,10 +104,10 @@ func addHackerLookup() { AddFuncLookup("hackernoun", Info{ Display: "Hacker Noun", Category: "hacker", - Description: "Random hacker noun", + Description: "Noun representing an element, tool, or concept within the realm of hacking and cybersecurity", Example: "driver", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerNoun(r), nil }, }) @@ -115,10 +115,10 @@ func addHackerLookup() { AddFuncLookup("hackerverb", Info{ Display: "Hacker Verb", Category: "hacker", - Description: "Random hacker verb", + Description: "Verbs associated with actions and activities in the field of hacking and cybersecurity", Example: "synthesize", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerVerb(r), nil }, }) @@ -126,10 +126,10 @@ func addHackerLookup() { AddFuncLookup("hackeringverb", Info{ Display: "Hackering Verb", Category: "hacker", - Description: "Random hackering verb", + Description: "Verb describing actions and activities related to hacking, often involving computer systems and security", Example: "connecting", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackeringVerb(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/helpers.go b/vendor/github.com/brianvoe/gofakeit/v6/helpers.go index d0212f97e..3dcf849b7 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/helpers.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/helpers.go @@ -3,6 +3,8 @@ package gofakeit import ( crand "crypto/rand" "encoding/binary" + "encoding/json" + "fmt" "math" "math/rand" "reflect" @@ -15,7 +17,8 @@ import ( const lowerStr = "abcdefghijklmnopqrstuvwxyz" const upperStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" const numericStr = "0123456789" -const specialStr = "!@#$%&*+-_=?:;,.|(){}<>" +const specialStr = "@#$%&?|!(){}<>=*+-_:;,." +const specialSafeStr = "@#$&?!-_*." const spaceStr = " " const allStr = lowerStr + upperStr + numericStr + specialStr + spaceStr const vowels = "aeiou" @@ -223,7 +226,7 @@ func equalSliceInt(a, b []int) bool { return true } -func equalSliceInterface(a, b []interface{}) bool { +func equalSliceInterface(a, b []any) bool { sizeA, sizeB := len(a), len(b) if sizeA != sizeB { return false @@ -246,6 +249,28 @@ func stringInSlice(a string, list []string) bool { return false } +func anyToString(a any) string { + if a == nil { + return "" + } + + // If it's a slice of bytes or struct, unmarshal it into an interface + if bytes, ok := a.([]byte); ok { + return string(bytes) + } + + // If it's a struct, map, or slice, convert to JSON + switch reflect.TypeOf(a).Kind() { + case reflect.Struct, reflect.Map, reflect.Slice: + b, err := json.Marshal(a) + if err == nil { + return string(b) + } + } + + return fmt.Sprintf("%v", a) +} + // Title returns a copy of the string s with all Unicode letters that begin words // mapped to their Unicode title case func title(s string) string { diff --git a/vendor/github.com/brianvoe/gofakeit/v6/hipster.go b/vendor/github.com/brianvoe/gofakeit/v6/hipster.go index 4421f5c5d..0369f17e1 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/hipster.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/hipster.go @@ -49,10 +49,10 @@ func addHipsterLookup() { AddFuncLookup("hipsterword", Info{ Display: "Hipster Word", Category: "hipster", - Description: "Random hipster word", + Description: "Trendy and unconventional vocabulary used by hipsters to express unique cultural preferences", Example: "microdosing", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hipsterWord(r), nil }, }) @@ -60,13 +60,13 @@ func addHipsterLookup() { AddFuncLookup("hipstersentence", Info{ Display: "Hipster Sentence", Category: "hipster", - Description: "Random hipster sentence", + Description: "Sentence showcasing the use of trendy and unconventional vocabulary associated with hipster culture", Example: "Microdosing roof chia echo pickled.", Output: "string", Params: []Param{ {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { wordCount, err := info.GetInt(m, "wordcount") if err != nil { return nil, err @@ -82,16 +82,20 @@ func addHipsterLookup() { AddFuncLookup("hipsterparagraph", Info{ Display: "Hipster Paragraph", Category: "hipster", - Description: "Random hipster paragraph", - Example: "Microdosing roof chia echo pickled meditation cold-pressed raw denim fingerstache normcore sriracha pork belly. Wolf try-hard pop-up blog tilde hashtag health butcher waistcoat paleo portland vinegar. Microdosing sartorial blue bottle slow-carb freegan five dollar toast you probably haven't heard of them asymmetrical chia farm-to-table narwhal banjo. Gluten-free blog authentic literally synth vinyl meh ethical health fixie banh mi Yuccie. Try-hard drinking squid seitan cray VHS echo chillwave hammock kombucha food truck sustainable.
Pug bushwick hella tote bag cliche direct trade waistcoat yr waistcoat knausgaard pour-over master. Pitchfork jean shorts franzen flexitarian distillery hella meggings austin knausgaard crucifix wolf heirloom. Crucifix food truck you probably haven't heard of them trust fund fixie gentrify pitchfork stumptown mlkshk umami chambray blue bottle. 3 wolf moon swag +1 biodiesel knausgaard semiotics taxidermy meh artisan hoodie +1 blue bottle. Fashion axe forage mixtape Thundercats pork belly whatever 90's beard selfies chambray cred mlkshk.
Shabby chic typewriter VHS readymade lo-fi bitters PBR&B gentrify lomo raw denim freegan put a bird on it. Raw denim cliche dreamcatcher pug fixie park trust fund migas fingerstache sriracha +1 mustache. Tilde shoreditch kickstarter franzen dreamcatcher green juice mustache neutra polaroid stumptown organic schlitz. Flexitarian ramps chicharrones kogi lo-fi mustache tilde forage street church-key williamsburg taxidermy. Chia mustache plaid mumblecore squid slow-carb disrupt Thundercats goth shoreditch master direct trade.", - Output: "string", + Description: "Paragraph showcasing the use of trendy and unconventional vocabulary associated with hipster culture", + Example: `Microdosing roof chia echo pickled meditation cold-pressed raw denim fingerstache normcore sriracha pork belly. Wolf try-hard pop-up blog tilde hashtag health butcher waistcoat paleo portland vinegar. Microdosing sartorial blue bottle slow-carb freegan five dollar toast you probably haven't heard of them asymmetrical chia farm-to-table narwhal banjo. Gluten-free blog authentic literally synth vinyl meh ethical health fixie banh mi Yuccie. Try-hard drinking squid seitan cray VHS echo chillwave hammock kombucha food truck sustainable. + +Pug bushwick hella tote bag cliche direct trade waistcoat yr waistcoat knausgaard pour-over master. Pitchfork jean shorts franzen flexitarian distillery hella meggings austin knausgaard crucifix wolf heirloom. Crucifix food truck you probably haven't heard of them trust fund fixie gentrify pitchfork stumptown mlkshk umami chambray blue bottle. 3 wolf moon swag +1 biodiesel knausgaard semiotics taxidermy meh artisan hoodie +1 blue bottle. Fashion axe forage mixtape Thundercats pork belly whatever 90's beard selfies chambray cred mlkshk. + +Shabby chic typewriter VHS readymade lo-fi bitters PBR&B gentrify lomo raw denim freegan put a bird on it. Raw denim cliche dreamcatcher pug fixie park trust fund migas fingerstache sriracha +1 mustache. Tilde shoreditch kickstarter franzen dreamcatcher green juice mustache neutra polaroid stumptown organic schlitz. Flexitarian ramps chicharrones kogi lo-fi mustache tilde forage street church-key williamsburg taxidermy. Chia mustache plaid mumblecore squid slow-carb disrupt Thundercats goth shoreditch master direct trade.`, + Output: "string", Params: []Param{ {Field: "paragraphcount", Display: "Paragraph Count", Type: "int", Default: "2", Description: "Number of paragraphs"}, {Field: "sentencecount", Display: "Sentence Count", Type: "int", Default: "2", Description: "Number of sentences in a paragraph"}, {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, {Field: "paragraphseparator", Display: "Paragraph Separator", Type: "string", Default: "
", Description: "String value to add between paragraphs"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { paragraphCount, err := info.GetInt(m, "paragraphcount") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/image.go b/vendor/github.com/brianvoe/gofakeit/v6/image.go index a820a4222..e7c40dd87 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/image.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/image.go @@ -71,14 +71,14 @@ func addImageLookup() { AddFuncLookup("imageurl", Info{ Display: "Image URL", Category: "image", - Description: "Random image url", + Description: "Web address pointing to an image file that can be accessed and displayed online", Example: "https://picsum.photos/500/500", Output: "string", Params: []Param{ {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Image width in px"}, {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Image height in px"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { width, err := info.GetInt(m, "width") if err != nil { return nil, err @@ -102,7 +102,7 @@ func addImageLookup() { AddFuncLookup("imagejpeg", Info{ Display: "Image JPEG", Category: "image", - Description: "Random jpeg image", + Description: "Image file format known for its efficient compression and compatibility", Example: "file.jpeg - bytes", Output: "[]byte", ContentType: "image/jpeg", @@ -110,7 +110,7 @@ func addImageLookup() { {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Image width in px"}, {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Image height in px"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { width, err := info.GetInt(m, "width") if err != nil { return nil, err @@ -134,7 +134,7 @@ func addImageLookup() { AddFuncLookup("imagepng", Info{ Display: "Image PNG", Category: "image", - Description: "Random png image", + Description: "Image file format known for its lossless compression and support for transparency", Example: "file.png - bytes", Output: "[]byte", ContentType: "image/png", @@ -142,7 +142,7 @@ func addImageLookup() { {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Image width in px"}, {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Image height in px"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { width, err := info.GetInt(m, "width") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/internet.go b/vendor/github.com/brianvoe/gofakeit/v6/internet.go index 1cc207b37..a0fcd9bb4 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/internet.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/internet.go @@ -266,10 +266,10 @@ func addInternetLookup() { AddFuncLookup("url", Info{ Display: "URL", Category: "internet", - Description: "Random url", + Description: "Web address that specifies the location of a resource on the internet", Example: "http://www.principalproductize.biz/target", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return url(r), nil }, }) @@ -277,10 +277,10 @@ func addInternetLookup() { AddFuncLookup("domainname", Info{ Display: "Domain Name", Category: "internet", - Description: "Random domain name", + Description: "Human-readable web address used to identify websites on the internet", Example: "centraltarget.biz", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return domainName(r), nil }, }) @@ -288,10 +288,10 @@ func addInternetLookup() { AddFuncLookup("domainsuffix", Info{ Display: "Domain Suffix", Category: "internet", - Description: "Random domain suffix", + Description: "The part of a domain name that comes after the last dot, indicating its type or purpose", Example: "org", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return domainSuffix(r), nil }, }) @@ -299,10 +299,10 @@ func addInternetLookup() { AddFuncLookup("ipv4address", Info{ Display: "IPv4 Address", Category: "internet", - Description: "Random ip address v4", + Description: "Numerical label assigned to devices on a network for identification and communication", Example: "222.83.191.222", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return ipv4Address(r), nil }, }) @@ -310,10 +310,10 @@ func addInternetLookup() { AddFuncLookup("ipv6address", Info{ Display: "IPv6 Address", Category: "internet", - Description: "Random ip address v6", + Description: "Numerical label assigned to devices on a network, providing a larger address space than IPv4 for internet communication", Example: "2001:cafe:8898:ee17:bc35:9064:5866:d019", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return ipv6Address(r), nil }, }) @@ -321,10 +321,10 @@ func addInternetLookup() { AddFuncLookup("httpmethod", Info{ Display: "HTTP Method", Category: "internet", - Description: "Random http method", + Description: "Verb used in HTTP requests to specify the desired action to be performed on a resource", Example: "HEAD", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpMethod(r), nil }, }) @@ -332,10 +332,10 @@ func addInternetLookup() { AddFuncLookup("loglevel", Info{ Display: "Log Level", Category: "internet", - Description: "Random log level", + Description: "Classification used in logging to indicate the severity or priority of a log entry", Example: "error", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return logLevel(r, ""), nil }, }) @@ -343,10 +343,10 @@ func addInternetLookup() { AddFuncLookup("useragent", Info{ Display: "User Agent", Category: "internet", - Description: "Random browser user agent", + Description: "String sent by a web browser to identify itself when requesting web content", Example: "Mozilla/5.0 (Windows NT 5.0) AppleWebKit/5362 (KHTML, like Gecko) Chrome/37.0.834.0 Mobile Safari/5362", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return userAgent(r), nil }, }) @@ -354,10 +354,10 @@ func addInternetLookup() { AddFuncLookup("chromeuseragent", Info{ Display: "Chrome User Agent", Category: "internet", - Description: "Random chrome user agent", + Description: "The specific identification string sent by the Google Chrome web browser when making requests on the internet", Example: "Mozilla/5.0 (X11; Linux i686) AppleWebKit/5312 (KHTML, like Gecko) Chrome/39.0.836.0 Mobile Safari/5312", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return chromeUserAgent(r), nil }, }) @@ -365,10 +365,10 @@ func addInternetLookup() { AddFuncLookup("firefoxuseragent", Info{ Display: "Firefox User Agent", Category: "internet", - Description: "Random browser user agent", + Description: "The specific identification string sent by the Firefox web browser when making requests on the internet", Example: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_8_3 rv:7.0) Gecko/1900-07-01 Firefox/37.0", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return firefoxUserAgent(r), nil }, }) @@ -376,10 +376,10 @@ func addInternetLookup() { AddFuncLookup("operauseragent", Info{ Display: "Opera User Agent", Category: "internet", - Description: "Random browser user agent", + Description: "The specific identification string sent by the Opera web browser when making requests on the internet", Example: "Opera/8.39 (Macintosh; U; PPC Mac OS X 10_8_7; en-US) Presto/2.9.335 Version/10.00", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return operaUserAgent(r), nil }, }) @@ -387,10 +387,10 @@ func addInternetLookup() { AddFuncLookup("safariuseragent", Info{ Display: "Safari User Agent", Category: "internet", - Description: "Random safari user agent", + Description: "The specific identification string sent by the Safari web browser when making requests on the internet", Example: "Mozilla/5.0 (iPad; CPU OS 8_3_2 like Mac OS X; en-US) AppleWebKit/531.15.6 (KHTML, like Gecko) Version/4.0.5 Mobile/8B120 Safari/6531.15.6", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return safariUserAgent(r), nil }, }) @@ -401,7 +401,7 @@ func addInternetLookup() { Description: "Random http status code", Example: "200", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpStatusCode(r), nil }, }) @@ -409,10 +409,10 @@ func addInternetLookup() { AddFuncLookup("httpstatuscodesimple", Info{ Display: "HTTP Status Code Simple", Category: "internet", - Description: "Random http status code within more general usage codes", + Description: "Three-digit number returned by a web server to indicate the outcome of an HTTP request", Example: "404", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpStatusCodeSimple(r), nil }, }) @@ -420,11 +420,22 @@ func addInternetLookup() { AddFuncLookup("httpversion", Info{ Display: "HTTP Version", Category: "internet", - Description: "Random http version", + Description: "Number indicating the version of the HTTP protocol used for communication between a client and a server", Example: "HTTP/1.1", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpVersion(r), nil }, }) + + AddFuncLookup("macaddress", Info{ + Display: "MAC Address", + Category: "internet", + Description: "Unique identifier assigned to network interfaces, often used in Ethernet networks", + Example: "cb:ce:06:94:22:e9", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return macAddress(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/json.go b/vendor/github.com/brianvoe/gofakeit/v6/json.go index b284fed61..8edf5b458 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/json.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/json.go @@ -4,20 +4,23 @@ import ( "bytes" "encoding/json" "errors" + "fmt" "math/rand" + "reflect" + "strconv" ) // JSONOptions defines values needed for json generation type JSONOptions struct { - Type string `json:"type" xml:"type"` // array or object - RowCount int `json:"row_count" xml:"row_count"` - Fields []Field `json:"fields" xml:"fields"` + Type string `json:"type" xml:"type" fake:"{randomstring:[array,object]}"` // array or object + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` Indent bool `json:"indent" xml:"indent"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } type jsonKeyVal struct { Key string - Value interface{} + Value any } type jsonOrderedKeyVal []*jsonKeyVal @@ -54,14 +57,24 @@ func (okv jsonOrderedKeyVal) MarshalJSON() ([]byte, error) { return buf.Bytes(), nil } -// JSON generates an object or an array of objects in json format -func JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(globalFaker.Rand, jo) } +// JSON generates an object or an array of objects in json format. +// A nil JSONOptions returns a randomly structured JSON. +func JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(globalFaker, jo) } -// JSON generates an object or an array of objects in json format -func (f *Faker) JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(f.Rand, jo) } +// JSON generates an object or an array of objects in json format. +// A nil JSONOptions returns a randomly structured JSON. +func (f *Faker) JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(f, jo) } // JSON generates an object or an array of objects in json format -func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { +func jsonFunc(f *Faker, jo *JSONOptions) ([]byte, error) { + if jo == nil { + // We didn't get a JSONOptions, so create a new random one + err := f.Struct(&jo) + if err != nil { + return nil, err + } + } + // Check to make sure they passed in a type if jo.Type != "array" && jo.Type != "object" { return nil, errors.New("invalid type, must be array or object") @@ -74,7 +87,7 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { if jo.Type == "object" { v := make(jsonOrderedKeyVal, len(jo.Fields)) - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for i, field := range jo.Fields { if field.Function == "autoincrement" { // Object only has one @@ -89,14 +102,14 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { } // Call function value - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } if _, ok := value.([]byte); ok { // If it's a slice, unmarshal it into an interface - var val interface{} + var val any err := json.Unmarshal(value.([]byte), &val) if err != nil { return nil, err @@ -129,7 +142,7 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { for i := 0; i < int(jo.RowCount); i++ { vr := make(jsonOrderedKeyVal, len(jo.Fields)) - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for ii, field := range jo.Fields { if field.Function == "autoincrement" { vr[ii] = &jsonKeyVal{Key: field.Name, Value: i + 1} // +1 because index starts with 0 @@ -143,14 +156,14 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { } // Call function value - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } if _, ok := value.([]byte); ok { // If it's a slice, unmarshal it into an interface - var val interface{} + var val any err := json.Unmarshal(value.([]byte), &val) if err != nil { return nil, err @@ -181,21 +194,21 @@ func addFileJSONLookup() { AddFuncLookup("json", Info{ Display: "JSON", Category: "file", - Description: "Generates an object or an array of objects in json format", + Description: "Format for structured data interchange used in programming, returns an object or an array of objects", Example: `[ - { "id": 1, "first_name": "Markus", "last_name": "Moen" }, - { "id": 2, "first_name": "Alayna", "last_name": "Wuckert" }, - { "id": 3, "first_name": "Lura", "last_name": "Lockman" } + { "first_name": "Markus", "last_name": "Moen", "password": "Dc0VYXjkWABx" }, + { "first_name": "Osborne", "last_name": "Hilll", "password": "XPJ9OVNbs5lm" }, + { "first_name": "Mertie", "last_name": "Halvorson", "password": "eyl3bhwfV8wA" } ]`, Output: "[]byte", ContentType: "application/json", Params: []Param{ {Field: "type", Display: "Type", Type: "string", Default: "object", Options: []string{"object", "array"}, Description: "Type of JSON, object or array"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows in JSON array"}, - {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, {Field: "indent", Display: "Indent", Type: "bool", Default: "false", Description: "Whether or not to add indents and newlines"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { jo := JSONOptions{} typ, err := info.GetString(m, "type") @@ -210,6 +223,12 @@ func addFileJSONLookup() { } jo.RowCount = rowcount + indent, err := info.GetBool(m, "indent") + if err != nil { + return nil, err + } + jo.Indent = indent + fieldsStr, err := info.GetStringArray(m, "fields") if err != nil { return nil, err @@ -228,13 +247,89 @@ func addFileJSONLookup() { } } - indent, err := info.GetBool(m, "indent") - if err != nil { - return nil, err - } - jo.Indent = indent - - return jsonFunc(r, &jo) + f := &Faker{Rand: r} + return jsonFunc(f, &jo) }, }) } + +// encoding/json.RawMessage is a special case of []byte +// it cannot be handled as a reflect.Array/reflect.Slice +// because it needs additional structure in the output +func rJsonRawMessage(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { + b, err := f.JSON(nil) + if err != nil { + return err + } + + v.SetBytes(b) + return nil +} + +// encoding/json.Number is a special case of string +// that represents a JSON number literal. +// It cannot be handled as a string because it needs to +// represent an integer or a floating-point number. +func rJsonNumber(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { + var ret json.Number + + var numberType string + + if tag == "" { + numberType = f.RandomString([]string{"int", "float"}) + + switch numberType { + case "int": + retInt := f.Int16() + ret = json.Number(strconv.Itoa(int(retInt))) + case "float": + retFloat := f.Float64() + ret = json.Number(strconv.FormatFloat(retFloat, 'f', -1, 64)) + } + } else { + fName, fParams := parseNameAndParamsFromTag(tag) + info := GetFuncLookup(fName) + if info == nil { + return fmt.Errorf("invalid function, %s does not exist", fName) + } + + // Parse map params + mapParams := parseMapParams(info, fParams) + + valueIface, err := info.Generate(f.Rand, mapParams, info) + if err != nil { + return err + } + + switch value := valueIface.(type) { + case int: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int8: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int16: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int32: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int64: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case uint: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint8: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint16: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint32: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint64: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case float32: + ret = json.Number(strconv.FormatFloat(float64(value), 'f', -1, 64)) + case float64: + ret = json.Number(strconv.FormatFloat(float64(value), 'f', -1, 64)) + default: + return fmt.Errorf("invalid type, %s is not a valid type for json.Number", reflect.TypeOf(value)) + } + } + v.Set(reflect.ValueOf(ret)) + return nil +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/languages.go b/vendor/github.com/brianvoe/gofakeit/v6/languages.go index bd634d570..43e0b877f 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/languages.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/languages.go @@ -48,10 +48,10 @@ func addLanguagesLookup() { AddFuncLookup("language", Info{ Display: "Language", Category: "language", - Description: "Random language", + Description: "System of communication using symbols, words, and grammar to convey meaning between individuals", Example: "Kazakh", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return language(r), nil }, }) @@ -59,10 +59,10 @@ func addLanguagesLookup() { AddFuncLookup("languageabbreviation", Info{ Display: "Language Abbreviation", Category: "language", - Description: "Random abbreviated language", + Description: "Shortened form of a language's name", Example: "kk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return languageAbbreviation(r), nil }, }) @@ -70,10 +70,10 @@ func addLanguagesLookup() { AddFuncLookup("languagebcp", Info{ Display: "Language BCP", Category: "language", - Description: "Random language BCP (Best Current Practices)", + Description: "Set of guidelines and standards for identifying and representing languages in computing and internet protocols", Example: "en-US", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return languageBCP(r), nil }, }) @@ -81,10 +81,10 @@ func addLanguagesLookup() { AddFuncLookup("programminglanguage", Info{ Display: "Programming Language", Category: "language", - Description: "Random programming language", + Description: "Formal system of instructions used to create software and perform computational tasks", Example: "Go", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return programmingLanguage(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/lookup.go b/vendor/github.com/brianvoe/gofakeit/v6/lookup.go index 633053d1c..9bb9e9d82 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/lookup.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/lookup.go @@ -21,14 +21,15 @@ type MapParamsValue []string // Info structures fields to better break down what each one generates type Info struct { - Display string `json:"display"` - Category string `json:"category"` - Description string `json:"description"` - Example string `json:"example"` - Output string `json:"output"` - ContentType string `json:"content_type"` - Params []Param `json:"params"` - Generate func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) `json:"-"` + Display string `json:"display"` + Category string `json:"category"` + Description string `json:"description"` + Example string `json:"example"` + Output string `json:"output"` + ContentType string `json:"content_type"` + Params []Param `json:"params"` + Any any `json:"any"` + Generate func(r *rand.Rand, m *MapParams, info *Info) (any, error) `json:"-"` } // Param is a breakdown of param requirements and type definition @@ -53,49 +54,74 @@ func init() { initLookup() } // init will add all the functions to MapLookups func initLookup() { - addAuthLookup() addAddressLookup() + addAnimalLookup() + addAppLookup() + addAuthLookup() addBeerLookup() + addBookLookup() addCarLookup() - addPersonLookup() - addWordGeneralLookup() - addWordNounLookup() - addWordVerbLookup() - addWordAdverbLookup() - addWordPrepositionLookup() - addWordAdjectiveLookup() - addWordPronounLookup() - addWordConnectiveLookup() - addWordPhraseLookup() - addWordSentenceLookup() - addWordGrammerLookup() - addLoremLookup() - addGenerateLookup() - addMiscLookup() + addCelebrityLookup() addColorLookup() - addInternetLookup() - addDateTimeLookup() - addPaymentLookup() addCompanyLookup() - addHackerLookup() - addHipsterLookup() - addLanguagesLookup() - addFileLookup() + addDatabaseSQLLookup() + addDateTimeLookup() + addEmojiLookup() + addErrorLookup() + addFileCSVLookup() addFileJSONLookup() + addFileLookup() addFileXMLLookup() - addFileCSVLookup() - addEmojiLookup() + addFinanceLookup() + addFoodLookup() + addGameLookup() + addGenerateLookup() + addHackerLookup() + addHipsterLookup() + addHtmlLookup() addImageLookup() + addInternetLookup() + addLanguagesLookup() + addLoremLookup() + addMinecraftLookup() + addMiscLookup() + addMovieLookup() addNumberLookup() + addPaymentLookup() + addPersonLookup() + addProductLookup() + addSchoolLookup() addStringLookup() - addAnimalLookup() - addGameLookup() - addFoodLookup() - addAppLookup() + addTemplateLookup() addWeightedLookup() - addMinecraftLookup() - addCelebrityLookup() - addDatabaseSQLLookup() + addWordAdjectiveLookup() + addWordAdverbLookup() + addWordConnectiveLookup() + addWordGeneralLookup() + addWordGrammerLookup() + addWordNounLookup() + addWordPhraseLookup() + addWordPrepositionLookup() + addWordPronounLookup() + addWordSentenceLookup() + addWordVerbLookup() + addWordCommentLookup() + addWordMiscLookup() +} + +// internalFuncLookups is the internal map array with mapping to all available data +var internalFuncLookups map[string]Info = map[string]Info{ + "fields": { + Description: "Example fields for generating csv, json, xml, etc", + Output: "gofakeit.Field", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + function, _ := GetRandomSimpleFunc(r) + return Field{ + Name: function, + Function: function, + }, nil + }, + }, } // NewMapParams will create a new MapParams @@ -133,7 +159,7 @@ func (m *MapParamsValue) UnmarshalJSON(data []byte) error { // check if the data is an array // if so, marshal it into m if data[0] == '[' { - var values []interface{} + var values []any err := json.Unmarshal(data, &values) if err != nil { return err @@ -157,7 +183,7 @@ func (m *MapParamsValue) UnmarshalJSON(data []byte) error { } // if not, then convert into a string and add it to m - var s interface{} + var s any if err := json.Unmarshal(data, &s); err != nil { return err } @@ -166,6 +192,23 @@ func (m *MapParamsValue) UnmarshalJSON(data []byte) error { return nil } +func GetRandomSimpleFunc(r *rand.Rand) (string, Info) { + // Loop through all the functions and add them to a slice + var keys []string + for k, info := range FuncLookups { + // Only grab simple functions + if info.Params == nil { + keys = append(keys, k) + } + } + + // Randomly grab a function from the slice + randomKey := randomString(r, keys) + + // Return the function name and info + return randomKey, FuncLookups[randomKey] +} + // AddFuncLookup takes a field and adds it to map func AddFuncLookup(functionName string, info Info) { if FuncLookups == nil { @@ -184,12 +227,21 @@ func AddFuncLookup(functionName string, info Info) { // GetFuncLookup will lookup func GetFuncLookup(functionName string) *Info { - info, ok := FuncLookups[functionName] - if !ok { - return nil + var info Info + var ok bool + + // Check internal functions first + info, ok = internalFuncLookups[functionName] + if ok { + return &info + } + + info, ok = FuncLookups[functionName] + if ok { + return &info } - return &info + return nil } // RemoveFuncLookup will remove a function from lookup @@ -204,6 +256,57 @@ func RemoveFuncLookup(functionName string) { lockFuncLookups.Unlock() } +// GetAny will retrieve Any field from Info +func (i *Info) GetAny(m *MapParams, field string) (any, error) { + _, value, err := i.GetField(m, field) + if err != nil { + return nil, err + } + + var anyValue any + + // Try to convert to int + valueInt, err := strconv.ParseInt(value[0], 10, 64) + if err == nil { + return int(valueInt), nil + } + + // Try to convert to float + valueFloat, err := strconv.ParseFloat(value[0], 64) + if err == nil { + return valueFloat, nil + } + + // Try to convert to boolean + valueBool, err := strconv.ParseBool(value[0]) + if err == nil { + return valueBool, nil + } + + err = json.Unmarshal([]byte(value[0]), &anyValue) + if err == nil { + return valueBool, nil + } + + return value[0], nil +} + +// GetMap will retrieve map[string]any field from data +func (i *Info) GetMap(m *MapParams, field string) (map[string]any, error) { + _, value, err := i.GetField(m, field) + if err != nil { + return nil, err + } + + var mapValue map[string]any + err = json.Unmarshal([]byte(value[0]), &mapValue) + if err != nil { + return nil, fmt.Errorf("%s field could not parse to map[string]any", field) + } + + return mapValue, nil +} + // GetField will retrieve field from data func (i *Info) GetField(m *MapParams, field string) (*Param, []string, error) { // Get param diff --git a/vendor/github.com/brianvoe/gofakeit/v6/lorem.go b/vendor/github.com/brianvoe/gofakeit/v6/lorem.go index 59290c121..bf11bce7c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/lorem.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/lorem.go @@ -45,10 +45,10 @@ func addLoremLookup() { AddFuncLookup("loremipsumword", Info{ Display: "Lorem Ipsum Word", Category: "word", - Description: "Random lorem ipsum word", + Description: "Word of the Lorem Ipsum placeholder text used in design and publishing", Example: "quia", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return loremIpsumWord(r), nil }, }) @@ -56,13 +56,13 @@ func addLoremLookup() { AddFuncLookup("loremipsumsentence", Info{ Display: "Lorem Ipsum Sentence", Category: "word", - Description: "Random lorem ipsum sentence", + Description: "Sentence of the Lorem Ipsum placeholder text used in design and publishing", Example: "Quia quae repellat consequatur quidem.", Output: "string", Params: []Param{ {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { wordCount, err := info.GetInt(m, "wordcount") if err != nil { return nil, err @@ -78,16 +78,20 @@ func addLoremLookup() { AddFuncLookup("loremipsumparagraph", Info{ Display: "Lorem Ipsum Paragraph", Category: "word", - Description: "Random lorem ipsum paragraph", - Example: "Quia quae repellat consequatur quidem nisi quo qui voluptatum accusantium quisquam amet. Quas et ut non dolorem ipsam aut enim assumenda mollitia harum ut. Dicta similique veniam nulla voluptas at excepturi non ad maxime at non. Eaque hic repellat praesentium voluptatem qui consequuntur dolor iusto autem velit aut. Fugit tempore exercitationem harum consequatur voluptatum modi minima aut eaque et et.
Aut ea voluptatem dignissimos expedita odit tempore quod aut beatae ipsam iste. Minus voluptatibus dolorem maiores eius sed nihil vel enim odio voluptatem accusamus. Natus quibusdam temporibus tenetur cumque sint necessitatibus dolorem ex ducimus iusto ex. Voluptatem neque dicta explicabo officiis et ducimus sit ut ut praesentium pariatur. Illum molestias nisi at dolore ut voluptatem accusantium et fugiat et ut.
Explicabo incidunt reprehenderit non quia dignissimos recusandae vitae soluta quia et quia. Aut veniam voluptas consequatur placeat sapiente non eveniet voluptatibus magni velit eum. Nobis vel repellendus sed est qui autem laudantium quidem quam ullam consequatur. Aut iusto ut commodi similique quae voluptatem atque qui fugiat eum aut. Quis distinctio consequatur voluptatem vel aliquid aut laborum facere officiis iure tempora.", - Output: "string", + Description: "Paragraph of the Lorem Ipsum placeholder text used in design and publishing", + Example: `Quia quae repellat consequatur quidem nisi quo qui voluptatum accusantium quisquam amet. Quas et ut non dolorem ipsam aut enim assumenda mollitia harum ut. Dicta similique veniam nulla voluptas at excepturi non ad maxime at non. Eaque hic repellat praesentium voluptatem qui consequuntur dolor iusto autem velit aut. Fugit tempore exercitationem harum consequatur voluptatum modi minima aut eaque et et. + +Aut ea voluptatem dignissimos expedita odit tempore quod aut beatae ipsam iste. Minus voluptatibus dolorem maiores eius sed nihil vel enim odio voluptatem accusamus. Natus quibusdam temporibus tenetur cumque sint necessitatibus dolorem ex ducimus iusto ex. Voluptatem neque dicta explicabo officiis et ducimus sit ut ut praesentium pariatur. Illum molestias nisi at dolore ut voluptatem accusantium et fugiat et ut. + +Explicabo incidunt reprehenderit non quia dignissimos recusandae vitae soluta quia et quia. Aut veniam voluptas consequatur placeat sapiente non eveniet voluptatibus magni velit eum. Nobis vel repellendus sed est qui autem laudantium quidem quam ullam consequatur. Aut iusto ut commodi similique quae voluptatem atque qui fugiat eum aut. Quis distinctio consequatur voluptatem vel aliquid aut laborum facere officiis iure tempora.`, + Output: "string", Params: []Param{ {Field: "paragraphcount", Display: "Paragraph Count", Type: "int", Default: "2", Description: "Number of paragraphs"}, {Field: "sentencecount", Display: "Sentence Count", Type: "int", Default: "2", Description: "Number of sentences in a paragraph"}, {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, {Field: "paragraphseparator", Display: "Paragraph Separator", Type: "string", Default: "
", Description: "String value to add between paragraphs"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { paragraphCount, err := info.GetInt(m, "paragraphcount") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go b/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go index 7697ef986..1fb740e42 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go @@ -170,10 +170,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftore", Info{ Display: "Minecraft ore", Category: "minecraft", - Description: "Random Minecraft ore", + Description: "Naturally occurring minerals found in the game Minecraft, used for crafting purposes", Example: "coal", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftOre(r), nil }, }) @@ -181,10 +181,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftwood", Info{ Display: "Minecraft wood", Category: "minecraft", - Description: "Random Minecraft wood", + Description: "Natural resource in Minecraft, used for crafting various items and building structures", Example: "oak", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftWood(r), nil }, }) @@ -192,10 +192,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftarmortier", Info{ Display: "Minecraft armor tier", Category: "minecraft", - Description: "Random Minecraft armor tier", + Description: "Classification system for armor sets in Minecraft, indicating their effectiveness and protection level", Example: "iron", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftArmorTier(r), nil }, }) @@ -203,10 +203,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftarmorpart", Info{ Display: "Minecraft armor part", Category: "minecraft", - Description: "Random Minecraft armor part", + Description: "Component of an armor set in Minecraft, such as a helmet, chestplate, leggings, or boots", Example: "helmet", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftArmorPart(r), nil }, }) @@ -214,10 +214,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftweapon", Info{ Display: "Minecraft weapon", Category: "minecraft", - Description: "Random Minecraft weapon", + Description: "Tools and items used in Minecraft for combat and defeating hostile mobs", Example: "bow", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftWeapon(r), nil }, }) @@ -225,10 +225,10 @@ func addMinecraftLookup() { AddFuncLookup("minecrafttool", Info{ Display: "Minecraft tool", Category: "minecraft", - Description: "Random Minecraft tool", + Description: "Items in Minecraft designed for specific tasks, including mining, digging, and building", Example: "shovel", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftTool(r), nil }, }) @@ -236,10 +236,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftdye", Info{ Display: "Minecraft dye", Category: "minecraft", - Description: "Random Minecraft dye", + Description: "Items used to change the color of various in-game objects", Example: "white", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftDye(r), nil }, }) @@ -247,10 +247,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftfood", Info{ Display: "Minecraft food", Category: "minecraft", - Description: "Random Minecraft food", + Description: "Consumable items in Minecraft that provide nourishment to the player character", Example: "apple", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftFood(r), nil }, }) @@ -258,10 +258,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftanimal", Info{ Display: "Minecraft animal", Category: "minecraft", - Description: "Random Minecraft animal", + Description: "Non-hostile creatures in Minecraft, often used for resources and farming", Example: "chicken", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftAnimal(r), nil }, }) @@ -269,10 +269,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftvillagerjob", Info{ Display: "Minecraft villager job", Category: "minecraft", - Description: "Random Minecraft villager job", + Description: "The profession or occupation assigned to a villager character in the game", Example: "farmer", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftVillagerJob(r), nil }, }) @@ -280,10 +280,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftvillagerstation", Info{ Display: "Minecraft villager station", Category: "minecraft", - Description: "Random Minecraft villager station", + Description: "Designated area or structure in Minecraft where villagers perform their job-related tasks and trading", Example: "furnace", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftVillagerStation(r), nil }, }) @@ -291,10 +291,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftvillagerlevel", Info{ Display: "Minecraft villager level", Category: "minecraft", - Description: "Random Minecraft villager level", + Description: "Measure of a villager's experience and proficiency in their assigned job or profession", Example: "master", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftVillagerLevel(r), nil }, }) @@ -302,10 +302,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobpassive", Info{ Display: "Minecraft mob passive", Category: "minecraft", - Description: "Random Minecraft mob passive", + Description: "Non-aggressive creatures in the game that do not attack players", Example: "cow", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobPassive(r), nil }, }) @@ -313,10 +313,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobneutral", Info{ Display: "Minecraft mob neutral", Category: "minecraft", - Description: "Random Minecraft mob neutral", + Description: "Creature in the game that only becomes hostile if provoked, typically defending itself when attacked", Example: "bee", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobNeutral(r), nil }, }) @@ -324,10 +324,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobhostile", Info{ Display: "Minecraft mob hostile", Category: "minecraft", - Description: "Random Minecraft mob hostile", + Description: "Aggressive creatures in the game that actively attack players when encountered", Example: "spider", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobHostile(r), nil }, }) @@ -335,10 +335,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobboss", Info{ Display: "Minecraft mob boss", Category: "minecraft", - Description: "Random Minecraft mob boss", + Description: "Powerful hostile creature in the game, often found in challenging dungeons or structures", Example: "ender dragon", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobBoss(r), nil }, }) @@ -346,10 +346,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftbiome", Info{ Display: "Minecraft biome", Category: "minecraft", - Description: "Random Minecraft biome", + Description: "Distinctive environmental regions in the game, characterized by unique terrain, vegetation, and weather", Example: "forest", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftBiome(r), nil }, }) @@ -357,10 +357,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftweather", Info{ Display: "Minecraft weather", Category: "minecraft", - Description: "Random Minecraft weather", + Description: "Atmospheric conditions in the game that include rain, thunderstorms, and clear skies, affecting gameplay and ambiance", Example: "rain", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftWeather(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/misc.go b/vendor/github.com/brianvoe/gofakeit/v6/misc.go index 30a732433..aa55911e4 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/misc.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/misc.go @@ -2,7 +2,6 @@ package gofakeit import ( "encoding/hex" - "io" "math/rand" "reflect" @@ -22,13 +21,20 @@ func boolFunc(r *rand.Rand) bool { return randIntRange(r, 0, 1) == 1 } func UUID() string { return uuid(globalFaker.Rand) } // UUID (version 4) will generate a random unique identifier based upon random numbers -// Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 8-4-4-4-12 func (f *Faker) UUID() string { return uuid(f.Rand) } func uuid(r *rand.Rand) string { version := byte(4) uuid := make([]byte, 16) - io.ReadFull(r, uuid[:]) + + // Commented out due to io.ReadFull not being race condition safe + // io.ReadFull(r, uuid[:]) + + // Read 16 random bytes + for i := 0; i < 16; i++ { + uuid[i] = byte(r.Intn(256)) + } // Set version uuid[6] = (uuid[6] & 0x0f) | (version << 4) @@ -51,12 +57,12 @@ func uuid(r *rand.Rand) string { } // ShuffleAnySlice takes in a slice and outputs it in a random order -func ShuffleAnySlice(v interface{}) { shuffleAnySlice(globalFaker.Rand, v) } +func ShuffleAnySlice(v any) { shuffleAnySlice(globalFaker.Rand, v) } // ShuffleAnySlice takes in a slice and outputs it in a random order -func (f *Faker) ShuffleAnySlice(v interface{}) { shuffleAnySlice(f.Rand, v) } +func (f *Faker) ShuffleAnySlice(v any) { shuffleAnySlice(f.Rand, v) } -func shuffleAnySlice(r *rand.Rand, v interface{}) { +func shuffleAnySlice(r *rand.Rand, v any) { if v == nil { return } @@ -103,12 +109,12 @@ func flipACoin(r *rand.Rand) string { } // RandomMapKey will return a random key from a map -func RandomMapKey(mapI interface{}) interface{} { return randomMapKey(globalFaker.Rand, mapI) } +func RandomMapKey(mapI any) any { return randomMapKey(globalFaker.Rand, mapI) } // RandomMapKey will return a random key from a map -func (f *Faker) RandomMapKey(mapI interface{}) interface{} { return randomMapKey(f.Rand, mapI) } +func (f *Faker) RandomMapKey(mapI any) any { return randomMapKey(f.Rand, mapI) } -func randomMapKey(r *rand.Rand, mapI interface{}) interface{} { +func randomMapKey(r *rand.Rand, mapI any) any { keys := reflect.ValueOf(mapI).MapKeys() return keys[r.Intn(len(keys))].Interface() } @@ -130,10 +136,10 @@ func addMiscLookup() { AddFuncLookup("uuid", Info{ Display: "UUID", Category: "misc", - Description: "Random uuid", + Description: "128-bit identifier used to uniquely identify objects or entities in computer systems", Example: "590c1440-9888-45b0-bd51-a817ee07c3f2", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uuid(r), nil }, }) @@ -141,10 +147,10 @@ func addMiscLookup() { AddFuncLookup("bool", Info{ Display: "Boolean", Category: "misc", - Description: "Random boolean", + Description: "Data type that represents one of two possible values, typically true or false", Example: "true", Output: "bool", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return boolFunc(r), nil }, }) @@ -152,10 +158,10 @@ func addMiscLookup() { AddFuncLookup("flipacoin", Info{ Display: "Flip A Coin", Category: "misc", - Description: "Random Heads or Tails outcome", + Description: "Decision-making method involving the tossing of a coin to determine outcomes", Example: "Tails", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return flipACoin(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/number.go b/vendor/github.com/brianvoe/gofakeit/v6/number.go index db6fd7675..7200a5988 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/number.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/number.go @@ -253,14 +253,14 @@ func addNumberLookup() { AddFuncLookup("number", Info{ Display: "Number", Category: "number", - Description: "Random number between given range", + Description: "Mathematical concept used for counting, measuring, and expressing quantities or values", Example: "14866", Output: "int", Params: []Param{ {Field: "min", Display: "Min", Type: "int", Default: "-2147483648", Description: "Minimum integer value"}, {Field: "max", Display: "Max", Type: "int", Default: "2147483647", Description: "Maximum integer value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetInt(m, "min") if err != nil { return nil, err @@ -278,10 +278,10 @@ func addNumberLookup() { AddFuncLookup("uint8", Info{ Display: "Uint8", Category: "number", - Description: "Random uint8 value", + Description: "Unsigned 8-bit integer, capable of representing values from 0 to 255", Example: "152", Output: "uint8", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint8Func(r), nil }, }) @@ -289,10 +289,10 @@ func addNumberLookup() { AddFuncLookup("uint16", Info{ Display: "Uint16", Category: "number", - Description: "Random uint16 value", + Description: "Unsigned 16-bit integer, capable of representing values from 0 to 65,535", Example: "34968", Output: "uint16", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint16Func(r), nil }, }) @@ -300,10 +300,10 @@ func addNumberLookup() { AddFuncLookup("uint32", Info{ Display: "Uint32", Category: "number", - Description: "Random uint32 value", + Description: "Unsigned 32-bit integer, capable of representing values from 0 to 4,294,967,295", Example: "1075055705", Output: "uint32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint32Func(r), nil }, }) @@ -311,10 +311,10 @@ func addNumberLookup() { AddFuncLookup("uint64", Info{ Display: "Uint64", Category: "number", - Description: "Random uint64 value", + Description: "Unsigned 64-bit integer, capable of representing values from 0 to 18,446,744,073,709,551,615", Example: "843730692693298265", Output: "uint64", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint64Func(r), nil }, }) @@ -322,14 +322,14 @@ func addNumberLookup() { AddFuncLookup("uintrange", Info{ Display: "UintRange", Category: "number", - Description: "Random uint value between given range", + Description: "Non-negative integer value between given range", Example: "1075055705", Output: "uint", Params: []Param{ {Field: "min", Display: "Min", Type: "uint", Default: "0", Description: "Minimum uint value"}, {Field: "max", Display: "Max", Type: "uint", Default: "4294967295", Description: "Maximum uint value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetUint(m, "min") if err != nil { return nil, err @@ -347,10 +347,10 @@ func addNumberLookup() { AddFuncLookup("int8", Info{ Display: "Int8", Category: "number", - Description: "Random int8 value", + Description: "Signed 8-bit integer, capable of representing values from -128 to 127", Example: "24", Output: "int8", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int8Func(r), nil }, }) @@ -358,10 +358,10 @@ func addNumberLookup() { AddFuncLookup("int16", Info{ Display: "Int16", Category: "number", - Description: "Random int16 value", + Description: "Signed 16-bit integer, capable of representing values from 32,768 to 32,767", Example: "2200", Output: "int16", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int16Func(r), nil }, }) @@ -369,10 +369,10 @@ func addNumberLookup() { AddFuncLookup("int32", Info{ Display: "Int32", Category: "number", - Description: "Random int32 value", + Description: "Signed 32-bit integer, capable of representing values from -2,147,483,648 to 2,147,483,647", Example: "-1072427943", Output: "int32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int32Func(r), nil }, }) @@ -380,10 +380,10 @@ func addNumberLookup() { AddFuncLookup("int64", Info{ Display: "Int64", Category: "number", - Description: "Random int64 value", + Description: "Signed 64-bit integer, capable of representing values from -9,223,372,036,854,775,808 to -9,223,372,036,854,775,807", Example: "-8379641344161477543", Output: "int64", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int64Func(r), nil }, }) @@ -391,14 +391,14 @@ func addNumberLookup() { AddFuncLookup("intrange", Info{ Display: "IntRange", Category: "number", - Description: "Random int value between min and max", + Description: "Integer value between given range", Example: "-8379477543", Output: "int", Params: []Param{ {Field: "min", Display: "Min", Type: "int", Description: "Minimum int value"}, {Field: "max", Display: "Max", Type: "int", Description: "Maximum int value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetInt(m, "min") if err != nil { return nil, err @@ -416,10 +416,10 @@ func addNumberLookup() { AddFuncLookup("float32", Info{ Display: "Float32", Category: "number", - Description: "Random float32 value", + Description: "Data type representing floating-point numbers with 32 bits of precision in computing", Example: "3.1128167e+37", Output: "float32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return float32Func(r), nil }, }) @@ -427,14 +427,14 @@ func addNumberLookup() { AddFuncLookup("float32range", Info{ Display: "Float32 Range", Category: "number", - Description: "Random float32 between given range", + Description: "Float32 value between given range", Example: "914774.6", Output: "float32", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Description: "Minimum float32 value"}, {Field: "max", Display: "Max", Type: "float", Description: "Maximum float32 value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat32(m, "min") if err != nil { return nil, err @@ -452,10 +452,10 @@ func addNumberLookup() { AddFuncLookup("float64", Info{ Display: "Float64", Category: "number", - Description: "Random float64 value", + Description: "Data type representing floating-point numbers with 64 bits of precision in computing", Example: "1.644484108270445e+307", Output: "float64", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return float64Func(r), nil }, }) @@ -463,14 +463,14 @@ func addNumberLookup() { AddFuncLookup("float64range", Info{ Display: "Float64 Range", Category: "number", - Description: "Random float64 between given range", + Description: "Float64 value between given range", Example: "914774.5585333086", Output: "float64", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Description: "Minimum float64 value"}, {Field: "max", Display: "Max", Type: "float", Description: "Maximum float64 value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err @@ -488,13 +488,13 @@ func addNumberLookup() { AddFuncLookup("shuffleints", Info{ Display: "Shuffle Ints", Category: "number", - Description: "Shuffle an array of ints", + Description: "Shuffles an array of ints", Example: "1,2,3,4 => 3,1,4,2", Output: "[]int", Params: []Param{ {Field: "ints", Display: "Integers", Type: "[]int", Description: "Delimited separated integers"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ints, err := info.GetIntArray(m, "ints") if err != nil { return nil, err @@ -506,13 +506,51 @@ func addNumberLookup() { }, }) + AddFuncLookup("randomint", Info{ + Display: "Random Int", + Category: "number", + Description: "Randomly selected value from a slice of int", + Example: "-1,2,-3,4 => -3", + Output: "int", + Params: []Param{ + {Field: "ints", Display: "Integers", Type: "[]int", Description: "Delimited separated integers"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + ints, err := info.GetIntArray(m, "ints") + if err != nil { + return nil, err + } + + return randomInt(r, ints), nil + }, + }) + + AddFuncLookup("randomuint", Info{ + Display: "Random Uint", + Category: "number", + Description: "Randomly selected value from a slice of uint", + Example: "1,2,3,4 => 4", + Output: "uint", + Params: []Param{ + {Field: "uints", Display: "Unsigned Integers", Type: "[]uint", Description: "Delimited separated unsigned integers"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + uints, err := info.GetUintArray(m, "uints") + if err != nil { + return nil, err + } + + return randomUint(r, uints), nil + }, + }) + AddFuncLookup("hexuint8", Info{ Display: "HexUint8", Category: "number", - Description: "Random uint8 hex value", + Description: "Hexadecimal representation of an 8-bit unsigned integer", Example: "0x87", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 8), nil }, }) @@ -520,10 +558,10 @@ func addNumberLookup() { AddFuncLookup("hexuint16", Info{ Display: "HexUint16", Category: "number", - Description: "Random uint16 hex value", + Description: "Hexadecimal representation of an 16-bit unsigned integer", Example: "0x8754", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 16), nil }, }) @@ -531,10 +569,10 @@ func addNumberLookup() { AddFuncLookup("hexuint32", Info{ Display: "HexUint32", Category: "number", - Description: "Random uint32 hex value", + Description: "Hexadecimal representation of an 32-bit unsigned integer", Example: "0x87546957", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 32), nil }, }) @@ -542,10 +580,10 @@ func addNumberLookup() { AddFuncLookup("hexuint64", Info{ Display: "HexUint64", Category: "number", - Description: "Random uint64 hex value", + Description: "Hexadecimal representation of an 64-bit unsigned integer", Example: "0x875469578e51b5e5", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 64), nil }, }) @@ -553,10 +591,10 @@ func addNumberLookup() { AddFuncLookup("hexuint128", Info{ Display: "HexUint128", Category: "number", - Description: "Random uint128 hex value", + Description: "Hexadecimal representation of an 128-bit unsigned integer", Example: "0x875469578e51b5e56c95b64681d147a1", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 128), nil }, }) @@ -564,10 +602,10 @@ func addNumberLookup() { AddFuncLookup("hexuint256", Info{ Display: "HexUint256", Category: "number", - Description: "Random uint256 hex value", + Description: "Hexadecimal representation of an 256-bit unsigned integer", Example: "0x875469578e51b5e56c95b64681d147a12cde48a4f417231b0c486abbc263e48d", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 256), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/payment.go b/vendor/github.com/brianvoe/gofakeit/v6/payment.go index b2248e8f6..dc4b0057b 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/payment.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/payment.go @@ -243,11 +243,14 @@ func addPaymentLookup() { AddFuncLookup("currency", Info{ Display: "Currency", Category: "payment", - Description: "Random currency data set", - Example: `{short: "USD", long: "United States Dollar"}`, + Description: "Medium of exchange, often in the form of paper money or coins, used for trade and transactions", + Example: `{ + "short": "IQD", + "long": "Iraq Dinar" +}`, Output: "map[string]string", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return currency(r), nil }, }) @@ -255,10 +258,10 @@ func addPaymentLookup() { AddFuncLookup("currencyshort", Info{ Display: "Currency Short", Category: "payment", - Description: "Random currency abbreviated", + Description: "Short 3-letter word used to represent a specific currency", Example: "USD", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return currencyShort(r), nil }, }) @@ -266,10 +269,10 @@ func addPaymentLookup() { AddFuncLookup("currencylong", Info{ Display: "Currency Long", Category: "payment", - Description: "Random currency", + Description: "Complete name of a specific currency used for official identification in financial transactions", Example: "United States Dollar", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return currencyLong(r), nil }, }) @@ -277,14 +280,14 @@ func addPaymentLookup() { AddFuncLookup("price", Info{ Display: "Price", Category: "payment", - Description: "Random monitary price", + Description: "The amount of money or value assigned to a product, service, or asset in a transaction", Example: "92.26", Output: "float64", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Default: "0", Description: "Minimum price value"}, {Field: "max", Display: "Max", Type: "float", Default: "1000", Description: "Maximum price value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err @@ -302,10 +305,16 @@ func addPaymentLookup() { AddFuncLookup("creditcard", Info{ Display: "Credit Card", Category: "payment", - Description: "Random credit card data set", - Example: `{type: "Visa", number: "4136459948995369", exp: "01/21", cvv: "513"}`, - Output: "map[string]interface", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Description: "Plastic card allowing users to make purchases on credit, with payment due at a later date", + Example: `{ + "type": "UnionPay", + "number": "4364599489953698", + "exp": "02/24", + "cvv": "300" +}`, + Output: "map[string]any", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCard(r), nil }, }) @@ -313,10 +322,10 @@ func addPaymentLookup() { AddFuncLookup("creditcardtype", Info{ Display: "Credit Card Type", Category: "payment", - Description: "Random credit card type", + Description: "Classification of credit cards based on the issuing company", Example: "Visa", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCardType(r), nil }, }) @@ -324,9 +333,9 @@ func addPaymentLookup() { AddFuncLookup("creditcardnumber", Info{ Display: "Credit Card Number", Category: "payment", - Description: "Random credit card number", + Description: "Unique numerical identifier on a credit card used for making electronic payments and transactions", Example: "4136459948995369", - Output: "int", + Output: "string", Params: []Param{ { Field: "types", Display: "Types", Type: "[]string", Default: "all", @@ -336,7 +345,7 @@ func addPaymentLookup() { {Field: "bins", Display: "Bins", Type: "[]string", Optional: true, Description: "Optional list of prepended bin numbers to pick from"}, {Field: "gaps", Display: "Gaps", Type: "bool", Default: "false", Description: "Whether or not to have gaps in number"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { types, err := info.GetStringArray(m, "types") if err != nil { return nil, err @@ -368,10 +377,10 @@ func addPaymentLookup() { AddFuncLookup("creditcardexp", Info{ Display: "Credit Card Exp", Category: "payment", - Description: "Random credit card expiraction date", + Description: "Date when a credit card becomes invalid and cannot be used for transactions", Example: "01/21", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCardExp(r), nil }, }) @@ -379,10 +388,10 @@ func addPaymentLookup() { AddFuncLookup("creditcardcvv", Info{ Display: "Credit Card CVV", Category: "payment", - Description: "Random credit card number", + Description: "Three or four-digit security code on a credit card used for online and remote transactions", Example: "513", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCardCvv(r), nil }, }) @@ -390,10 +399,10 @@ func addPaymentLookup() { AddFuncLookup("achrouting", Info{ Display: "ACH Routing Number", Category: "payment", - Description: "Random 9 digit ach routing number", + Description: "Unique nine-digit code used in the U.S. for identifying the bank and processing electronic transactions", Example: "513715684", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return achRouting(r), nil }, }) @@ -401,10 +410,10 @@ func addPaymentLookup() { AddFuncLookup("achaccount", Info{ Display: "ACH Account Number", Category: "payment", - Description: "Random 12 digit ach account number", + Description: "A bank account number used for Automated Clearing House transactions and electronic transfers", Example: "491527954328", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return achAccount(r), nil }, }) @@ -412,10 +421,10 @@ func addPaymentLookup() { AddFuncLookup("bitcoinaddress", Info{ Display: "Bitcoin Address", Category: "payment", - Description: "Random 26-35 characters representing a bitcoin address", + Description: "Cryptographic identifier used to receive, store, and send Bitcoin cryptocurrency in a peer-to-peer network", Example: "1lWLbxojXq6BqWX7X60VkcDIvYA", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return bitcoinAddress(r), nil }, }) @@ -423,10 +432,10 @@ func addPaymentLookup() { AddFuncLookup("bitcoinprivatekey", Info{ Display: "Bitcoin Private Key", Category: "payment", - Description: "Random 51 characters representing a bitcoin private key", + Description: "Secret, secure code that allows the owner to access and control their Bitcoin holdings", Example: "5vrbXTADWJ6sQBSYd6lLkG97jljNc0X9VPBvbVqsIH9lWOLcoqg", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return bitcoinPrivateKey(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/person.go b/vendor/github.com/brianvoe/gofakeit/v6/person.go index 569a9f873..c1fe99f33 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/person.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/person.go @@ -60,6 +60,14 @@ func (f *Faker) FirstName() string { return firstName(f.Rand) } func firstName(r *rand.Rand) string { return getRandValue(r, []string{"person", "first"}) } +// MiddleName will generate a random middle name +func MiddleName() string { return middleName(globalFaker.Rand) } + +// MiddleName will generate a random middle name +func (f *Faker) MiddleName() string { return middleName(f.Rand) } + +func middleName(r *rand.Rand) string { return getRandValue(r, []string{"person", "middle"}) } + // LastName will generate a random last name func LastName() string { return lastName(globalFaker.Rand) } @@ -201,44 +209,44 @@ func addPersonLookup() { AddFuncLookup("person", Info{ Display: "Person", Category: "person", - Description: "Random set of person info", + Description: "Personal data, like name and contact details, used for identification and communication", Example: `{ - first_name: "Markus", - last_name: "Moen", - gender: "male", - ssn: "420776036", - image: "https://picsum.photos/300/300/people", - hobby: "Swimming", - job: { - company: "Lockman and Sons", - title: "Developer", - descriptor: "Global", - level: "Brand" - }, - address: { - address: "5369 Streamville, Rossieview, Hawaii 42591", - street: "5369 Streamville", - city: "Rossieview", - state: "Hawaii", - zip: "42591", - country: "Burkina Faso", - latitude: "-6.662594491850811", - longitude: "23.921575244414612" - }, - contact: { - phone: "6136459948", - email: "carolecarroll@bosco.com" - }, - credit_card: { - type: "Visa", - number: "6536459948995369", - exp: "03/27", - cvv: "353" - } - }`, - Output: "map[string]interface", + "first_name": "Markus", + "last_name": "Moen", + "gender": "male", + "ssn": "275413589", + "image": "https://picsum.photos/208/500", + "hobby": "Lacrosse", + "job": { + "company": "Intermap Technologies", + "title": "Developer", + "descriptor": "Direct", + "level": "Paradigm" + }, + "address": { + "address": "369 North Cornerbury, Miami, North Dakota 24259", + "street": "369 North Cornerbury", + "city": "Miami", + "state": "North Dakota", + "zip": "24259", + "country": "Ghana", + "latitude": -6.662595, + "longitude": 23.921575 + }, + "contact": { + "phone": "3023202027", + "email": "lamarkoelpin@heaney.biz" + }, + "credit_card": { + "type": "Maestro", + "number": "39800889982276", + "exp": "01/29", + "cvv": "932" + } +}`, + Output: "map[string]any", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return person(r), nil }, }) @@ -246,10 +254,10 @@ func addPersonLookup() { AddFuncLookup("name", Info{ Display: "Name", Category: "person", - Description: "Random name", + Description: "The given and family name of an individual", Example: "Markus Moen", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return name(r), nil }, }) @@ -257,10 +265,10 @@ func addPersonLookup() { AddFuncLookup("nameprefix", Info{ Display: "Name Prefix", Category: "person", - Description: "Random name prefix", + Description: "A title or honorific added before a person's name", Example: "Mr.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return namePrefix(r), nil }, }) @@ -268,10 +276,10 @@ func addPersonLookup() { AddFuncLookup("namesuffix", Info{ Display: "Name Suffix", Category: "person", - Description: "Random name suffix", + Description: "A title or designation added after a person's name", Example: "Jr.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nameSuffix(r), nil }, }) @@ -279,21 +287,32 @@ func addPersonLookup() { AddFuncLookup("firstname", Info{ Display: "First Name", Category: "person", - Description: "Random first name", + Description: "The name given to a person at birth", Example: "Markus", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return firstName(r), nil }, }) + AddFuncLookup("middlename", Info{ + Display: "Middle Name", + Category: "person", + Description: "Name between a person's first name and last name", + Example: "Belinda", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return middleName(r), nil + }, + }) + AddFuncLookup("lastname", Info{ Display: "Last Name", Category: "person", - Description: "Random last name", + Description: "The family name or surname of an individual", Example: "Daniel", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return lastName(r), nil }, }) @@ -301,10 +320,10 @@ func addPersonLookup() { AddFuncLookup("gender", Info{ Display: "Gender", Category: "person", - Description: "Random gender", + Description: "Classification based on social and cultural norms that identifies an individual", Example: "male", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return gender(r), nil }, }) @@ -312,10 +331,10 @@ func addPersonLookup() { AddFuncLookup("ssn", Info{ Display: "SSN", Category: "person", - Description: "Random social security number", + Description: "Unique nine-digit identifier used for government and financial purposes in the United States", Example: "296446360", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return ssn(r), nil }, }) @@ -323,10 +342,10 @@ func addPersonLookup() { AddFuncLookup("hobby", Info{ Display: "Hobby", Category: "person", - Description: "Random hobby activity", + Description: "An activity pursued for leisure and pleasure", Example: "Swimming", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hobby(r), nil }, }) @@ -334,10 +353,10 @@ func addPersonLookup() { AddFuncLookup("email", Info{ Display: "Email", Category: "person", - Description: "Random email", + Description: "Electronic mail used for sending digital messages and communication over the internet", Example: "markusmoen@pagac.net", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return email(r), nil }, }) @@ -345,10 +364,10 @@ func addPersonLookup() { AddFuncLookup("phone", Info{ Display: "Phone", Category: "person", - Description: "Random phone number", + Description: "Numerical sequence used to contact individuals via telephone or mobile devices", Example: "6136459948", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phone(r), nil }, }) @@ -356,10 +375,10 @@ func addPersonLookup() { AddFuncLookup("phoneformatted", Info{ Display: "Phone Formatted", Category: "person", - Description: "Random formatted phone number", + Description: "Formatted phone number of a person", Example: "136-459-9489", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phoneFormatted(r), nil }, }) @@ -368,13 +387,29 @@ func addPersonLookup() { Display: "Teams", Category: "person", Description: "Randomly split people into teams", - Example: `{"Team 1": ["Sharon","Jeff"], "Team 2": ["Billy","Connor"]}`, + Example: `{ + "Team 1": [ + "Justin", + "Connor", + "Jeff" + ], + "Team 2": [ + "Sharon", + "Fabian", + "Billy" + ], + "Team 3": [ + "Steve", + "Robert" + ] +}`, Output: "map[string][]string", + ContentType: "application/json", Params: []Param{ {Field: "people", Display: "Strings", Type: "[]string", Description: "Array of people"}, {Field: "teams", Display: "Strings", Type: "[]string", Description: "Array of teams"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { people, err := info.GetStringArray(m, "people") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/slice.go b/vendor/github.com/brianvoe/gofakeit/v6/slice.go index 5f93fa5b3..eec5e43d9 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/slice.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/slice.go @@ -1,16 +1,15 @@ package gofakeit import ( - "math/rand" "reflect" ) // Slice fills built-in types and exported fields of a struct with random data. -func Slice(v interface{}) { sliceFunc(globalFaker.Rand, v) } +func Slice(v any) { sliceFunc(globalFaker, v) } // Slice fills built-in types and exported fields of a struct with random data. -func (f *Faker) Slice(v interface{}) { sliceFunc(f.Rand, v) } +func (f *Faker) Slice(v any) { sliceFunc(f, v) } -func sliceFunc(ra *rand.Rand, v interface{}) { - r(ra, reflect.TypeOf(v), reflect.ValueOf(v), "", -1) +func sliceFunc(f *Faker, v any) { + r(f, reflect.TypeOf(v), reflect.ValueOf(v), "", -1) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/sql.go b/vendor/github.com/brianvoe/gofakeit/v6/sql.go index 9434d8350..b9918b23a 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/sql.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/sql.go @@ -90,7 +90,7 @@ func sqlFunc(r *rand.Rand, so *SQLOptions) (string, error) { } // sqlConvertType will take in a type and value and convert it to the proper SQL type -func sqlConvertType(t string, val interface{}) string { +func sqlConvertType(t string, val any) string { switch t { case "string": return `'` + fmt.Sprintf("%v", val) + `'` @@ -105,12 +105,12 @@ func addDatabaseSQLLookup() { AddFuncLookup("sql", Info{ Display: "SQL", Category: "database", - Description: "Generates an object or an array of objects in json format", + Description: "Command in SQL used to add new data records into a database table", Example: `INSERT INTO people - (id, first_name, price, age, created_at) - VALUES - (1, 'Markus', 804.92, 21, '1937-01-30 07:58:01'), - (2, 'Santino', 235.13, 40, '1964-07-07 22:25:40');`, + (id, first_name, price, age, created_at) +VALUES + (1, 'Markus', 804.92, 21, '1937-01-30 07:58:01'), + (2, 'Santino', 235.13, 40, '1964-07-07 22:25:40');`, Output: "string", ContentType: "application/sql", Params: []Param{ @@ -118,7 +118,7 @@ func addDatabaseSQLLookup() { {Field: "count", Display: "Count", Type: "int", Default: "100", Description: "Number of inserts to generate"}, {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { so := SQLOptions{} table, err := info.GetString(m, "table") diff --git a/vendor/github.com/brianvoe/gofakeit/v6/string.go b/vendor/github.com/brianvoe/gofakeit/v6/string.go index 42461c021..778772bc0 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/string.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/string.go @@ -10,10 +10,10 @@ func (f *Faker) Letter() string { return letter(f.Rand) } func letter(r *rand.Rand) string { return string(randLetter(r)) } -// LetterN will generate a random ASCII string with length N +// LetterN will generate a random ASCII string with length N. Note that this function returns a string with a length of 1 when 0 is passed. func LetterN(n uint) string { return letterN(globalFaker.Rand, n) } -// LetterN will generate a random ASCII string with length N +// LetterN will generate a random ASCII string with length N. Note that this function returns a string with a length of 1 when 0 is passed. func (f *Faker) LetterN(n uint) string { return letterN(f.Rand, n) } func letterN(r *rand.Rand, n uint) string { @@ -44,10 +44,10 @@ func (f *Faker) Digit() string { return digit(f.Rand) } func digit(r *rand.Rand) string { return string(randDigit(r)) } -// DigitN will generate a random string of length N consists of ASCII digits (note it can start with 0). +// DigitN will generate a random string of length N consists of ASCII digits. Note that the string generated can start with 0 and this function returns a string with a length of 1 when 0 is passed. func DigitN(n uint) string { return digitN(globalFaker.Rand, n) } -// DigitN will generate a random string of length N consists of ASCII digits (note it can start with 0). +// DigitN will generate a random string of length N consists of ASCII digits. Note that the string generated can start with 0 and this function returns a string with a length of 1 when 0 is passed. func (f *Faker) DigitN(n uint) string { return digitN(f.Rand, n) } func digitN(r *rand.Rand, n uint) string { @@ -123,10 +123,10 @@ func addStringLookup() { AddFuncLookup("letter", Info{ Display: "Letter", Category: "string", - Description: "Generate a single random lower case ASCII letter", + Description: "Character or symbol from the American Standard Code for Information Interchange (ASCII) character set", Example: "g", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return letter(r), nil }, }) @@ -134,13 +134,13 @@ func addStringLookup() { AddFuncLookup("lettern", Info{ Display: "LetterN", Category: "string", - Description: "Generate a random ASCII string with length N", + Description: "ASCII string with length N", Example: "gbRMaRxHki", Output: "string", Params: []Param{ {Field: "count", Display: "Count", Type: "uint", Description: "Number of digits to generate"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ui, err := info.GetUint(m, "count") if err != nil { return nil, err @@ -153,10 +153,10 @@ func addStringLookup() { AddFuncLookup("vowel", Info{ Display: "Vowel", Category: "string", - Description: "Generate a single random lower case vowel", + Description: "Speech sound produced with an open vocal tract", Example: "a", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return vowel(r), nil }, }) @@ -164,10 +164,10 @@ func addStringLookup() { AddFuncLookup("digit", Info{ Display: "Digit", Category: "string", - Description: "Generate a single ASCII digit", + Description: "Numerical symbol used to represent numbers", Example: "0", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return digit(r), nil }, }) @@ -175,13 +175,13 @@ func addStringLookup() { AddFuncLookup("digitn", Info{ Display: "DigitN", Category: "string", - Description: "Generate a random string of length N consists of ASCII digits", + Description: "string of length N consisting of ASCII digits", Example: "0136459948", Output: "string", Params: []Param{ {Field: "count", Display: "Count", Type: "uint", Description: "Number of digits to generate"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ui, err := info.GetUint(m, "count") if err != nil { return nil, err @@ -200,7 +200,7 @@ func addStringLookup() { Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "String value to replace #'s"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -219,7 +219,7 @@ func addStringLookup() { Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "String value to replace ?'s"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -239,7 +239,7 @@ func addStringLookup() { Params: []Param{ {Field: "strs", Display: "Strings", Type: "[]string", Description: "Delimited separated strings"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { strs, err := info.GetStringArray(m, "strs") if err != nil { return nil, err @@ -254,13 +254,13 @@ func addStringLookup() { AddFuncLookup("randomstring", Info{ Display: "Random String", Category: "string", - Description: "Randomly grab one string from array", + Description: "Return a random string from a string array", Example: "hello,world,whats,up => world", Output: "[]string", Params: []Param{ {Field: "strs", Display: "Strings", Type: "[]string", Description: "Delimited separated strings"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { strs, err := info.GetStringArray(m, "strs") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/struct.go b/vendor/github.com/brianvoe/gofakeit/v6/struct.go index b192dc8b2..c587ca17d 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/struct.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/struct.go @@ -2,7 +2,7 @@ package gofakeit import ( "errors" - "math/rand" + "fmt" "reflect" "strconv" "strings" @@ -10,100 +10,134 @@ import ( ) // Struct fills in exported fields of a struct with random data -// based on the value of `fake` tag of exported fields. +// based on the value of `fake` tag of exported fields +// or with the result of a call to the Fake() method +// if the field type implements `Fakeable`. // Use `fake:"skip"` to explicitly skip an element. // All built-in types are supported, with templating support // for string types. -func Struct(v interface{}) error { return structFunc(globalFaker.Rand, v) } +func Struct(v any) error { return structFunc(globalFaker, v) } // Struct fills in exported fields of a struct with random data // based on the value of `fake` tag of exported fields. // Use `fake:"skip"` to explicitly skip an element. // All built-in types are supported, with templating support // for string types. -func (f *Faker) Struct(v interface{}) error { return structFunc(f.Rand, v) } +func (f *Faker) Struct(v any) error { return structFunc(f, v) } -func structFunc(ra *rand.Rand, v interface{}) error { - return r(ra, reflect.TypeOf(v), reflect.ValueOf(v), "", 0) +func structFunc(f *Faker, v any) error { + return r(f, reflect.TypeOf(v), reflect.ValueOf(v), "", 0) } -func r(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func r(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { + // Handle special types + + if t.PkgPath() == "encoding/json" { + // encoding/json has two special types: + // - RawMessage + // - Number + + switch t.Name() { + case "RawMessage": + return rJsonRawMessage(f, t, v, tag, size) + case "Number": + return rJsonNumber(f, t, v, tag, size) + default: + return errors.New("unknown encoding/json type: " + t.Name()) + } + } + + // Handle generic types switch t.Kind() { case reflect.Ptr: - return rPointer(ra, t, v, tag, size) + return rPointer(f, t, v, tag, size) case reflect.Struct: - return rStruct(ra, t, v, tag) + return rStruct(f, t, v, tag) case reflect.String: - return rString(ra, v, tag) + return rString(f, t, v, tag) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return rUint(ra, t, v, tag) + return rUint(f, t, v, tag) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return rInt(ra, t, v, tag) + return rInt(f, t, v, tag) case reflect.Float32, reflect.Float64: - return rFloat(ra, t, v, tag) + return rFloat(f, t, v, tag) case reflect.Bool: - return rBool(ra, v, tag) + return rBool(f, t, v, tag) case reflect.Array, reflect.Slice: - return rSlice(ra, t, v, tag, size) + return rSlice(f, t, v, tag, size) case reflect.Map: - return rMap(ra, t, v, tag, size) + return rMap(f, t, v, tag, size) } return nil } -func rCustom(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rCustom(f *Faker, t reflect.Type, v reflect.Value, tag string) error { // If tag is empty return error if tag == "" { return errors.New("tag is empty") } fName, fParams := parseNameAndParamsFromTag(tag) - // Check to see if its a replaceable lookup function - if info := GetFuncLookup(fName); info != nil { - // Parse map params - mapParams := parseMapParams(info, fParams) + info := GetFuncLookup(fName) - // Call function - fValue, err := info.Generate(ra, mapParams, info) - if err != nil { - return err - } + // Check to see if it's a replaceable lookup function + if info == nil { + return fmt.Errorf("function %q not found", tag) + } - // Create new element of expected type - field := reflect.New(reflect.TypeOf(fValue)) - field.Elem().Set(reflect.ValueOf(fValue)) + // Parse map params + mapParams := parseMapParams(info, fParams) - // Check if element is pointer if so - // grab the underlyning value - fieldElem := field.Elem() - if fieldElem.Kind() == reflect.Ptr { - fieldElem = fieldElem.Elem() - } + // Call function + fValue, err := info.Generate(f.Rand, mapParams, info) + if err != nil { + return err + } - // Check if field kind is the same as the expected type - if fieldElem.Kind() != v.Kind() { - // return error saying the field and kinds that do not match - return errors.New("field kind " + fieldElem.Kind().String() + " does not match expected kind " + v.Kind().String()) - } + // Create new element of expected type + field := reflect.New(reflect.TypeOf(fValue)) + field.Elem().Set(reflect.ValueOf(fValue)) - // Set the value - v.Set(fieldElem) + // Check if element is pointer if so + // grab the underlying value + fieldElem := field.Elem() + if fieldElem.Kind() == reflect.Ptr { + fieldElem = fieldElem.Elem() + } - // If a function is called to set the struct - // stop from going through sub fields - return nil + // Check if field kind is the same as the expected type + if fieldElem.Kind() != v.Kind() { + // return error saying the field and kinds that do not match + return errors.New("field kind " + fieldElem.Kind().String() + " does not match expected kind " + v.Kind().String()) } - return errors.New("function not found") + // Set the value + v.Set(fieldElem.Convert(v.Type())) + + // If a function is called to set the struct + // stop from going through sub fields + return nil } -func rStruct(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rStruct(f *Faker, t reflect.Type, v reflect.Value, tag string) error { // Check if tag exists, if so run custom function if t.Name() != "" && tag != "" { - return rCustom(ra, t, v, tag) + return rCustom(f, t, v, tag) } + // Check if struct is fakeable + if isFakeable(t) { + value, err := callFake(f, v, reflect.Struct) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(value)) + return nil + } + + // Loop through all the fields of the struct n := t.NumField() for i := 0; i < n; i++ { elementT := t.Field(i) @@ -111,54 +145,93 @@ func rStruct(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { fakeTag, ok := elementT.Tag.Lookup("fake") // Check whether or not to skip this field - if ok && fakeTag == "skip" { + if ok && fakeTag == "skip" || fakeTag == "-" { // Do nothing, skip it continue } - // Check to make sure you can set it or that its an embeded(anonymous) field - if elementV.CanSet() || elementT.Anonymous { - // Check if reflect type is of values we can specifically set - switch elementT.Type.String() { - case "time.Time": - err := rTime(ra, elementT, elementV, fakeTag) - if err != nil { - return err - } - continue + // Check to make sure you can set it or that it's an embedded(anonymous) field + if !elementV.CanSet() && !elementT.Anonymous { + continue + } + + // Check if reflect type is of values we can specifically set + elemStr := elementT.Type.String() + switch elemStr { + case "time.Time", "*time.Time": + // Check if element is a pointer + elemV := elementV + if elemStr == "*time.Time" { + elemV = reflect.New(elementT.Type.Elem()).Elem() } - // Check if fakesize is set - size := -1 // Set to -1 to indicate fakesize was not set - fs, ok := elementT.Tag.Lookup("fakesize") - if ok { - var err error + // Run rTime on the element + err := rTime(f, elementT, elemV, fakeTag) + if err != nil { + return err + } + + if elemStr == "*time.Time" { + elementV.Set(elemV.Addr()) + } + + continue + } + + // Check if fakesize is set + size := -1 // Set to -1 to indicate fakesize was not set + fs, ok := elementT.Tag.Lookup("fakesize") + if ok { + var err error + + // Check if size has params separated by , + if strings.Contains(fs, ",") { + sizeSplit := strings.SplitN(fs, ",", 2) + if len(sizeSplit) == 2 { + var sizeMin int + var sizeMax int + + sizeMin, err = strconv.Atoi(sizeSplit[0]) + if err != nil { + return err + } + sizeMax, err = strconv.Atoi(sizeSplit[1]) + if err != nil { + return err + } + + size = f.Rand.Intn(sizeMax-sizeMin+1) + sizeMin + } + } else { size, err = strconv.Atoi(fs) if err != nil { return err } } - err := r(ra, elementT.Type, elementV, fakeTag, size) - if err != nil { - return err - } + } + + // Recursively call r() to fill in the struct + err := r(f, elementT.Type, elementV, fakeTag, size) + if err != nil { + return err } } return nil } -func rPointer(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func rPointer(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { elemT := t.Elem() if v.IsNil() { - nv := reflect.New(elemT) - err := r(ra, elemT, nv.Elem(), tag, size) + nv := reflect.New(elemT).Elem() + err := r(f, elemT, nv, tag, size) if err != nil { return err } - v.Set(nv) + + v.Set(nv.Addr()) } else { - err := r(ra, elemT, v.Elem(), tag, size) + err := r(f, elemT, v.Elem(), tag, size) if err != nil { return err } @@ -167,7 +240,7 @@ func rPointer(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size i return nil } -func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func rSlice(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { // If you cant even set it dont even try if !v.CanSet() { return errors.New("cannot set slice") @@ -176,10 +249,18 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int // Check if tag exists, if so run custom function if t.Name() != "" && tag != "" { // Check to see if custom function works if not continue to normal loop of values - err := rCustom(ra, t, v, tag) + err := rCustom(f, t, v, tag) if err == nil { return nil } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Slice) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(value)) + return nil } // Grab original size to use if needed for sub arrays @@ -189,7 +270,7 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int // use that instead of the requested size elemLen := v.Len() if elemLen == 0 && size == -1 { - size = number(ra, 1, 10) + size = number(f.Rand, 1, 10) } else if elemLen != 0 && (size == -1 || elemLen < size) { size = elemLen } @@ -200,7 +281,7 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int // Loop through the elements length and set based upon the index for i := 0; i < size; i++ { nv := reflect.New(elemT) - err := r(ra, elemT, nv.Elem(), tag, ogSize) + err := r(f, elemT, nv.Elem(), tag, ogSize) if err != nil { return err } @@ -216,21 +297,31 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int return nil } -func rMap(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func rMap(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { // If you cant even set it dont even try if !v.CanSet() { return errors.New("cannot set slice") } // Check if tag exists, if so run custom function - if t.Name() != "" && tag != "" { - return rCustom(ra, t, v, tag) + if tag != "" { + return rCustom(f, t, v, tag) + } else if size > 0 { + // NOOP + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Map) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(value)) + return nil } // Set a size newSize := size if newSize == -1 { - newSize = number(ra, 1, 10) + newSize = number(f.Rand, 1, 10) } // Create new map based upon map key value type @@ -240,14 +331,14 @@ func rMap(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) for i := 0; i < newSize; i++ { // Create new key mapIndex := reflect.New(t.Key()) - err := r(ra, t.Key(), mapIndex.Elem(), "", -1) + err := r(f, t.Key(), mapIndex.Elem(), "", -1) if err != nil { return err } // Create new value mapValue := reflect.New(t.Elem()) - err = r(ra, t.Elem(), mapValue.Elem(), "", -1) + err = r(f, t.Elem(), mapValue.Elem(), "", -1) if err != nil { return err } @@ -265,116 +356,196 @@ func rMap(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) return nil } -func rString(ra *rand.Rand, v reflect.Value, tag string) error { +func rString(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - v.SetString(generate(ra, tag)) + v.SetString(generate(f.Rand, tag)) + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.String) + if err != nil { + return err + } + + valueStr, ok := value.(string) + if !ok { + return errors.New("call to Fake method did not return a string") + } + v.SetString(valueStr) } else { - v.SetString(generate(ra, strings.Repeat("?", number(ra, 4, 10)))) + v.SetString(generate(f.Rand, strings.Repeat("?", number(f.Rand, 4, 10)))) } return nil } -func rInt(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rInt(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - i, err := strconv.ParseInt(generate(ra, tag), 10, 64) + i, err := strconv.ParseInt(generate(f.Rand, tag), 10, 64) if err != nil { return err } v.SetInt(i) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64) + if err != nil { + return err + } - // If no tag or error converting to int, set with random value - switch t.Kind() { - case reflect.Int: - v.SetInt(int64Func(ra)) - case reflect.Int8: - v.SetInt(int64(int8Func(ra))) - case reflect.Int16: - v.SetInt(int64(int16Func(ra))) - case reflect.Int32: - v.SetInt(int64(int32Func(ra))) - case reflect.Int64: - v.SetInt(int64Func(ra)) + switch i := value.(type) { + case int: + v.SetInt(int64(i)) + case int8: + v.SetInt(int64(i)) + case int16: + v.SetInt(int64(i)) + case int32: + v.SetInt(int64(i)) + case int64: + v.SetInt(int64(i)) + default: + return errors.New("call to Fake method did not return an integer") + } + } else { + // If no tag or error converting to int, set with random value + switch t.Kind() { + case reflect.Int: + v.SetInt(int64Func(f.Rand)) + case reflect.Int8: + v.SetInt(int64(int8Func(f.Rand))) + case reflect.Int16: + v.SetInt(int64(int16Func(f.Rand))) + case reflect.Int32: + v.SetInt(int64(int32Func(f.Rand))) + case reflect.Int64: + v.SetInt(int64Func(f.Rand)) + } } return nil } -func rUint(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rUint(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - u, err := strconv.ParseUint(generate(ra, tag), 10, 64) + u, err := strconv.ParseUint(generate(f.Rand, tag), 10, 64) if err != nil { return err } v.SetUint(u) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64) + if err != nil { + return err + } - // If no tag or error converting to uint, set with random value - switch t.Kind() { - case reflect.Uint: - v.SetUint(uint64Func(ra)) - case reflect.Uint8: - v.SetUint(uint64(uint8Func(ra))) - case reflect.Uint16: - v.SetUint(uint64(uint16Func(ra))) - case reflect.Uint32: - v.SetUint(uint64(uint32Func(ra))) - case reflect.Uint64: - v.SetUint(uint64Func(ra)) + switch i := value.(type) { + case uint: + v.SetUint(uint64(i)) + case uint8: + v.SetUint(uint64(i)) + case uint16: + v.SetUint(uint64(i)) + case uint32: + v.SetUint(uint64(i)) + case uint64: + v.SetUint(uint64(i)) + default: + return errors.New("call to Fake method did not return an unsigned integer") + } + } else { + // If no tag or error converting to uint, set with random value + switch t.Kind() { + case reflect.Uint: + v.SetUint(uint64Func(f.Rand)) + case reflect.Uint8: + v.SetUint(uint64(uint8Func(f.Rand))) + case reflect.Uint16: + v.SetUint(uint64(uint16Func(f.Rand))) + case reflect.Uint32: + v.SetUint(uint64(uint32Func(f.Rand))) + case reflect.Uint64: + v.SetUint(uint64Func(f.Rand)) + } } return nil } -func rFloat(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rFloat(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - f, err := strconv.ParseFloat(generate(ra, tag), 64) + f, err := strconv.ParseFloat(generate(f.Rand, tag), 64) if err != nil { return err } v.SetFloat(f) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Float32, reflect.Float64) + if err != nil { + return err + } - // If no tag or error converting to float, set with random value - switch t.Kind() { - case reflect.Float64: - v.SetFloat(float64Func(ra)) - case reflect.Float32: - v.SetFloat(float64(float32Func(ra))) + switch i := value.(type) { + case float32: + v.SetFloat(float64(i)) + case float64: + v.SetFloat(float64(i)) + default: + return errors.New("call to Fake method did not return a float") + } + } else { + // If no tag or error converting to float, set with random value + switch t.Kind() { + case reflect.Float64: + v.SetFloat(float64Func(f.Rand)) + case reflect.Float32: + v.SetFloat(float64(float32Func(f.Rand))) + } } return nil } -func rBool(ra *rand.Rand, v reflect.Value, tag string) error { +func rBool(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - b, err := strconv.ParseBool(generate(ra, tag)) + b, err := strconv.ParseBool(generate(f.Rand, tag)) if err != nil { return err } v.SetBool(b) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Bool) + if err != nil { + return err + } - // If no tag or error converting to boolean, set with random value - v.SetBool(boolFunc(ra)) + switch i := value.(type) { + case bool: + v.SetBool(bool(i)) + default: + return errors.New("call to Fake method did not return a boolean") + } + } else { + // If no tag or error converting to boolean, set with random value + v.SetBool(boolFunc(f.Rand)) + } return nil } // rTime will set a time.Time field the best it can from either the default date tag or from the generate tag -func rTime(ra *rand.Rand, t reflect.StructField, v reflect.Value, tag string) error { +func rTime(f *Faker, t reflect.StructField, v reflect.Value, tag string) error { if tag != "" { // Generate time - timeOutput := generate(ra, tag) + timeOutput := generate(f.Rand, tag) + + // Check to see if timeOutput has monotonic clock reading + // if so, remove it. This is because time.Parse() does not + // support parsing the monotonic clock reading + if strings.Contains(timeOutput, " m=") { + timeOutput = strings.Split(timeOutput, " m=")[0] + } // Check to see if they are passing in a format to parse the time timeFormat, timeFormatOK := t.Tag.Lookup("format") @@ -407,6 +578,6 @@ func rTime(ra *rand.Rand, t reflect.StructField, v reflect.Value, tag string) er return nil } - v.Set(reflect.ValueOf(date(ra))) + v.Set(reflect.ValueOf(date(f.Rand))) return nil } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/time.go b/vendor/github.com/brianvoe/gofakeit/v6/time.go index ca8d2514e..ecd0c1cac 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/time.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/time.go @@ -14,7 +14,27 @@ func Date() time.Time { return date(globalFaker.Rand) } func (f *Faker) Date() time.Time { return date(f.Rand) } func date(r *rand.Rand) time.Time { - return time.Date(year(r), time.Month(number(r, 1, 12)), day(r), hour(r), minute(r), second(r), nanoSecond(r), time.UTC) + return time.Date(year(r), time.Month(month(r)), day(r), hour(r), minute(r), second(r), nanoSecond(r), time.UTC) +} + +// FutureDate will generate a random past time.Time struct +func PastDate() time.Time { return pastDate(globalFaker.Rand) } + +// FutureDate will generate a random past time.Time struct +func (f *Faker) PastDate() time.Time { return pastDate(f.Rand) } + +func pastDate(r *rand.Rand) time.Time { + return time.Now().Add(time.Hour * -time.Duration(number(r, 1, 12))) +} + +// FutureDate will generate a random future time.Time struct +func FutureDate() time.Time { return futureDate(globalFaker.Rand) } + +// FutureDate will generate a random future time.Time struct +func (f *Faker) FutureDate() time.Time { return futureDate(f.Rand) } + +func futureDate(r *rand.Rand) time.Time { + return time.Now().Add(time.Hour * time.Duration(number(r, 1, 12))) } // DateRange will generate a random time.Time struct between a start and end date @@ -193,7 +213,7 @@ func addDateTimeLookup() { AddFuncLookup("date", Info{ Display: "Date", Category: "time", - Description: "Random date", + Description: "Representation of a specific day, month, and year, often used for chronological reference", Example: "2006-01-02T15:04:05Z07:00", Output: "string", Params: []Param{ @@ -206,7 +226,7 @@ func addDateTimeLookup() { Description: "Date time string format output. You may also use golang time format or java time format", }, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { format, err := info.GetString(m, "format") if err != nil { return nil, err @@ -272,7 +292,7 @@ func addDateTimeLookup() { Description: "Date time string format", }, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { format, err := info.GetString(m, "format") if err != nil { return nil, err @@ -301,13 +321,35 @@ func addDateTimeLookup() { }, }) + AddFuncLookup("pasttime", Info{ + Display: "PastTime", + Category: "time", + Description: "Date that has occurred before the current moment in time", + Example: "2007-01-24 13:00:35.820738079 +0000 UTC", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return pastDate(r), nil + }, + }) + + AddFuncLookup("futuretime", Info{ + Display: "FutureTime", + Category: "time", + Description: "Date that has occurred after the current moment in time", + Example: "2107-01-24 13:00:35.820738079 +0000 UTC", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return futureDate(r), nil + }, + }) + AddFuncLookup("nanosecond", Info{ Display: "Nanosecond", Category: "time", - Description: "Random nanosecond", + Description: "Unit of time equal to One billionth (10^-9) of a second", Example: "196446360", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nanoSecond(r), nil }, }) @@ -315,10 +357,10 @@ func addDateTimeLookup() { AddFuncLookup("second", Info{ Display: "Second", Category: "time", - Description: "Random second", + Description: "Unit of time equal to 1/60th of a minute", Example: "43", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return second(r), nil }, }) @@ -326,10 +368,10 @@ func addDateTimeLookup() { AddFuncLookup("minute", Info{ Display: "Minute", Category: "time", - Description: "Random minute", + Description: "Unit of time equal to 60 seconds", Example: "34", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minute(r), nil }, }) @@ -337,10 +379,10 @@ func addDateTimeLookup() { AddFuncLookup("hour", Info{ Display: "Hour", Category: "time", - Description: "Random hour", + Description: "Unit of time equal to 60 minutes", Example: "8", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hour(r), nil }, }) @@ -348,10 +390,10 @@ func addDateTimeLookup() { AddFuncLookup("day", Info{ Display: "Day", Category: "time", - Description: "Random day", + Description: "24-hour period equivalent to one rotation of Earth on its axis", Example: "12", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return day(r), nil }, }) @@ -359,10 +401,10 @@ func addDateTimeLookup() { AddFuncLookup("weekday", Info{ Display: "Weekday", Category: "time", - Description: "Random week day", + Description: "Day of the week excluding the weekend", Example: "Friday", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return weekDay(r), nil }, }) @@ -370,10 +412,10 @@ func addDateTimeLookup() { AddFuncLookup("month", Info{ Display: "Month", Category: "time", - Description: "Random month", + Description: "Division of the year, typically 30 or 31 days long", Example: "1", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return month(r), nil }, }) @@ -381,10 +423,10 @@ func addDateTimeLookup() { AddFuncLookup("monthstring", Info{ Display: "Month String", Category: "time", - Description: "Random month in string output", + Description: "String Representation of a month name", Example: "September", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return monthString(r), nil }, }) @@ -392,10 +434,10 @@ func addDateTimeLookup() { AddFuncLookup("year", Info{ Display: "Year", Category: "time", - Description: "Random year", + Description: "Period of 365 days, the time Earth takes to orbit the Sun", Example: "1900", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return year(r), nil }, }) @@ -403,10 +445,10 @@ func addDateTimeLookup() { AddFuncLookup("timezone", Info{ Display: "Timezone", Category: "time", - Description: "Random timezone", + Description: "Region where the same standard time is used, based on longitudinal divisions of the Earth", Example: "Kaliningrad Standard Time", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZone(r), nil }, }) @@ -414,10 +456,10 @@ func addDateTimeLookup() { AddFuncLookup("timezoneabv", Info{ Display: "Timezone Abbreviation", Category: "time", - Description: "Random abbreviated timezone", + Description: "Abbreviated 3-letter word of a timezone", Example: "KST", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneAbv(r), nil }, }) @@ -425,10 +467,10 @@ func addDateTimeLookup() { AddFuncLookup("timezonefull", Info{ Display: "Timezone Full", Category: "time", - Description: "Random full timezone", + Description: "Full name of a timezone", Example: "(UTC+03:00) Kaliningrad, Minsk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneFull(r), nil }, }) @@ -436,10 +478,10 @@ func addDateTimeLookup() { AddFuncLookup("timezoneoffset", Info{ Display: "Timezone Offset", Category: "time", - Description: "Random timezone offset", + Description: "The difference in hours from Coordinated Universal Time (UTC) for a specific region", Example: "3", Output: "float32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneOffset(r), nil }, }) @@ -447,10 +489,10 @@ func addDateTimeLookup() { AddFuncLookup("timezoneregion", Info{ Display: "Timezone Region", Category: "time", - Description: "Random region timezone", + Description: "Geographic area sharing the same standard time", Example: "America/Alaska", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneRegion(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/weighted.go b/vendor/github.com/brianvoe/gofakeit/v6/weighted.go index 22ead1162..c04fa6bd3 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/weighted.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/weighted.go @@ -6,17 +6,17 @@ import ( ) // Weighted will take in an array of options and weights and return a random selection based upon its indexed weight -func Weighted(options []interface{}, weights []float32) (interface{}, error) { +func Weighted(options []any, weights []float32) (any, error) { return weighted(globalFaker.Rand, options, weights) } // Weighted will take in an array of options and weights and return a random selection based upon its indexed weight -func (f *Faker) Weighted(options []interface{}, weights []float32) (interface{}, error) { +func (f *Faker) Weighted(options []any, weights []float32) (any, error) { return weighted(f.Rand, options, weights) } // Weighted will take in an array of options and weights and return a random selection based upon its indexed weight -func weighted(r *rand.Rand, options []interface{}, weights []float32) (interface{}, error) { +func weighted(r *rand.Rand, options []any, weights []float32) (any, error) { ol := len(options) wl := len(weights) @@ -85,7 +85,7 @@ func addWeightedLookup() { {Field: "options", Display: "Options", Type: "[]string", Description: "Array of any values"}, {Field: "weights", Display: "Weights", Type: "[]float", Description: "Array of weights"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { options, err := info.GetStringArray(m, "options") if err != nil { return nil, err @@ -96,7 +96,7 @@ func addWeightedLookup() { return nil, err } - optionsInterface := make([]interface{}, len(options)) + optionsInterface := make([]any, len(options)) for i, o := range options { optionsInterface[i] = o } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go b/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go index 834c2259c..c9fcbd8ec 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go @@ -95,10 +95,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjective", Info{ Display: "Adjective", Category: "word", - Description: "Random adjective", + Description: "Word describing or modifying a noun", Example: "genuine", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjective(r), nil }, }) @@ -106,10 +106,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivedescriptive", Info{ Display: "Descriptive Adjective", Category: "word", - Description: "Random descriptive adjective", + Description: "Adjective that provides detailed characteristics about a noun", Example: "brave", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveDescriptive(r), nil }, }) @@ -117,10 +117,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivequantitative", Info{ Display: "Quantitative Adjective", Category: "word", - Description: "Random quantitative adjective", + Description: "Adjective that indicates the quantity or amount of something", Example: "a little", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveQuantitative(r), nil }, }) @@ -128,10 +128,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectiveproper", Info{ Display: "Proper Adjective", Category: "word", - Description: "Random proper adjective", + Description: "Adjective derived from a proper noun, often used to describe nationality or origin", Example: "Afghan", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveProper(r), nil }, }) @@ -139,10 +139,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivedemonstrative", Info{ Display: "Demonstrative Adjective", Category: "word", - Description: "Random demonstrative adjective", + Description: "Adjective used to point out specific things", Example: "this", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveDemonstrative(r), nil }, }) @@ -150,10 +150,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivepossessive", Info{ Display: "Possessive Adjective", Category: "word", - Description: "Random possessive adjective", + Description: "Adjective indicating ownership or possession", Example: "my", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectivePossessive(r), nil }, }) @@ -161,10 +161,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectiveinterrogative", Info{ Display: "Interrogative Adjective", Category: "word", - Description: "Random interrogative adjective", + Description: "Adjective used to ask questions", Example: "what", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveInterrogative(r), nil }, }) @@ -172,10 +172,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectiveindefinite", Info{ Display: "Indefinite Adjective", Category: "word", - Description: "Random indefinite adjective", + Description: "Adjective describing a non-specific noun", Example: "few", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveIndefinite(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go b/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go index e2e196452..b148bf8d3 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go @@ -89,10 +89,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverb", Info{ Display: "Adverb", Category: "word", - Description: "Random adverb", + Description: "Word that modifies verbs, adjectives, or other adverbs", Example: "smoothly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverb(r), nil }, }) @@ -100,10 +100,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbmanner", Info{ Display: "Adverb Manner", Category: "word", - Description: "Random manner adverb", + Description: "Adverb that describes how an action is performed", Example: "stupidly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbManner(r), nil }, }) @@ -111,10 +111,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbdegree", Info{ Display: "Adverb Degree", Category: "word", - Description: "Random degree adverb", + Description: "Adverb that indicates the degree or intensity of an action or adjective", Example: "intensely", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbDegree(r), nil }, }) @@ -122,10 +122,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbplace", Info{ Display: "Adverb Place", Category: "word", - Description: "Random place adverb", + Description: "Adverb that indicates the location or direction of an action", Example: "east", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbPlace(r), nil }, }) @@ -133,10 +133,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbtimedefinite", Info{ Display: "Adverb Time Definite", Category: "word", - Description: "Random time definite adverb", + Description: "Adverb that specifies the exact time an action occurs", Example: "now", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbTimeDefinite(r), nil }, }) @@ -144,10 +144,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbtimeindefinite", Info{ Display: "Adverb Time Indefinite", Category: "word", - Description: "Random time indefinite adverb", + Description: "Adverb that gives a general or unspecified time frame", Example: "already", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbTimeIndefinite(r), nil }, }) @@ -155,10 +155,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbfrequencydefinite", Info{ Display: "Adverb Frequency Definite", Category: "word", - Description: "Random frequency definite adverb", + Description: "Adverb that specifies how often an action occurs with a clear frequency", Example: "hourly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbFrequencyDefinite(r), nil }, }) @@ -166,10 +166,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbfrequencyindefinite", Info{ Display: "Adverb Frequency Indefinite", Category: "word", - Description: "Random frequency indefinite adverb", + Description: "Adverb that specifies how often an action occurs without specifying a particular frequency", Example: "occasionally", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbFrequencyIndefinite(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go b/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go index ea4745f68..5be26166c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go @@ -31,14 +31,14 @@ func connectiveTime(r *rand.Rand) string { return getRandValue(r, []string{"word", "connective_time"}) } -// ConnectiveComparitive will generate a random comparative connective -func ConnectiveComparitive() string { return connectiveComparitive(globalFaker.Rand) } +// ConnectiveComparative will generate a random comparative connective +func ConnectiveComparative() string { return connectiveComparative(globalFaker.Rand) } -// ConnectiveComparitive will generate a random comparative connective -func (f *Faker) ConnectiveComparitive() string { return connectiveComparitive(f.Rand) } +// ConnectiveComparative will generate a random comparative connective +func (f *Faker) ConnectiveComparative() string { return connectiveComparative(f.Rand) } -func connectiveComparitive(r *rand.Rand) string { - return getRandValue(r, []string{"word", "connective_comparitive"}) +func connectiveComparative(r *rand.Rand) string { + return getRandValue(r, []string{"word", "connective_comparative"}) } // ConnectiveComplaint will generate a random complaint connective @@ -85,10 +85,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connective", Info{ Display: "Connective", Category: "word", - Description: "Random connective word", + Description: "Word used to connect words or sentences", Example: "such as", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connective(r), nil }, }) @@ -96,32 +96,32 @@ func addWordConnectiveLookup() { AddFuncLookup("connectivetime", Info{ Display: "Connective Time", Category: "word", - Description: "Random connective time word", + Description: "Connective word used to indicate a temporal relationship between events or actions", Example: "finally", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveTime(r), nil }, }) - AddFuncLookup("connectivecomparitive", Info{ + AddFuncLookup("connectivecomparative", Info{ Display: "Connective Comparitive", Category: "word", - Description: "Random connective comparative word", + Description: "Connective word used to indicate a comparison between two or more things", Example: "in addition", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { - return connectiveComparitive(r), nil + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return connectiveComparative(r), nil }, }) AddFuncLookup("connectivecomplaint", Info{ Display: "Connective Complaint", Category: "word", - Description: "Random connective complaint word", + Description: "Connective word used to express dissatisfaction or complaints about a situation", Example: "besides", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveComplaint(r), nil }, }) @@ -129,10 +129,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connectivelisting", Info{ Display: "Connective Listing", Category: "word", - Description: "Random connective listing word", + Description: "Connective word used to list or enumerate items or examples", Example: "firstly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveListing(r), nil }, }) @@ -140,10 +140,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connectivecasual", Info{ Display: "Connective Casual", Category: "word", - Description: "Random connective casual word", + Description: "Connective word used to indicate a cause-and-effect relationship between events or actions", Example: "an outcome of", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveCasual(r), nil }, }) @@ -151,10 +151,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connectiveexamplify", Info{ Display: "Connective Examplify", Category: "word", - Description: "Random connective examplify word", + Description: "Connective word used to provide examples or illustrations of a concept or idea", Example: "then", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveExamplify(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_general.go b/vendor/github.com/brianvoe/gofakeit/v6/word_general.go index cfa2a56b1..d2a84f920 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_general.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_general.go @@ -28,10 +28,10 @@ func addWordGeneralLookup() { AddFuncLookup("word", Info{ Display: "Word", Category: "word", - Description: "Random word", + Description: "Basic unit of language representing a concept or thing, consisting of letters and having meaning", Example: "man", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return word(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go b/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go index 4079f0231..77722d76c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go @@ -25,10 +25,10 @@ func addWordGrammerLookup() { AddFuncLookup("sentencesimple", Info{ Display: "Simple Sentence", Category: "word", - Description: "Random simple sentence", + Description: "Group of words that expresses a complete thought", Example: "A tribe fly the lemony kitchen.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return sentenceSimple(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go b/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go index 3dec9396d..fbf9e806e 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go @@ -111,14 +111,22 @@ func nounProper(r *rand.Rand) string { return getRandValue(r, []string{"person", "first"}) } +// NounDeterminer will generate a random noun determiner +func NounDeterminer() string { return nounDeterminer(globalFaker.Rand) } + +// NounDeterminer will generate a random noun determiner +func (f *Faker) NounDeterminer() string { return nounDeterminer(f.Rand) } + +func nounDeterminer(r *rand.Rand) string { return getRandValue(r, []string{"word", "noun_determiner"}) } + func addWordNounLookup() { AddFuncLookup("noun", Info{ Display: "Noun", Category: "word", - Description: "Random noun", + Description: "Person, place, thing, or idea, named or referred to in a sentence", Example: "aunt", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return noun(r), nil }, }) @@ -126,10 +134,10 @@ func addWordNounLookup() { AddFuncLookup("nouncommon", Info{ Display: "Noun Common", Category: "word", - Description: "Random common noun", + Description: "General name for people, places, or things, not specific or unique", Example: "part", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCommon(r), nil }, }) @@ -137,10 +145,10 @@ func addWordNounLookup() { AddFuncLookup("nounconcrete", Info{ Display: "Noun Concrete", Category: "word", - Description: "Random concrete noun", + Description: "Names for physical entities experienced through senses like sight, touch, smell, or taste", Example: "snowman", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounConcrete(r), nil }, }) @@ -148,10 +156,10 @@ func addWordNounLookup() { AddFuncLookup("nounabstract", Info{ Display: "Noun Abstract", Category: "word", - Description: "Random abstract noun", + Description: "Ideas, qualities, or states that cannot be perceived with the five senses", Example: "confusion", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounAbstract(r), nil }, }) @@ -159,10 +167,10 @@ func addWordNounLookup() { AddFuncLookup("nouncollectivepeople", Info{ Display: "Noun Collective People", Category: "word", - Description: "Random collective noun person", + Description: "Group of people or things regarded as a unit", Example: "body", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCollectivePeople(r), nil }, }) @@ -170,10 +178,10 @@ func addWordNounLookup() { AddFuncLookup("nouncollectiveanimal", Info{ Display: "Noun Collective Animal", Category: "word", - Description: "Random collective noun animal", + Description: "Group of animals, like a 'pack' of wolves or a 'flock' of birds", Example: "party", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCollectiveAnimal(r), nil }, }) @@ -181,10 +189,10 @@ func addWordNounLookup() { AddFuncLookup("nouncollectivething", Info{ Display: "Noun Collective Thing", Category: "word", - Description: "Random collective noun thing", + Description: "Group of objects or items, such as a 'bundle' of sticks or a 'cluster' of grapes", Example: "hand", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCollectiveThing(r), nil }, }) @@ -192,10 +200,10 @@ func addWordNounLookup() { AddFuncLookup("nouncountable", Info{ Display: "Noun Countable", Category: "word", - Description: "Random countable noun", + Description: "Items that can be counted individually", Example: "neck", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCountable(r), nil }, }) @@ -203,10 +211,10 @@ func addWordNounLookup() { AddFuncLookup("noununcountable", Info{ Display: "Noun Uncountable", Category: "word", - Description: "Random uncountable noun", + Description: "Items that can't be counted individually", Example: "seafood", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounUncountable(r), nil }, }) @@ -214,11 +222,22 @@ func addWordNounLookup() { AddFuncLookup("nounproper", Info{ Display: "Noun Proper", Category: "word", - Description: "Random proper noun", + Description: "Specific name for a particular person, place, or organization", Example: "John", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounProper(r), nil }, }) + + AddFuncLookup("noundeterminer", Info{ + Display: "Noun Determiner", + Category: "word", + Description: "Word that introduces a noun and identifies it as a noun", + Example: "your", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return nounDeterminer(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go b/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go index 34c816dd6..1432f1730 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go @@ -30,7 +30,7 @@ func phraseNoun(r *rand.Rand) string { } // Add determiner from weighted list - prob, _ := weighted(r, []interface{}{1, 2, 3}, []float32{2, 1.5, 1}) + prob, _ := weighted(r, []any{1, 2, 3}, []float32{2, 1.5, 1}) if prob == 1 { str = getArticle(str) + " " + str } else if prob == 2 { @@ -109,10 +109,10 @@ func addWordPhraseLookup() { AddFuncLookup("phrase", Info{ Display: "Phrase", Category: "word", - Description: "Random phrase", + Description: "A small group of words standing together", Example: "time will tell", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phrase(r), nil }, }) @@ -120,10 +120,10 @@ func addWordPhraseLookup() { AddFuncLookup("phrasenoun", Info{ Display: "Noun Phrase", Category: "word", - Description: "Random noun phrase", + Description: "Phrase with a noun as its head, functions within sentence like a noun", Example: "a tribe", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phraseNoun(r), nil }, }) @@ -131,10 +131,10 @@ func addWordPhraseLookup() { AddFuncLookup("phraseverb", Info{ Display: "Verb Phrase", Category: "word", - Description: "Random verb phrase", + Description: "Phrase that Consists of a verb and its modifiers, expressing an action or state", Example: "a tribe", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phraseVerb(r), nil }, }) @@ -142,10 +142,10 @@ func addWordPhraseLookup() { AddFuncLookup("phraseadverb", Info{ Display: "Adverb Phrase", Category: "word", - Description: "Random adverb phrase", + Description: "Phrase that modifies a verb, adjective, or another adverb, providing additional information.", Example: "fully gladly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phraseAdverb(r), nil }, }) @@ -153,10 +153,10 @@ func addWordPhraseLookup() { AddFuncLookup("phrasepreposition", Info{ Display: "Preposition Phrase", Category: "word", - Description: "Random preposition phrase", + Description: "Phrase starting with a preposition, showing relation between elements in a sentence.", Example: "out the black thing", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phrasePreposition(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go b/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go index 7bebf004c..bf1d2f74a 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go @@ -51,10 +51,10 @@ func addWordPrepositionLookup() { AddFuncLookup("preposition", Info{ Display: "Preposition", Category: "word", - Description: "Random preposition", + Description: "Words used to express the relationship of a noun or pronoun to other words in a sentence", Example: "other than", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return preposition(r), nil }, }) @@ -62,10 +62,10 @@ func addWordPrepositionLookup() { AddFuncLookup("prepositionsimple", Info{ Display: "Preposition Simple", Category: "word", - Description: "Random simple preposition", + Description: "Single-word preposition showing relationships between 2 parts of a sentence", Example: "out", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return prepositionSimple(r), nil }, }) @@ -73,10 +73,10 @@ func addWordPrepositionLookup() { AddFuncLookup("prepositiondouble", Info{ Display: "Preposition Double", Category: "word", - Description: "Random double preposition", + Description: "Two-word combination preposition, indicating a complex relation", Example: "before", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return prepositionDouble(r), nil }, }) @@ -84,10 +84,10 @@ func addWordPrepositionLookup() { AddFuncLookup("prepositioncompound", Info{ Display: "Preposition Compound", Category: "word", - Description: "Random compound preposition", + Description: "Preposition that can be formed by combining two or more prepositions", Example: "according to", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return prepositionCompound(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go b/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go index ca346b9ef..00c533104 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go @@ -106,10 +106,10 @@ func addWordPronounLookup() { AddFuncLookup("pronoun", Info{ Display: "Pronoun", Category: "word", - Description: "Generates a random pronoun", + Description: "Word used in place of a noun to avoid repetition", Example: "me", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronoun(r), nil }, }) @@ -117,10 +117,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounpersonal", Info{ Display: "Pronoun Personal", Category: "word", - Description: "Generates a random personal pronoun", + Description: "Pronoun referring to a specific persons or things", Example: "it", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounPersonal(r), nil }, }) @@ -128,10 +128,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounobject", Info{ Display: "Pronoun Object", Category: "word", - Description: "Generates a random object pronoun", + Description: "Pronoun used as the object of a verb or preposition", Example: "it", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounObject(r), nil }, }) @@ -139,10 +139,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounpossessive", Info{ Display: "Pronoun Possessive", Category: "word", - Description: "Generates a random possessive pronoun", + Description: "Pronoun indicating ownership or belonging", Example: "mine", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounPossessive(r), nil }, }) @@ -150,10 +150,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounreflective", Info{ Display: "Pronoun Reflective", Category: "word", - Description: "Generates a random reflective pronoun", + Description: "Pronoun referring back to the subject of the sentence", Example: "myself", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounReflective(r), nil }, }) @@ -161,10 +161,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounindefinite", Info{ Display: "Pronoun Indefinite", Category: "word", - Description: "Generates a random indefinite pronoun", + Description: "Pronoun that does not refer to a specific person or thing", Example: "few", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounIndefinite(r), nil }, }) @@ -172,10 +172,10 @@ func addWordPronounLookup() { AddFuncLookup("pronoundemonstrative", Info{ Display: "Pronoun Demonstrative", Category: "word", - Description: "Generates a random demonstrative pronoun", + Description: "Pronoun that points out specific people or things", Example: "this", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounDemonstrative(r), nil }, }) @@ -183,10 +183,10 @@ func addWordPronounLookup() { AddFuncLookup("pronouninterrogative", Info{ Display: "Pronoun Interrogative", Category: "word", - Description: "Generates a random interrogative pronoun", + Description: "Pronoun used to ask questions", Example: "what", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounInterrogative(r), nil }, }) @@ -194,10 +194,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounrelative", Info{ Display: "Pronoun Relative", Category: "word", - Description: "Generates a random relative pronoun", + Description: "Pronoun that introduces a clause, referring back to a noun or pronoun", Example: "as", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounRelative(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go b/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go index e5ae5eb21..de8d41e9e 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go @@ -124,13 +124,13 @@ func addWordSentenceLookup() { AddFuncLookup("sentence", Info{ Display: "Sentence", Category: "word", - Description: "Random sentence", + Description: "Set of words expressing a statement, question, exclamation, or command", Example: "Interpret context record river mind.", Output: "string", Params: []Param{ {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { wordCount, err := info.GetInt(m, "wordcount") if err != nil { return nil, err @@ -146,8 +146,8 @@ func addWordSentenceLookup() { AddFuncLookup("paragraph", Info{ Display: "Paragraph", Category: "word", - Description: "Random paragraph", - Example: "Interpret context record river mind press self should compare property outcome divide. Combine approach sustain consult discover explanation direct address church husband seek army. Begin own act welfare replace press suspect stay link place manchester specialist. Arrive price satisfy sign force application hair train provide basis right pay. Close mark teacher strengthen information attempt head touch aim iron tv take. Handle wait begin look speech trust cancer visit capacity disease chancellor clean. Race aim function gain couple push faith enjoy admit ring attitude develop. Edge game prevent cast mill favour father star live search aim guess. West heart item adopt compete equipment miss output report communicate model cabinet. Seek worker variety step argue air improve give succeed relief artist suffer. Hide finish insist knowledge thatcher make research chance structure proportion husband implement. Town crown restaurant cost material compete lady climb football region discussion order. Place lee market ice like display mind stress compete weather station raise. Democracy college major recall struggle use cut intention accept period generation strike. Benefit defend recommend conclude justify result depend succeed address owner fill interpret.", + Description: "Distinct section of writing covering a single theme, composed of multiple sentences", + Example: "Interpret context record river mind press self should compare property outcome divide. Combine approach sustain consult discover explanation direct address church husband seek army. Begin own act welfare replace press suspect stay link place manchester specialist. Arrive price satisfy sign force application hair train provide basis right pay. Close mark teacher strengthen information attempt head touch aim iron tv take.", Output: "string", Params: []Param{ {Field: "paragraphcount", Display: "Paragraph Count", Type: "int", Default: "2", Description: "Number of paragraphs"}, @@ -155,7 +155,7 @@ func addWordSentenceLookup() { {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, {Field: "paragraphseparator", Display: "Paragraph Separator", Type: "string", Default: "
", Description: "String value to add between paragraphs"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { paragraphCount, err := info.GetInt(m, "paragraphcount") if err != nil { return nil, err @@ -192,21 +192,21 @@ func addWordSentenceLookup() { AddFuncLookup("question", Info{ Display: "Question", Category: "word", - Description: "Random question", + Description: "Statement formulated to inquire or seek clarification", Example: "Roof chia echo?", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return question(r), nil }, }) AddFuncLookup("quote", Info{ - Display: "Qoute", + Display: "Quote", Category: "word", - Description: "Random quote", + Description: "Direct repetition of someone else's words", Example: `"Roof chia echo." - Lura Lockman`, Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return quote(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go b/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go index ab8b209b9..6a5db2347 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go @@ -63,10 +63,10 @@ func addWordVerbLookup() { AddFuncLookup("verb", Info{ Display: "Verb", Category: "word", - Description: "Random verb", + Description: "Word expressing an action, event or state", Example: "release", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verb(r), nil }, }) @@ -74,10 +74,10 @@ func addWordVerbLookup() { AddFuncLookup("verbaction", Info{ Display: "Action Verb", Category: "word", - Description: "Random action verb", + Description: "Verb Indicating a physical or mental action", Example: "close", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbAction(r), nil }, }) @@ -85,10 +85,10 @@ func addWordVerbLookup() { AddFuncLookup("verbtransitive", Info{ Display: "Transitive Verb", Category: "word", - Description: "Random transitive verb", + Description: "Verb that requires a direct object to complete its meaning", Example: "follow", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbTransitive(r), nil }, }) @@ -96,10 +96,10 @@ func addWordVerbLookup() { AddFuncLookup("verbintransitive", Info{ Display: "Intransitive Verb", Category: "word", - Description: "Random intransitive verb", + Description: "Verb that does not require a direct object to complete its meaning", Example: "laugh", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbIntransitive(r), nil }, }) @@ -107,10 +107,10 @@ func addWordVerbLookup() { AddFuncLookup("verblinking", Info{ Display: "Linking Verb", Category: "word", - Description: "Random linking verb", + Description: "Verb that Connects the subject of a sentence to a subject complement", Example: "was", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbLinking(r), nil }, }) @@ -118,10 +118,10 @@ func addWordVerbLookup() { AddFuncLookup("verbhelping", Info{ Display: "Helping Verb", Category: "word", - Description: "Random helping verb", + Description: "Auxiliary verb that helps the main verb complete the sentence", Example: "be", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbHelping(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/xml.go b/vendor/github.com/brianvoe/gofakeit/v6/xml.go index 98482cec7..b922d0def 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/xml.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/xml.go @@ -11,12 +11,12 @@ import ( // XMLOptions defines values needed for json generation type XMLOptions struct { - Type string `json:"type" xml:"type"` // single or multiple + Type string `json:"type" xml:"type" fake:"{randomstring:[array,single]}"` // single or array RootElement string `json:"root_element" xml:"root_element"` RecordElement string `json:"record_element" xml:"record_element"` - RowCount int `json:"row_count" xml:"row_count"` - Fields []Field `json:"fields" xml:"fields"` + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` Indent bool `json:"indent" xml:"indent"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } type xmlArray struct { @@ -27,12 +27,12 @@ type xmlArray struct { type xmlMap struct { XMLName xml.Name KeyOrder []string - Map map[string]interface{} `xml:",chardata"` + Map map[string]any `xml:",chardata"` } type xmlEntry struct { XMLName xml.Name - Value interface{} `xml:",chardata"` + Value any `xml:",chardata"` } func (m xmlMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error { @@ -97,15 +97,15 @@ func xmlMapLoop(e *xml.Encoder, m *xmlMap) error { case reflect.Map: err = e.Encode(xmlMap{ XMLName: xml.Name{Local: key}, - Map: m.Map[key].(map[string]interface{}), + Map: m.Map[key].(map[string]any), }) if err != nil { return err } case reflect.Struct: - // Convert struct to map[string]interface{} + // Convert struct to map[string]any // So we can rewrap element - var inInterface map[string]interface{} + var inInterface map[string]any inrec, _ := json.Marshal(m.Map[key]) json.Unmarshal(inrec, &inInterface) @@ -128,12 +128,22 @@ func xmlMapLoop(e *xml.Encoder, m *xmlMap) error { } // XML generates an object or an array of objects in json format -func XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(globalFaker.Rand, xo) } +// A nil XMLOptions returns a randomly structured XML. +func XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(globalFaker, xo) } // XML generates an object or an array of objects in json format -func (f *Faker) XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(f.Rand, xo) } +// A nil XMLOptions returns a randomly structured XML. +func (f *Faker) XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(f, xo) } + +func xmlFunc(f *Faker, xo *XMLOptions) ([]byte, error) { + if xo == nil { + // We didn't get a XMLOptions, so create a new random one + err := f.Struct(&xo) + if err != nil { + return nil, err + } + } -func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { // Check to make sure they passed in a type if xo.Type != "single" && xo.Type != "array" { return nil, errors.New("invalid type, must be array or object") @@ -164,10 +174,10 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { v := xmlMap{ XMLName: xml.Name{Local: xo.RootElement}, KeyOrder: keyOrder, - Map: make(map[string]interface{}), + Map: make(map[string]any), } - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for _, field := range xo.Fields { // Get function info funcInfo := GetFuncLookup(field.Function) @@ -175,7 +185,7 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { return nil, errors.New("invalid function, " + field.Function + " does not exist") } - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } @@ -212,10 +222,10 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { v := xmlMap{ XMLName: xml.Name{Local: xo.RecordElement}, KeyOrder: keyOrder, - Map: make(map[string]interface{}), + Map: make(map[string]any), } - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for _, field := range xo.Fields { if field.Function == "autoincrement" { v.Map[field.Name] = i @@ -228,7 +238,7 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { return nil, errors.New("invalid function, " + field.Function + " does not exist") } - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } @@ -261,20 +271,18 @@ func addFileXMLLookup() { Display: "XML", Category: "file", Description: "Generates an single or an array of elements in xml format", - Example: ` - - - Markus - Moen - Dc0VYXjkWABx - - - Osborne - Hilll - XPJ9OVNbs5lm - - - `, + Example: ` + + Markus + Moen + Dc0VYXjkWABx + + + Osborne + Hilll + XPJ9OVNbs5lm + +`, Output: "[]byte", ContentType: "application/xml", Params: []Param{ @@ -282,10 +290,10 @@ func addFileXMLLookup() { {Field: "rootelement", Display: "Root Element", Type: "string", Default: "xml", Description: "Root element wrapper name"}, {Field: "recordelement", Display: "Record Element", Type: "string", Default: "record", Description: "Record element for each record row"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows in JSON array"}, - {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, {Field: "indent", Display: "Indent", Type: "bool", Default: "false", Description: "Whether or not to add indents and newlines"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { xo := XMLOptions{} typ, err := info.GetString(m, "type") @@ -317,6 +325,12 @@ func addFileXMLLookup() { return nil, err } + indent, err := info.GetBool(m, "indent") + if err != nil { + return nil, err + } + xo.Indent = indent + // Check to make sure fields has length if len(fieldsStr) > 0 { xo.Fields = make([]Field, len(fieldsStr)) @@ -330,13 +344,8 @@ func addFileXMLLookup() { } } - indent, err := info.GetBool(m, "indent") - if err != nil { - return nil, err - } - xo.Indent = indent - - return xmlFunc(r, &xo) + f := &Faker{Rand: r} + return xmlFunc(f, &xo) }, }) } diff --git a/vendor/github.com/codegangsta/negroni/README.md b/vendor/github.com/codegangsta/negroni/README.md index 1b3491a20..172985595 100644 --- a/vendor/github.com/codegangsta/negroni/README.md +++ b/vendor/github.com/codegangsta/negroni/README.md @@ -1,26 +1,42 @@ -# Negroni [![GoDoc](https://godoc.org/github.com/codegangsta/negroni?status.svg)](http://godoc.org/github.com/codegangsta/negroni) [![wercker status](https://app.wercker.com/status/13688a4a94b82d84a0b8d038c4965b61/s "wercker status")](https://app.wercker.com/project/bykey/13688a4a94b82d84a0b8d038c4965b61) [![codebeat](https://codebeat.co/badges/47d320b1-209e-45e8-bd99-9094bc5111e2)](https://codebeat.co/projects/github-com-codegangsta-negroni) +# Negroni +[![GoDoc](https://godoc.org/github.com/urfave/negroni?status.svg)](http://godoc.org/github.com/urfave/negroni) +[![Build Status](https://travis-ci.org/urfave/negroni.svg?branch=master)](https://travis-ci.org/urfave/negroni) +[![codebeat](https://codebeat.co/badges/47d320b1-209e-45e8-bd99-9094bc5111e2)](https://codebeat.co/projects/github-com-urfave-negroni) +[![codecov](https://codecov.io/gh/urfave/negroni/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/negroni) -Negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of `net/http` Handlers. +**Notice:** This is the library formerly known as +`github.com/codegangsta/negroni` -- Github will automatically redirect requests +to this repository, but we recommend updating your references for clarity. -If you like the idea of [Martini](https://github.com/go-martini/martini), but you think it contains too much magic, then Negroni is a great fit. +Negroni is an idiomatic approach to web middleware in Go. It is tiny, +non-intrusive, and encourages use of `net/http` Handlers. +If you like the idea of [Martini](https://github.com/go-martini/martini), but +you think it contains too much magic, then Negroni is a great fit. Language Translations: +* [Deutsch (de_DE)](translations/README_de_de.md) * [Português Brasileiro (pt_BR)](translations/README_pt_br.md) -* [繁體中文 (zh_tw)](translations/README_zh_tw.md) -* [German (de_DE)](translations/README_de_de.md) +* [简体中文 (zh_CN)](translations/README_zh_CN.md) +* [繁體中文 (zh_TW)](translations/README_zh_tw.md) +* [日本語 (ja_JP)](translations/README_ja_JP.md) +* [Français (fr_FR)](translations/README_fr_FR.md) ## Getting Started -After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`. +After installing Go and setting up your +[GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. +We'll call it `server.go`. -~~~ go + +``` go package main import ( - "github.com/codegangsta/negroni" - "net/http" "fmt" + "net/http" + + "github.com/urfave/negroni" ) func main() { @@ -29,34 +45,47 @@ func main() { fmt.Fprintf(w, "Welcome to the home page!") }) - n := negroni.Classic() + n := negroni.Classic() // Includes some default middlewares n.UseHandler(mux) - n.Run(":3000") + + http.ListenAndServe(":3000", n) } -~~~ +``` + +Then install the Negroni package (**NOTE**: >= **go 1.1** is required): -Then install the Negroni package (**go 1.1** and greater is required): -~~~ -go get github.com/codegangsta/negroni -~~~ +``` +go get github.com/urfave/negroni +``` Then run your server: -~~~ + +``` go run server.go -~~~ +``` -You will now have a Go net/http webserver running on `localhost:3000`. +You will now have a Go `net/http` webserver running on `localhost:3000`. -## Need Help? -If you have a question or feature request, [go ask the mailing list](https://groups.google.com/forum/#!forum/negroni-users). The GitHub issues for Negroni will be used exclusively for bug reports and pull requests. +### Packaging + +If you are on Debian, `negroni` is also available as [a +package](https://packages.debian.org/sid/golang-github-urfave-negroni-dev) that +you can install via `apt install golang-github-urfave-negroni-dev` (at the time +of writing, it is in the `sid` repositories). ## Is Negroni a Framework? -Negroni is **not** a framework. It is a library that is designed to work directly with net/http. + +Negroni is **not** a framework. It is a middleware-focused library that is +designed to work directly with `net/http`. ## Routing? -Negroni is BYOR (Bring your own Router). The Go community already has a number of great http routers available, Negroni tries to play well with all of them by fully supporting `net/http`. For instance, integrating with [Gorilla Mux](https://github.com/gorilla/mux) looks like so: -~~~ go +Negroni is BYOR (Bring your own Router). The Go community already has a number +of great http routers available, and Negroni tries to play well with all of them +by fully supporting `net/http`. For instance, integrating with [Gorilla Mux] +looks like so: + +``` go router := mux.NewRouter() router.HandleFunc("/", HomeHandler) @@ -66,47 +95,54 @@ n.Use(Middleware3) // router goes last n.UseHandler(router) -n.Run(":3000") -~~~ +http.ListenAndServe(":3001", n) +``` ## `negroni.Classic()` -`negroni.Classic()` provides some default middleware that is useful for most applications: -* `negroni.Recovery` - Panic Recovery Middleware. -* `negroni.Logger` - Request/Response Logger Middleware. -* `negroni.Static` - Static File serving under the "public" directory. +`negroni.Classic()` provides some default middleware that is useful for most +applications: + +* [`negroni.Recovery`](#recovery) - Panic Recovery Middleware. +* [`negroni.Logger`](#logger) - Request/Response Logger Middleware. +* [`negroni.Static`](#static) - Static File serving under the "public" + directory. This makes it really easy to get started with some useful features from Negroni. ## Handlers -Negroni provides a bidirectional middleware flow. This is done through the `negroni.Handler` interface: -~~~ go +Negroni provides a bidirectional middleware flow. This is done through the +`negroni.Handler` interface: + +``` go type Handler interface { ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) } -~~~ +``` -If a middleware hasn't already written to the ResponseWriter, it should call the next `http.HandlerFunc` in the chain to yield to the next middleware handler. This can be used for great good: +If a middleware hasn't already written to the `ResponseWriter`, it should call +the next `http.HandlerFunc` in the chain to yield to the next middleware +handler. This can be used for great good: -~~~ go +``` go func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { // do some stuff before next(rw, r) // do some stuff after } -~~~ +``` And you can map it to the handler chain with the `Use` function: -~~~ go +``` go n := negroni.New() n.Use(negroni.HandlerFunc(MyMiddleware)) -~~~ +``` You can also map plain old `http.Handler`s: -~~~ go +``` go n := negroni.New() mux := http.NewServeMux() @@ -114,22 +150,94 @@ mux := http.NewServeMux() n.UseHandler(mux) -n.Run(":3000") -~~~ +http.ListenAndServe(":3000", n) +``` + +## `With()` + +Negroni has a convenience function called `With`. `With` takes one or more +`Handler` instances and returns a new `Negroni` with the combination of the +receiver's handlers and the new handlers. + +```go +// middleware we want to reuse +common := negroni.New() +common.Use(MyMiddleware1) +common.Use(MyMiddleware2) + +// `specific` is a new negroni with the handlers from `common` combined with the +// the handlers passed in +specific := common.With( + SpecificMiddleware1, + SpecificMiddleware2 +) +``` ## `Run()` -Negroni has a convenience function called `Run`. `Run` takes an addr string identical to [http.ListenAndServe](http://golang.org/pkg/net/http#ListenAndServe). -~~~ go -n := negroni.Classic() -// ... -log.Fatal(http.ListenAndServe(":8080", n)) -~~~ +Negroni has a convenience function called `Run`. `Run` takes an addr string +identical to [`http.ListenAndServe`](https://godoc.org/net/http#ListenAndServe). + + +``` go +package main + +import ( + "github.com/urfave/negroni" +) + +func main() { + n := negroni.Classic() + n.Run(":8080") +} +``` +If no address is provided, the `PORT` environment variable is used instead. +If the `PORT` environment variable is not defined, the default address will be used. +See [Run](https://godoc.org/github.com/urfave/negroni#Negroni.Run) for a complete description. + +In general, you will want to use `net/http` methods and pass `negroni` as a +`Handler`, as this is more flexible, e.g.: + + +``` go +package main + +import ( + "fmt" + "log" + "net/http" + "time" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) + + n := negroni.Classic() // Includes some default middlewares + n.UseHandler(mux) + + s := &http.Server{ + Addr: ":8080", + Handler: n, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + log.Fatal(s.ListenAndServe()) +} +``` ## Route Specific Middleware -If you have a route group of routes that need specific middleware to be executed, you can simply create a new Negroni instance and use it as your route handler. -~~~ go +If you have a route group of routes that need specific middleware to be +executed, you can simply create a new Negroni instance and use it as your route +handler. + +``` go router := mux.NewRouter() adminRoutes := mux.NewRouter() // add admin routes here @@ -140,11 +248,11 @@ router.PathPrefix("/admin").Handler(negroni.New( Middleware2, negroni.Wrap(adminRoutes), )) -~~~ +``` -If you are using [Gorilla Mux](http://github.com/gorilla/mux) here is an example using a subrouter. +If you are using [Gorilla Mux], here is an example using a subrouter: -~~~go +``` go router := mux.NewRouter() subRouter := mux.NewRouter().PathPrefix("/subpath").Subrouter().StrictSlash(true) subRouter.HandleFunc("/", someSubpathHandler) // "/subpath/" @@ -152,44 +260,280 @@ subRouter.HandleFunc("/:id", someSubpathHandler) // "/subpath/:id" // "/subpath" is necessary to ensure the subRouter and main router linkup router.PathPrefix("/subpath").Handler(negroni.New( + Middleware1, + Middleware2, + negroni.Wrap(subRouter), +)) +``` + +`With()` can be used to eliminate redundancy for middlewares shared across +routes. + +``` go +router := mux.NewRouter() +apiRoutes := mux.NewRouter() +// add api routes here +webRoutes := mux.NewRouter() +// add web routes here + +// create common middleware to be shared across routes +common := negroni.New( Middleware1, Middleware2, - negroni.Wrap(subRouter), +) + +// create a new negroni for the api middleware +// using the common middleware as a base +router.PathPrefix("/api").Handler(common.With( + APIMiddleware1, + negroni.Wrap(apiRoutes), +)) +// create a new negroni for the web middleware +// using the common middleware as a base +router.PathPrefix("/web").Handler(common.With( + WebMiddleware1, + negroni.Wrap(webRoutes), )) -~~~ +``` -## Third Party Middleware +## Bundled Middleware + +### Static + +This middleware will serve files on the filesystem. If the files do not exist, +it proxies the request to the next middleware. If you want the requests for +non-existent files to return a `404 File Not Found` to the user you should look +at using [http.FileServer](https://golang.org/pkg/net/http/#FileServer) as +a handler. + +Example: + + +``` go +package main + +import ( + "fmt" + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) -Here is a current list of Negroni compatible middlware. Feel free to put up a PR linking your middleware if you have built one: + // Example of using a http.FileServer if you want "server-like" rather than "middleware" behavior + // mux.Handle("/public", http.FileServer(http.Dir("/home/public"))) + + n := negroni.New() + n.Use(negroni.NewStatic(http.Dir("/tmp"))) + n.UseHandler(mux) + + http.ListenAndServe(":3002", n) +} +``` + +Will serve files from the `/tmp` directory first, but proxy calls to the next +handler if the request does not match a file on the filesystem. + +### Recovery + +This middleware catches `panic`s and responds with a `500` response code. If +any other middleware has written a response code or body, this middleware will +fail to properly send a 500 to the client, as the client has already received +the HTTP response code. Additionally, an `PanicHandlerFunc` can be attached +to report 500's to an error reporting service such as Sentry or Airbrake. + +Example: + + +``` go +package main + +import ( + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + panic("oh no") + }) + + n := negroni.New() + n.Use(negroni.NewRecovery()) + n.UseHandler(mux) + + http.ListenAndServe(":3003", n) +} +``` +Will return a `500 Internal Server Error` to each request. It will also log the +stack traces as well as print the stack trace to the requester if `PrintStack` +is set to `true` (the default). + +Example with error handler: + +``` go +package main + +import ( + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + panic("oh no") + }) + + n := negroni.New() + recovery := negroni.NewRecovery() + recovery.PanicHandlerFunc = reportToSentry + n.Use(recovery) + n.UseHandler(mux) + + http.ListenAndServe(":3003", n) +} + +func reportToSentry(info *negroni.PanicInformation) { + // write code here to report error to Sentry +} +``` + +The middleware simply output the informations on STDOUT by default. +You can customize the output process by using the `SetFormatter()` function. + +You can use also the `HTMLPanicFormatter` to display a pretty HTML when a crash occurs. + + +``` go +package main + +import ( + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + panic("oh no") + }) + + n := negroni.New() + recovery := negroni.NewRecovery() + recovery.Formatter = &negroni.HTMLPanicFormatter{} + n.Use(recovery) + n.UseHandler(mux) + + http.ListenAndServe(":3003", n) +} +``` + +## Logger + +This middleware logs each incoming request and response. + +Example: + + +``` go +package main + +import ( + "fmt" + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) + + n := negroni.New() + n.Use(negroni.NewLogger()) + n.UseHandler(mux) + + http.ListenAndServe(":3004", n) +} +``` + +Will print a log similar to: + +``` +[negroni] 2017-10-04T14:56:25+02:00 | 200 | 378µs | localhost:3004 | GET / +``` + +on each request. + +You can also set your own log format by calling the `SetFormat` function. The format is a template string with fields as mentioned in the `LoggerEntry` struct. So, as an example - + +```go +l.SetFormat("[{{.Status}} {{.Duration}}] - {{.Request.UserAgent}}") +``` + +will show something like - `[200 18.263µs] - Go-User-Agent/1.1 ` + +## Third Party Middleware + +Here is a current list of Negroni compatible middlware. Feel free to put up a PR +linking your middleware if you have built one: | Middleware | Author | Description | | -----------|--------|-------------| -| [RestGate](https://github.com/pjebs/restgate) | [Prasanga Siripala](https://github.com/pjebs) | Secure authentication for REST API endpoints | -| [Graceful](https://github.com/tylerb/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown | -| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Middleware that implements a few quick security wins | -| [JWT Middleware](https://github.com/auth0/go-jwt-middleware) | [Auth0](https://github.com/auth0) | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it| +| [authz](https://github.com/casbin/negroni-authz) | [Yang Luo](https://github.com/hsluoyz) | ACL, RBAC, ABAC Authorization middlware based on [Casbin](https://github.com/casbin/casbin) | | [binding](https://github.com/mholt/binding) | [Matt Holt](https://github.com/mholt) | Data binding from HTTP requests into structs | -| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger | -| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Render JSON, XML and HTML templates | +| [cloudwatch](https://github.com/cvillecsteele/negroni-cloudwatch) | [Colin Steele](https://github.com/cvillecsteele) | AWS cloudwatch metrics middleware | +| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support | +| [csp](https://github.com/awakenetworks/csp) | [Awake Networks](https://github.com/awakenetworks) | [Content Security Policy](https://www.w3.org/TR/CSP2/) (CSP) support | +| [delay](https://github.com/jeffbmartinez/delay) | [Jeff Martinez](https://github.com/jeffbmartinez) | Add delays/latency to endpoints. Useful when testing effects of high latency | +| [New Relic Go Agent](https://github.com/yadvendar/negroni-newrelic-go-agent) | [Yadvendar Champawat](https://github.com/yadvendar) | Official [New Relic Go Agent](https://github.com/newrelic/go-agent) (currently in beta) | | [gorelic](https://github.com/jingweno/negroni-gorelic) | [Jingwen Owen Ou](https://github.com/jingweno) | New Relic agent for Go runtime | +| [Graceful](https://github.com/tylerb/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown | | [gzip](https://github.com/phyber/negroni-gzip) | [phyber](https://github.com/phyber) | GZIP response compression | +| [JWT Middleware](https://github.com/auth0/go-jwt-middleware) | [Auth0](https://github.com/auth0) | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it| +| [JWT Middleware](https://github.com/mfuentesg/go-jwtmiddleware) | [Marcelo Fuentes](https://github.com/mfuentesg) | JWT middleware for golang | +| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger | | [oauth2](https://github.com/goincremental/negroni-oauth2) | [David Bochenski](https://github.com/bochenski) | oAuth2 middleware | -| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Session Management | -| [permissions2](https://github.com/xyproto/permissions2) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, users and permissions | | [onthefly](https://github.com/xyproto/onthefly) | [Alexander Rødseth](https://github.com/xyproto) | Generate TinySVG, HTML and CSS on the fly | -| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support | -| [xrequestid](https://github.com/pilu/xrequestid) | [Andrea Franz](https://github.com/pilu) | Middleware that assigns a random X-Request-Id header to each request | -| [VanGoH](https://github.com/auroratechnologies/vangoh) | [Taylor Wrobel](https://github.com/twrobel3) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware | -| [stats](https://github.com/thoas/stats) | [Florent Messa](https://github.com/thoas) | Store information about your web application (response time, etc.) | +| [permissions2](https://github.com/xyproto/permissions2) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, users and permissions | | [prometheus](https://github.com/zbindenren/negroni-prometheus) | [Rene Zbinden](https://github.com/zbindenren) | Easily create metrics endpoint for the [prometheus](http://prometheus.io) instrumentation tool | -| [delay](https://github.com/jeffbmartinez/delay) | [Jeff Martinez](https://github.com/jeffbmartinez) | Add delays/latency to endpoints. Useful when testing effects of high latency | +| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Render JSON, XML and HTML templates | +| [RestGate](https://github.com/pjebs/restgate) | [Prasanga Siripala](https://github.com/pjebs) | Secure authentication for REST API endpoints | +| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Middleware that implements a few quick security wins | +| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Session Management | +| [stats](https://github.com/thoas/stats) | [Florent Messa](https://github.com/thoas) | Store information about your web application (response time, etc.) | +| [VanGoH](https://github.com/auroratechnologies/vangoh) | [Taylor Wrobel](https://github.com/twrobel3) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware | +| [xrequestid](https://github.com/pilu/xrequestid) | [Andrea Franz](https://github.com/pilu) | Middleware that assigns a random X-Request-Id header to each request | +| [mgo session](https://github.com/joeljames/nigroni-mgo-session) | [Joel James](https://github.com/joeljames) | Middleware that handles creating and closing mgo sessions per request | +| [digits](https://github.com/bamarni/digits) | [Bilal Amarni](https://github.com/bamarni) | Middleware that handles [Twitter Digits](https://get.digits.com/) authentication | +| [stats](https://github.com/guptachirag/stats) | [Chirag Gupta](https://github.com/guptachirag/stats) | Middleware that manages qps and latency stats for your endpoints and asynchronously flushes them to influx db | +| [Chaos](https://github.com/falzm/chaos) | [Marc Falzon](https://github.com/falzm) | Middleware for injecting chaotic behavior into application in a programmatic way | ## Examples -[Alexander Rødseth](https://github.com/xyproto) created [mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a Negroni middleware handler. + +[Alexander Rødseth](https://github.com/xyproto) created +[mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a +Negroni middleware handler. + +[Prasanga Siripala](https://github.com/pjebs) created an effective skeleton structure for web-based Go/Negroni projects: [Go-Skeleton](https://github.com/pjebs/go-skeleton) ## Live code reload? -[gin](https://github.com/codegangsta/gin) and [fresh](https://github.com/pilu/fresh) both live reload negroni apps. + +[gin](https://github.com/codegangsta/gin) and +[fresh](https://github.com/pilu/fresh) both live reload negroni apps. ## Essential Reading for Beginners of Go & Negroni @@ -198,4 +542,8 @@ Here is a current list of Negroni compatible middlware. Feel free to put up a PR ## About -Negroni is obsessively designed by none other than the [Code Gangsta](https://codegangsta.io/) +Negroni is obsessively designed by none other than the [Code +Gangsta](https://codegangsta.io/) + +[Gorilla Mux]: https://github.com/gorilla/mux +[`http.FileSystem`]: https://godoc.org/net/http#FileSystem diff --git a/vendor/github.com/codegangsta/negroni/doc.go b/vendor/github.com/codegangsta/negroni/doc.go index 24d6572c2..add1ed9f7 100644 --- a/vendor/github.com/codegangsta/negroni/doc.go +++ b/vendor/github.com/codegangsta/negroni/doc.go @@ -2,12 +2,12 @@ // // If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. // -// For a full guide visit http://github.com/codegangsta/negroni +// For a full guide visit http://github.com/urfave/negroni // // package main // // import ( -// "github.com/codegangsta/negroni" +// "github.com/urfave/negroni" // "net/http" // "fmt" // ) diff --git a/vendor/github.com/codegangsta/negroni/logger.go b/vendor/github.com/codegangsta/negroni/logger.go index e3828ef31..9c2216ba6 100644 --- a/vendor/github.com/codegangsta/negroni/logger.go +++ b/vendor/github.com/codegangsta/negroni/logger.go @@ -1,29 +1,78 @@ package negroni import ( + "bytes" + "log" "net/http" "os" + "text/template" "time" ) +// LoggerEntry is the structure passed to the template. +type LoggerEntry struct { + StartTime string + Status int + Duration time.Duration + Hostname string + Method string + Path string + Request *http.Request +} + +// LoggerDefaultFormat is the format logged used by the default Logger instance. +var LoggerDefaultFormat = "{{.StartTime}} | {{.Status}} | \t {{.Duration}} | {{.Hostname}} | {{.Method}} {{.Path}}" + +// LoggerDefaultDateFormat is the format used for date by the default Logger instance. +var LoggerDefaultDateFormat = time.RFC3339 + +// ALogger interface +type ALogger interface { + Println(v ...interface{}) + Printf(format string, v ...interface{}) +} + // Logger is a middleware handler that logs the request as it goes in and the response as it goes out. type Logger struct { - // Logger inherits from log.Logger used to log messages with the Logger middleware - *log.Logger + // ALogger implements just enough log.Logger interface to be compatible with other implementations + ALogger + dateFormat string + template *template.Template } // NewLogger returns a new Logger instance func NewLogger() *Logger { - return &Logger{log.New(os.Stdout, "[negroni] ", 0)} + logger := &Logger{ALogger: log.New(os.Stdout, "[negroni] ", 0), dateFormat: LoggerDefaultDateFormat} + logger.SetFormat(LoggerDefaultFormat) + return logger +} + +func (l *Logger) SetFormat(format string) { + l.template = template.Must(template.New("negroni_parser").Parse(format)) +} + +func (l *Logger) SetDateFormat(format string) { + l.dateFormat = format } func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { start := time.Now() - l.Printf("Started %s %s", r.Method, r.URL.Path) next(rw, r) res := rw.(ResponseWriter) - l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start)) + log := LoggerEntry{ + StartTime: start.Format(l.dateFormat), + Status: res.Status(), + Duration: time.Since(start), + Hostname: r.Host, + Method: r.Method, + Path: r.URL.Path, + Request: r, + } + + buff := &bytes.Buffer{} + l.template.Execute(buff, log) + l.Println(buff.String()) } diff --git a/vendor/github.com/codegangsta/negroni/negroni.go b/vendor/github.com/codegangsta/negroni/negroni.go index 57d15eb79..d1d77820a 100644 --- a/vendor/github.com/codegangsta/negroni/negroni.go +++ b/vendor/github.com/codegangsta/negroni/negroni.go @@ -6,6 +6,11 @@ import ( "os" ) +const ( + // DefaultAddress is used if no other is specified. + DefaultAddress = ":8080" +) + // Handler handler is an interface that objects can implement to be registered to serve as middleware // in the Negroni middleware stack. // ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc @@ -43,6 +48,16 @@ func Wrap(handler http.Handler) Handler { }) } +// WrapFunc converts a http.HandlerFunc into a negroni.Handler so it can be used as a Negroni +// middleware. The next http.HandlerFunc is automatically called after the Handler +// is executed. +func WrapFunc(handlerFunc http.HandlerFunc) Handler { + return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + handlerFunc(rw, r) + next(rw, r) + }) +} + // Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler. // Negroni middleware is evaluated in the order that they are added to the stack using // the Use and UseHandler methods. @@ -59,6 +74,14 @@ func New(handlers ...Handler) *Negroni { } } +// With returns a new Negroni instance that is a combination of the negroni +// receiver's handlers and the provided handlers. +func (n *Negroni) With(handlers ...Handler) *Negroni { + return New( + append(n.handlers, handlers...)..., + ) +} + // Classic returns a new Negroni instance with the default middleware already // in the stack. // @@ -75,6 +98,10 @@ func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { // Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. func (n *Negroni) Use(handler Handler) { + if handler == nil { + panic("handler cannot be nil") + } + n.handlers = append(n.handlers, handler) n.middleware = build(n.handlers) } @@ -89,17 +116,30 @@ func (n *Negroni) UseHandler(handler http.Handler) { n.Use(Wrap(handler)) } -// UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack. +// UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack. func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { n.UseHandler(http.HandlerFunc(handlerFunc)) } // Run is a convenience function that runs the negroni stack as an HTTP -// server. The addr string takes the same format as http.ListenAndServe. -func (n *Negroni) Run(addr string) { +// server. The addr string, if provided, takes the same format as http.ListenAndServe. +// If no address is provided but the PORT environment variable is set, the PORT value is used. +// If neither is provided, the address' value will equal the DefaultAddress constant. +func (n *Negroni) Run(addr ...string) { l := log.New(os.Stdout, "[negroni] ", 0) - l.Printf("listening on %s", addr) - l.Fatal(http.ListenAndServe(addr, n)) + finalAddr := detectAddress(addr...) + l.Printf("listening on %s", finalAddr) + l.Fatal(http.ListenAndServe(finalAddr, n)) +} + +func detectAddress(addr ...string) string { + if len(addr) > 0 { + return addr[0] + } + if port := os.Getenv("PORT"); port != "" { + return ":" + port + } + return DefaultAddress } // Returns a list of all the handlers in the current Negroni middleware chain. diff --git a/vendor/github.com/codegangsta/negroni/recovery.go b/vendor/github.com/codegangsta/negroni/recovery.go index d790cade6..c6fc24ef5 100644 --- a/vendor/github.com/codegangsta/negroni/recovery.go +++ b/vendor/github.com/codegangsta/negroni/recovery.go @@ -6,14 +6,137 @@ import ( "net/http" "os" "runtime" + "runtime/debug" + "text/template" ) +const ( + panicText = "PANIC: %s\n%s" + panicHTML = ` +PANIC: {{.RecoveredPanic}} + + +

Negroni - PANIC

+ +
+

{{.RequestDescription}}

+ Runtime error: {{.RecoveredPanic}} +
+ +{{ if .Stack }} +
+

Runtime Stack

+
{{.StackAsString}}
+
+{{ end }} + + +` + nilRequestMessage = "Request is nil" +) + +var panicHTMLTemplate = template.Must(template.New("PanicPage").Parse(panicHTML)) + +// PanicInformation contains all +// elements for printing stack informations. +type PanicInformation struct { + RecoveredPanic interface{} + Stack []byte + Request *http.Request +} + +// StackAsString returns a printable version of the stack +func (p *PanicInformation) StackAsString() string { + return string(p.Stack) +} + +// RequestDescription returns a printable description of the url +func (p *PanicInformation) RequestDescription() string { + + if p.Request == nil { + return nilRequestMessage + } + + var queryOutput string + if p.Request.URL.RawQuery != "" { + queryOutput = "?" + p.Request.URL.RawQuery + } + return fmt.Sprintf("%s %s%s", p.Request.Method, p.Request.URL.Path, queryOutput) +} + +// PanicFormatter is an interface on object can implement +// to be able to output the stack trace +type PanicFormatter interface { + // FormatPanicError output the stack for a given answer/response. + // In case the the middleware should not output the stack trace, + // the field `Stack` of the passed `PanicInformation` instance equals `[]byte{}`. + FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) +} + +// TextPanicFormatter output the stack +// as simple text on os.Stdout. If no `Content-Type` is set, +// it will output the data as `text/plain; charset=utf-8`. +// Otherwise, the origin `Content-Type` is kept. +type TextPanicFormatter struct{} + +func (t *TextPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) { + if rw.Header().Get("Content-Type") == "" { + rw.Header().Set("Content-Type", "text/plain; charset=utf-8") + } + fmt.Fprintf(rw, panicText, infos.RecoveredPanic, infos.Stack) +} + +// HTMLPanicFormatter output the stack inside +// an HTML page. This has been largely inspired by +// https://github.com/go-martini/martini/pull/156/commits. +type HTMLPanicFormatter struct{} + +func (t *HTMLPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) { + if rw.Header().Get("Content-Type") == "" { + rw.Header().Set("Content-Type", "text/html; charset=utf-8") + } + panicHTMLTemplate.Execute(rw, infos) +} + // Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. type Recovery struct { - Logger *log.Logger - PrintStack bool - StackAll bool - StackSize int + Logger ALogger + PrintStack bool + PanicHandlerFunc func(*PanicInformation) + StackAll bool + StackSize int + Formatter PanicFormatter + + // Deprecated: Use PanicHandlerFunc instead to receive panic + // error with additional information (see PanicInformation) + ErrorHandlerFunc func(interface{}) } // NewRecovery returns a new instance of Recovery @@ -23,6 +146,7 @@ func NewRecovery() *Recovery { PrintStack: true, StackAll: false, StackSize: 1024 * 8, + Formatter: &TextPanicFormatter{}, } } @@ -30,14 +154,38 @@ func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next htt defer func() { if err := recover(); err != nil { rw.WriteHeader(http.StatusInternalServerError) + stack := make([]byte, rec.StackSize) stack = stack[:runtime.Stack(stack, rec.StackAll)] - - f := "PANIC: %s\n%s" - rec.Logger.Printf(f, err, stack) + infos := &PanicInformation{RecoveredPanic: err, Request: r} if rec.PrintStack { - fmt.Fprintf(rw, f, err, stack) + infos.Stack = stack + } + rec.Logger.Printf(panicText, err, stack) + rec.Formatter.FormatPanicError(rw, r, infos) + + if rec.ErrorHandlerFunc != nil { + func() { + defer func() { + if err := recover(); err != nil { + rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack()) + rec.Logger.Printf("%s\n", debug.Stack()) + } + }() + rec.ErrorHandlerFunc(err) + }() + } + if rec.PanicHandlerFunc != nil { + func() { + defer func() { + if err := recover(); err != nil { + rec.Logger.Printf("provided PanicHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack()) + rec.Logger.Printf("%s\n", debug.Stack()) + } + }() + rec.PanicHandlerFunc(infos) + }() } } }() diff --git a/vendor/github.com/codegangsta/negroni/response_writer.go b/vendor/github.com/codegangsta/negroni/response_writer.go index 217cbd82a..cc507eb4b 100644 --- a/vendor/github.com/codegangsta/negroni/response_writer.go +++ b/vendor/github.com/codegangsta/negroni/response_writer.go @@ -13,7 +13,8 @@ import ( type ResponseWriter interface { http.ResponseWriter http.Flusher - // Status returns the status code of the response or 0 if the response has not been written. + // Status returns the status code of the response or 0 if the response has + // not been written Status() int // Written returns whether or not the ResponseWriter has been written. Written() bool @@ -28,11 +29,15 @@ type beforeFunc func(ResponseWriter) // NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { - return &responseWriter{ + nrw := &responseWriter{ ResponseWriter: rw, - status: http.StatusOK, - size: 0, - beforeFuncs: nil} + } + + if _, ok := rw.(http.CloseNotifier); ok { + return &responseWriterCloseNotifer{nrw} + } + + return nrw } type responseWriter struct { @@ -82,10 +87,6 @@ func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return hijacker.Hijack() } -func (rw *responseWriter) CloseNotify() <-chan bool { - return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - func (rw *responseWriter) callBefore() { for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { rw.beforeFuncs[i](rw) @@ -95,6 +96,18 @@ func (rw *responseWriter) callBefore() { func (rw *responseWriter) Flush() { flusher, ok := rw.ResponseWriter.(http.Flusher) if ok { + if !rw.Written() { + // The status will be StatusOK if WriteHeader has not been called yet + rw.WriteHeader(http.StatusOK) + } flusher.Flush() } } + +type responseWriterCloseNotifer struct { + *responseWriter +} + +func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool { + return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() +} diff --git a/vendor/github.com/codegangsta/negroni/static.go b/vendor/github.com/codegangsta/negroni/static.go index c5af4e688..34be967c0 100644 --- a/vendor/github.com/codegangsta/negroni/static.go +++ b/vendor/github.com/codegangsta/negroni/static.go @@ -6,7 +6,11 @@ import ( "strings" ) -// Static is a middleware handler that serves static files in the given directory/filesystem. +// Static is a middleware handler that serves static files in the given +// directory/filesystem. If the file does not exist on the filesystem, it +// passes along to the next middleware in the chain. If you desire "fileserver" +// type behavior where it returns a 404 for unfound files, you should consider +// using http.FileServer from the Go stdlib. type Static struct { // Dir is the directory to serve static files from Dir http.FileSystem diff --git a/vendor/github.com/corpix/uarand/.gitignore b/vendor/github.com/corpix/uarand/.gitignore index 4f59364bc..6fb5d8fc7 100644 --- a/vendor/github.com/corpix/uarand/.gitignore +++ b/vendor/github.com/corpix/uarand/.gitignore @@ -1,3 +1,2 @@ /build -/vendor *~ diff --git a/vendor/github.com/corpix/uarand/.go-makefile.json b/vendor/github.com/corpix/uarand/.go-makefile.json deleted file mode 100644 index b111df4e2..000000000 --- a/vendor/github.com/corpix/uarand/.go-makefile.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "build_id_generator": "0x$(shell echo $(version) | sha1sum | awk '{print $$1}')", - "host": "github.com", - "include": ["useragents.mk"], - "kind": "package", - "name": "uarand", - "tool": [], - "user": "corpix", - "version_generator": "$(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD)", - "version_variable": "cli.version" -} diff --git a/vendor/github.com/corpix/uarand/.travis.yml b/vendor/github.com/corpix/uarand/.travis.yml index 0d9e6e633..58114d498 100644 --- a/vendor/github.com/corpix/uarand/.travis.yml +++ b/vendor/github.com/corpix/uarand/.travis.yml @@ -1,9 +1,3 @@ -language: go +language: nix -go: - - 1.6 - - 1.7 - - 1.8 - - master - -script: make test +script: nix-shell --pure --command "make lint test" diff --git a/vendor/github.com/corpix/uarand/LICENSE b/vendor/github.com/corpix/uarand/LICENSE index e70c2b1f3..68a49daad 100644 --- a/vendor/github.com/corpix/uarand/LICENSE +++ b/vendor/github.com/corpix/uarand/LICENSE @@ -1,21 +1,24 @@ -The MIT License (MIT) +This is free and unencumbered software released into the public domain. -Copyright © 2017 Dmitry Moskowski +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +For more information, please refer to diff --git a/vendor/github.com/corpix/uarand/Makefile b/vendor/github.com/corpix/uarand/Makefile index d96582158..375b2acd2 100644 --- a/vendor/github.com/corpix/uarand/Makefile +++ b/vendor/github.com/corpix/uarand/Makefile @@ -1,52 +1,30 @@ .DEFAULT_GOAL = all -numcpus := $(shell cat /proc/cpuinfo | grep '^processor\s*:' | wc -l) -version := $(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD) - name := uarand package := github.com/corpix/$(name) .PHONY: all -all:: dependencies - -.PHONY: tools -tools:: - @if [ ! -e "$(GOPATH)"/bin/glide ]; then go get github.com/Masterminds/glide; fi - @if [ ! -e "$(GOPATH)"/bin/glide-cleanup ]; then go get github.com/ngdinhtoan/glide-cleanup; fi - @if [ ! -e "$(GOPATH)"/bin/glide-vc ]; then go get github.com/sgotti/glide-vc; fi - @if [ ! -e "$(GOPATH)"/bin/godef ]; then go get github.com/rogpeppe/godef; fi - @if [ ! -e "$(GOPATH)"/bin/gocode ]; then go get github.com/nsf/gocode; fi - @if [ ! -e "$(GOPATH)"/bin/gometalinter ]; then go get github.com/alecthomas/gometalinter && gometalinter --install; fi - @if [ ! -e "$(GOPATH)"/src/github.com/stretchr/testify/assert ]; then go get github.com/stretchr/testify/assert; fi - -.PHONY: dependencies -dependencies:: tools - glide install - -.PHONY: clean -clean:: tools - glide cache-clear +all:: useragents.go .PHONY: test -test:: dependencies - go test -v \ - $(shell glide novendor) - -.PHONY: bench -bench:: dependencies - go test \ - -bench=. -v \ - $(shell glide novendor) +test: + go test -v ./... .PHONY: lint -lint:: dependencies - go vet $(shell glide novendor) - gometalinter \ - --deadline=5m \ - --concurrency=$(numcpus) \ - $(shell glide novendor) +lint: +.PHONY: lint +lint: + golangci-lint --color=always \ + --exclude='uses unkeyed fields' \ + --exclude='type .* is unused' \ + --exclude='should merge variable declaration with assignment on next line' \ + --deadline=120s \ + run ./... .PHONY: check -check:: lint test +check: lint test -include useragents.mk +.PHONY: useragents.go +useragents.go: + ./scripts/fetch-user-agents | ./scripts/generate-useragents-go $(name) > $@ + go fmt $@ diff --git a/vendor/github.com/corpix/uarand/README.md b/vendor/github.com/corpix/uarand/README.md index d79b5c29b..c8d98a98a 100644 --- a/vendor/github.com/corpix/uarand/README.md +++ b/vendor/github.com/corpix/uarand/README.md @@ -35,4 +35,4 @@ Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41 ## License -MIT +[Unlicense](https://unlicense.org/) diff --git a/vendor/github.com/corpix/uarand/glide.lock b/vendor/github.com/corpix/uarand/glide.lock deleted file mode 100644 index abb3ec579..000000000 --- a/vendor/github.com/corpix/uarand/glide.lock +++ /dev/null @@ -1,16 +0,0 @@ -hash: 400dee10adae21284f2563cb7178f4b5a30e69c9ed3954a5a32a8a618d5bdfeb -updated: 2017-07-12T21:00:19.452016303Z -imports: [] -testImports: -- name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 - subpackages: - - spew -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert diff --git a/vendor/github.com/corpix/uarand/glide.yaml b/vendor/github.com/corpix/uarand/glide.yaml deleted file mode 100644 index 037ee2450..000000000 --- a/vendor/github.com/corpix/uarand/glide.yaml +++ /dev/null @@ -1,7 +0,0 @@ -package: github.com/corpix/uarand -import: [] -testImport: -- package: github.com/stretchr/testify - version: v1.1.4 - subpackages: - - assert diff --git a/vendor/github.com/corpix/uarand/uarand.go b/vendor/github.com/corpix/uarand/uarand.go index 04f9247c2..fad733784 100644 --- a/vendor/github.com/corpix/uarand/uarand.go +++ b/vendor/github.com/corpix/uarand/uarand.go @@ -2,6 +2,7 @@ package uarand import ( "math/rand" + "sync" "time" ) @@ -23,11 +24,18 @@ type Randomizer interface { // UARand describes the user agent randomizer settings. type UARand struct { Randomizer + UserAgents []string + + mutex sync.Mutex } // GetRandom returns a random user agent from UserAgents slice. func (u *UARand) GetRandom() string { - return UserAgents[u.Intn(len(UserAgents))] + u.mutex.Lock() + n := u.Intn(len(u.UserAgents)) + u.mutex.Unlock() + + return u.UserAgents[n] } // GetRandom returns a random user agent from UserAgents slice. @@ -36,6 +44,20 @@ func GetRandom() string { return Default.GetRandom() } +// New return UserAgent randomizer settings with default user-agents list func New(r Randomizer) *UARand { - return &UARand{r} + return &UARand{ + Randomizer: r, + UserAgents: UserAgents, + mutex: sync.Mutex{}, + } +} + +// NewWithCustomList return UserAgent randomizer settings with custom user-agents list +func NewWithCustomList(userAgents []string) *UARand { + return &UARand{ + Randomizer: rand.New(rand.NewSource(time.Now().UnixNano())), + UserAgents: userAgents, + mutex: sync.Mutex{}, + } } diff --git a/vendor/github.com/corpix/uarand/useragents.go b/vendor/github.com/corpix/uarand/useragents.go index aa8e44cc9..fd2fb4003 100644 --- a/vendor/github.com/corpix/uarand/useragents.go +++ b/vendor/github.com/corpix/uarand/useragents.go @@ -3,827 +3,1285 @@ package uarand var ( // UserAgents is a list of browser and bots user agents. UserAgents = []string{ - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.6 (Change: )", + "'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.39 (KHTML, like Gecko) Chrome/89.0.4389.111 Safari/537.39'", + "Adobe Application Manager 2.0", + "AdsBot-Google ( http://www.google.com/adsbot.html)", + "AndroidDownloadManager/5.1 (Linux; U; Android 5.1; Z820 Build/LMY47D)", "Avant Browser/1.2.789rel1 (http://www.avantbrowser.com)", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5", - "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27", - "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.120 Safari/535.2", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/18.6.872.0 Safari/535.2 UNTRUSTED/1.0 3gpp-gba UNTRUSTED/1.0", - "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", - "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", - "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB5", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)", - "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0a2) Gecko/20110622 Firefox/6.0a2", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", - "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0", - "Mozilla/5.0 (Windows NT 6.0; rv:14.0) Gecko/20100101 Firefox/14.0.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1", - "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0) Gecko/16.0 Firefox/16.0", - "Mozilla/5.0 (Windows NT 6.2; rv:19.0) Gecko/20121129 Firefox/19.0", - "Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Maxthon 2.0)", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b4pre) Gecko/20100815 Minefield/4.0b4pre", - "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0 )", - "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90)", - "Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a", + "Baiduspider ( http://www.baidu.com/search/spider.htm)", + "BlackBerry7100i/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/103", + "BlackBerry7520/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/5.0.3.3 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)", + "BlackBerry8300/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/107 UP.Link/6.2.3.15.0", + "BlackBerry8320/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/100", + "BlackBerry8330/4.3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/105", + "BlackBerry9000/4.6.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102", + "BlackBerry9530/4.7.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102 UP.Link/6.3.1.20.0", + "BlackBerry9700/5.0.0.351 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/123", + "Bloglines/3.1 (http://www.bloglines.com)", + "CSSCheck/1.2.2", + "Dalvik/2.1.0 (Linux; U; Android 8.0.0; SM-A520F Build/R16NW)", + "DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", + "DoCoMo/2.0 SH901iC(c100;TB;W24H12)", + "Download Demon/3.5.0.11", + "ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)", + "ELinks (0.4pre5; Linux 2.6.10-ac7 i686; 80x33)", + "ELinks/0.12~pre5-4", + "ELinks/0.9.3 (textmode; Linux 2.6.9-kanotix-8 i686; 127x41)", + "EmailWolf 1.00", + "FAST-WebCrawler/3.8 (crawler at trd dot overture dot com; http://www.alltheweb.com/help/webmaster/crawler)", + "Facebot", + "FeedFetcher-Google; ( http://www.google.com/feedfetcher.html)", + "Gaisbot/3.0 (robot@gais.cs.ccu.edu.tw; http://gais.cs.ccu.edu.tw/robot.php)", + "Googlebot-Image/1.0", + "Googlebot-News", + "Googlebot-Video/1.0", + "Googlebot/2.1 ( http://www.googlebot.com/bot.html)", + "Gregarius/0.5.2 ( http://devlog.gregarius.net/docs/ua)", + "Gulper Web Bot 0.2.4 (www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/Link/GulperBot)", + "HTC-ST7377/1.59.502.3 (67150) Opera/9.50 (Windows NT 5.1; U; en) UP.Link/6.3.1.17.0", + "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "HTMLParser/1.6", + "Java/1.6.0_13", + "Jigsaw/2.2.5 W3C_CSS_Validator_JFouffa/2.0", + "Konqueror/3.0-rc4; (Konqueror/3.0-rc4; i686 Linux;;datecode)", + "LG-GC900/V10a Obigo/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1", + "LG-LX550 AU-MIC-LX550/2.0 MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 196x84)", + "Links (2.1pre15; Linux 2.4.26 i686; 158x61)", + "Links (2.3pre1; Linux 2.6.38-8-generic x86_64; 170x48)", + "Links/0.9.1 (Linux 2.4.24; i386;)", + "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/0.8.12", + "Lynx/2.8.7dev.4 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8d", + "MOT-L7v/08.B7.5DR MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", + "MOT-V177/0.1.75 UP.Browser/6.2.3.9.c.12 (GUI) MMP/2.0 UP.Link/6.3.1.13.0", + "MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0", + "MOTORIZR-Z8/46.00.00 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 356) Opera 8.65 [it] UP.Link/6.3.0.0.0", + "MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23", + "Mediapartners-Google", + "Microsoft URL Control - 6.00.8862", + "Midori/0.1.10 (X11; Linux i686; U; en-us) WebKit/(531).(2)", + "MobileSafari/600.1.4 CFNetwork/711.1.12 Darwin/14.0.0", + "Mozilla/1.22 (compatible; MSIE 5.01; PalmOS 3.0) EudoraWeb 2.1", + "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)", "Mozilla/2.02E (Win95; U)", + "Mozilla/3.0 (compatible; NetPositive/2.1.1; BeOS)", "Mozilla/3.01Gold (Win95; I)", - "Mozilla/4.8 [en] (Windows NT 5.1; U)", - "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko Netscape/7.1 (ax)", - "Opera/7.50 (Windows XP; U)", - "Opera/7.50 (Windows ME; U) [en]", - "Opera/7.51 (Windows NT 5.1; U) [en]", + "Mozilla/4.0 (PDA; PalmOS/sony/model prmr/Revision:1.1.54 (en)) NetFront/3.0", + "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)", + "Mozilla/4.0 (compatible; Dillo 3.0)", + "Mozilla/4.0 (compatible; GoogleToolbar 4.0.1019.5266-big; Windows XP 5.1; MSIE 6.0.2900.2180)", + "Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 600x800)", + "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; MDA Pro/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1)", + "Mozilla/4.0 (compatible; MSIE 5.0; Series80/2.0 Nokia9500/4.51 Profile/MIDP-2.0 Configuration/CLDC-1.1)", + "Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)", + "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90)", + "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0 )", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) Sprint:PPC6800", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) XV6800", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile6.0)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; en) Opera 8.0", - "Opera/9.25 (Windows NT 6.0; U; en)", - "Opera/9.80 (Windows NT 5.2; U; en) Presto/2.2.15 Version/10.10", - "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10", - "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.7.62 Version/11.01", - "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00", - "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", - "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.2b) Gecko/20021001 Phoenix/0.2", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090825 SeaMonkey/1.1.18", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.17) Gecko/20110123 (like Firefox/3.x) SeaMonkey/2.0.12", - "Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", - "Mozilla/5.0 (Windows; U; ; en-NZ) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.8.0", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", + "Mozilla/4.0 (compatible; MSIE 6.0; j2me) ReqwirelessWeb/3.5", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; Avant Browser; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Beamrise/17.2.0.9 Chrome/17.0.939.0 Safari/535.8", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Maxthon 2.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)", + "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 6600;452) Opera 6.20 [en-US]", + "Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)", + "Mozilla/4.8 [en] (Windows NT 5.1; U)", + "Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)", + "Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4", + "Mozilla/5.0 (Android 4.2; rv:19.0) Gecko/20121129 Firefox/19.0", + "Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0", + "Mozilla/5.0 (Android; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", + "Mozilla/5.0 (Android; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", + "Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0", + "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.1.0.2342 Mobile Safari/537.10+", + "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.9a1) Gecko/20060702 SeaMonkey/1.5a", + "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1 (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1", + "Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.267 Mobile Safari/534.11+", + "Mozilla/5.0 (Linux U; en-US) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) Version/4.0 Kindle/3.0 (screen 600x800; rotate)", + "Mozilla/5.0 (Linux; Android 10; AC2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; BLA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; CLT-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; DL1036) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ELE-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Galaxy J2 Pro Build/QQ3A.200805.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/85.0.4183.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; HMA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; LYA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2003J15SC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2006C3LII) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2007J20CI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2010J19SI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; MAR-LX1B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; MAR-LX1M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; MI 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONE A2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; POCO F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; POCOPHONE F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-N980F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.2 Chrome/92.0.4515.166 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-A315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-J810G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-M307F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-M315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.50 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-N960F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; TECNO KE5 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; VOG-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; VOG-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; YAL-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; itel L5006C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; moto e(7) plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; moto e(7)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; moto g(7) plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; 100011886A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; AC2001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; AC2001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; BL5000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; CPH2373) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; DN2101) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; GM1910) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; GM1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; IN2025) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; IV2201) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; KB2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; LM-V500N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; LM-V500N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; LM-V510N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36 EdgA/101.0.1210.32", + "Mozilla/5.0 (Linux; Android 11; M2003J15SC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; M2007J3SY) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; M2101K6G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; MVK-T2101) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.116 Safari/537.36 EdgA/45.09.4.5083", + "Mozilla/5.0 (Linux; Android 11; Mi 9 SE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Mi A3 Build/RKQ1.200903.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.41 YaBrowser/22.1.0.194 (lite) Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Mi Note 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; ONEPLUS A6000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 2 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4812.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1851) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1921) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1921) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1931) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2027) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2101) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2117) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2161) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36 OPR/68.3.3557.64528", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 8T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 9 Pro Max) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36 OPR/68.3.3557.64528", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-A5070) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/17.0 Chrome/96.0.4664.104 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A115F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A225F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A326U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A415F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A505FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A505G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A526U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-G980F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-M315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-M317F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-M515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-T500) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.73 Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; moto e20) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; moto g(40) fusion) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; motorola edge 20 fusion) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; vivo 1906) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; ASUS_I005DA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36 EdgA/100.0.1185.50", + "Mozilla/5.0 (Linux; Android 12; I2126) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; LE2121) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; M2101K6G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 6 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; RMX3081) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SAMSUNG SM-G990E) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/17.0 Chrome/96.0.4664.104 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SAMSUNG SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.2 Chrome/92.0.4515.166 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-A525F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-F926B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G780G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G780G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Mobile Safari/537.36 EdgA/101.0.1210.39", + "Mozilla/5.0 (Linux; Android 12; SM-G781U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G970F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G970U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36 EdgA/100.0.1185.50", + "Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G991U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G998U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N770F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Mobile Safari/537.36 EdgA/101.0.1210.39", + "Mozilla/5.0 (Linux; Android 12; SM-N975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N985F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N9860) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N986U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-P615) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; motorola edge 20 pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; vivo 1907) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.1.2; SHV-E250S Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.82 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.3; SPH-L710 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; LGMS323 Build/KOT49I.MS32310b) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-G900A Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; SM-T230NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.135 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.4; XT1032 Build/KXB21.14-L1.61) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.0.1; SCH-R970 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.1.1; Coolpad 3622A Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", + "Mozilla/5.0 (Linux; Android 5.1; C6740N Build/LMY47O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.1; Lenovo TAB 2 A8-50LC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Safari/537.36 OPR/66.2.3445.62346", + "Mozilla/5.0 (Linux; Android 6.0.1; SM-G900H Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.89 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; LG-D850 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.97 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; HUAWEI CAN-L11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; HUAWEI CAN-L11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; LG-H918 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; LGL84VL Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; LGUS997 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; Moto G (5) Plus Build/NPNS25.137-35-5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; Nexus 9 Build/NRD90R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G925R6 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; SM-N920C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; ZE520KL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; BBB100-1 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; CPH1725 Build/N6F26Q; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/360.0.0.10.113;]", + "Mozilla/5.0 (Linux; Android 7.1.1; CPH1729) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; CPH1729) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; Coolpad 3632A Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; XT1710-02 Build/NDS26.74-36) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.2; Nexus 6P Build/N2G48C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.2; Pixel Build/NHG47N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; F8331) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; HWI-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; LG-US998) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36 OPR/68.3.3557.64528", + "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SAMSUNG SM-G935F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/12.1 Chrome/79.0.3945.136 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-A520F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-A605G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-G930F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-G935F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; WAS-LX1A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.1.0; TECNO KA7O Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.120 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.1.0; TECNO LA7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; ASUS_X00TD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; ONEPLUS A6003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; POT-LX2J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi 4 Prime) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi Note 5 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi Note 8T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.2 Chrome/92.0.4515.166 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; SM-G950F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; VTR-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Z6201V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; ZTE Blade A7 2020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; moto g(6) plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522 (KHTML, like Gecko) Safari/419.3", + "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", + "Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", + "Mozilla/5.0 (Linux; U; Android 1.5; de-ch; HTC Hero Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; de-de; Galaxy Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; de-de; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 FirePHP/0.3", + "Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile_G2_Touch Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; SPH-M900 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; T-Mobile G1 Build/CRB43) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari 525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; htc_bahamas Build/CRB17) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; sdk Build/CUPCAKE) AppleWebkit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; fr-fr; GT-I5700 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.6; en-us; SonyEricssonX10i Build/R1AA056) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.6; es-es; SonyEricssonX10i Build/R1FA016) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 10; Infinix X688B Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 OPR/62.5.2254.61243", + "Mozilla/5.0 (Linux; U; Android 10; zh-Hans-CN; SPN-AL00 Build/HUAWEISPN-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.4.9.201 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 10; zh-Hans-CN; YAL-AL50 Build/HUAWEIYAL-AL50) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.6.6.211 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 11; ru-ru; Mi 9T Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.116 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.1.0-gn", + "Mozilla/5.0 (Linux; U; Android 11; zh-CN; M2012K11AC Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.4.8.200 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 11; zh-CN; V2121A Build/RP1A.200720.012) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.4.9.201 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 2.0.1; de-de; Milestone Build/SHOLS_U2_01.14.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.1-update1; de-de; HTC Desire 1.19.161.5 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.1; en-us; HTC Legend Build/cupcake) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.3.3; en-us ; LS670 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1/UCBrowser/8.6.1.262/145/355", + "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; BNTV250 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7100 Build/HRI83) AppleWebkit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", + "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.0.3; de-de; Galaxy S II Build/GRJ22) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true", + "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; LG-P870/P87020d Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.1; en-us; sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.1 Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.2; en-us; sdk Build/MR1) AppleWebKit/535.19 (KHTML, like Gecko) Version/4.2 Safari/535.19", + "Mozilla/5.0 (Linux; U; Android 4.3; en-us; sdk Build/MR1) AppleWebKit/536.23 (KHTML, like Gecko) Version/4.3 Mobile Safari/536.23", + "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; GT-P5210 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 7.1.1; en-us; CPH1801 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.88 Mobile Safari/537.36 HeyTapBrowser/15.8.4.1", + "Mozilla/5.0 (Linux; U; Android 8.0.0; zh-cn; Mi Note 2 Build/OPR1.170623.032) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/MiuiBrowser/10.1.1", + "Mozilla/5.0 (Linux; arm; Android 10; HRY-LX1T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 YaBrowser/22.3.1.87.00 SA/3 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; webOS/2.2.4; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) webOSBrowser/221.56 Safari/534.6 Pre/3.0", + "Mozilla/5.0 (MSIE 9.0; Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14931", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:55.0) Gecko/20100101 Firefox/55.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre Camino/2.2a1pre", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:20.0) Gecko/20100101 Firefox/20.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:47.0) Gecko/20100101 Firefox/47.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 1083) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4853.129 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 OPR/28.0.1750.51", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.82 Safari/537.36 OPR/29.0.1795.41", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.105 Safari/537.36 Vivaldi/1.0.162.9", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2859.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.49 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.8 (KHTML, like Gecko) Version/10.1 Safari/603.1.30", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.75", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Flipboard/4.2.142", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4692.56 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4889.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.162 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.57 Whale/3.14.133.23 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4950.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4950.2 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.26", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.32", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.4972.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.27 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.49 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5056.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Safari/537.36 ArchiveBox/0.6.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.42", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.136 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.865 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.866 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.75", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko)", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.54 Safari/535.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.26.17 (KHTML like Gecko) Version/6.0.2 Safari/536.26.17", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.31 (KHTML like Gecko) Chrome/26.0.1410.63 Safari/537.31", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.78.1 (KHTML like Gecko) Version/7.0.6 Safari/537.78.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.60", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.41 YaBrowser/21.2.0.2458 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.14) Gecko/20110218 AlexaToolbar/alxf-2.0 Firefox/3.6.14", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7;en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.302.2 Safari/532.8", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.464.0 Safari/534.3", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; de-de) AppleWebKit/534.15 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7; en-us) AppleWebKit/534.20.8 (KHTML, like Gecko) Version/5.1 Safari/534.20.8", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0.112941", + "Mozilla/5.0 (Macintosh; U; Mac OS X Mach-O; en-US; rv:2.0a) Gecko/20040614 Firefox/3.0.0", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/85.8", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.15", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/312.5 (KHTML, like Gecko) Safari/312.3", + "Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", + "Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", + "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", + "Mozilla/5.0 (MeeGo; NokiaN950-00/00) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", + "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 929) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537", + "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Arora/0.11.0 Safari/533.3", + "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) QupZilla/1.3.1 Safari/533.3", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20100101 Firefox/10.0.12", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20130108 Firefox/10.0.12 SeaMonkey/2.7.2", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0 SeaMonkey/2.21", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0 SeaMonkey/2.28", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0 SeaMonkey/2.42.9esr", + "Mozilla/5.0 (PLAYSTATION 3; 1.10)", + "Mozilla/5.0 (PLAYSTATION 3; 2.00)", + "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", + "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebkit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC6-01/011.010; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.2 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC7-00/012.003; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE6-00/021.002; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.16 Mobile Safari/533.4 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE7-00/010.016; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/014.002; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.4 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaX7-00/021.004; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.21 Mobile Safari/533.4 3gpp-gba", + "Mozilla/5.0 (SymbianOS 9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", + "Mozilla/5.0 (SymbianOS/9.1; U; de) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es50", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es65", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es70", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia5700/3.27; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia6120c/3.70; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.2.3.18.0", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaN95/10.0.018; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.3.0.0.0", + "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", + "Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 SonyEricssonP100/01; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 Safari/525", + "Mozilla/5.0 (Unknown; U; UNIX BSD/SYSV system; C -) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.2", + "Mozilla/5.0 (Unknown; UNIX BSD/SYSV system) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.7.0 Safari/538.1", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.91 Safari/537.36 Vivaldi/1.92.917.39", + "Mozilla/5.0 (Windows NT 10.0; ARM; Lumia 950 Dual SIM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.59", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.136 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 UBrowser/5.6.13705.206 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 OPR/36.0.2130.46", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2869.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.90 Safari/537.36 Vivaldi/1.4.589.11", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 AOL/11.0 AOLBUILD/11.0.1305 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3191.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0", - "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240", - "Mozilla/5.0 (MSIE 9.0; Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14931", - "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063", - "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20130401 Firefox/21.0", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0", - "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:35.0) Gecko/20100101 Firefox/35.0", - "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0", - "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0", - "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3883.400 QQBrowser/10.8.4559.400", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.3161 SLBChan/10", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.145 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.119 YaBrowser/22.3.0.2539 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.4.734 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.4.3000 Chrome/47.0.2526.73 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko", + "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 AtContent/96.5.9594.95", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.50", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.59", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.136 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.143 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.143 Safari/537.36 Edg/100.0.1185.57", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.147 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.151 Whale/3.14.134.62 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36 Edg/100.0.1185.39", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4950.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.26 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.32", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Config/99.2.4111.12", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.40 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5030.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5042.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2869.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3191.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 HBPC/12.0.0.300", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.113 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4624.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.846.563 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.119 Safari/537.36 Edg/98.0.1108.76", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.4.731 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.43", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 OPR/85.0.4341.22", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.46", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.72", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.75", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.79", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.79 (Edition Campaign 76)", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.100.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko, Foregenix) Chrome/91.0.4472.77 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0", - "iTunes/9.0.2 (Windows; N)", - "Mozilla/5.0 (compatible; Konqueror/4.5; Windows) KHTML/4.5.4 (like Gecko)", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Maxthon/3.0.8.2 Safari/533.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML like Gecko) Maxthon/4.0.0.2000 Chrome/22.0.1229.79 Safari/537.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.4.3000 Chrome/47.0.2526.73 Safari/537.36", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", - "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)", - "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)", - "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)", - "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0", - "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", - "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0", + "Mozilla/5.0 (Windows NT 10.0; rv:45.9) Gecko/20100101 Goanna/3.2 Firefox/45.9 PaleMoon/27.4.0", + "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36", + "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 YaBrowser/17.3.0.1785 Yowser/2.5 Safari/537.36", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) MxBrowser/4.5.10.7000 Chrome/30.0.1551.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko", - "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko", - "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.12 Safari/537.36 OPR/14.0.1116.4", + "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0", + "Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", + "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", + "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.120 Safari/535.2", + "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Windows NT 6.0; rv:14.0) Gecko/20100101 Firefox/14.0.1", + "Mozilla/5.0 (Windows NT 6.0; rv:36.0) Gecko/20100101 Firefox/36.0 SeaMonkey/2.33.1", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/18.6.872.0 Safari/535.2 UNTRUSTED/1.0 3gpp-gba UNTRUSTED/1.0", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.29 Safari/537.36 OPR/15.0.1147.24 (Edition Next)", - "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.855 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.71 (KHTML like Gecko) WebVideo/1.0.1.10 Version/7.0 Safari/537.71", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Beamrise/17.2.0.9 Chrome/17.0.939.0 Safari/535.8", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML like Gecko) Maxthon/4.0.0.2000 Chrome/22.0.1229.79 Safari/537.1", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/89.0.4389.105 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.12 Safari/537.36 OPR/14.0.1116.4", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36 OPR/19.0.1326.56", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 OPR/20.0.1387.91", - "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36 OPR/28.0.1750.40", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.94.2 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 OPR/36.0.2130.46", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55", - "Mozilla/5.0 (Windows NT 10.0; rv:45.9) Gecko/20100101 Goanna/3.2 Firefox/45.9 PaleMoon/27.4.0", - "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5", - "Mozilla/5.0 (Windows; U; Windows NT 6.2; es-US ) AppleWebKit/540.0 (KHTML like Gecko) Version/6.0 Safari/8900.00", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.71 (KHTML like Gecko) WebVideo/1.0.1.10 Version/7.0 Safari/537.71", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20120422 Firefox/12.0 SeaMonkey/2.9", - "Mozilla/5.0 (Windows NT 6.0; rv:36.0) Gecko/20100101 Firefox/36.0 SeaMonkey/2.33.1", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 UBrowser/5.6.13705.206 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.94.2 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.90 Safari/537.36 Vivaldi/1.4.589.11", - "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.91 Safari/537.36 Vivaldi/1.92.917.39", - "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 YaBrowser/17.3.0.1785 Yowser/2.5 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre Camino/2.2a1pre", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.302.2 Safari/532.8", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.464.0 Safari/534.3", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.54 Safari/535.2", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", - "Mozilla/5.0 (Macintosh; U; Mac OS X Mach-O; en-US; rv:2.0a) Gecko/20040614 Firefox/3.0.0", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.14) Gecko/20110218 AlexaToolbar/alxf-2.0 Firefox/3.6.14", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0", - "Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.15", - "Opera/9.0 (Macintosh; PPC Mac OS X; U; en)", - "Opera/9.20 (Macintosh; Intel Mac OS X; U; en)", - "Opera/9.64 (Macintosh; PPC Mac OS X; U; en) Presto/2.1.1", - "Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.6.30 Version/10.61", - "Opera/9.80 (Macintosh; Intel Mac OS X 10.4.11; U; en) Presto/2.7.62 Version/11.00", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/85.8", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/312.5 (KHTML, like Gecko) Safari/312.3", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.31 (KHTML like Gecko) Chrome/26.0.1410.63 Safari/537.31", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 1083) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2859.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.49 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:20.0) Gecko/20100101 Firefox/20.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:47.0) Gecko/20100101 Firefox/47.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:55.0) Gecko/20100101 Firefox/55.0", - "iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)", - "iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0.112941", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0", - "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 OPR/28.0.1750.51", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.82 Safari/537.36 OPR/29.0.1795.41", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; de-de) AppleWebKit/534.15 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7; en-us) AppleWebKit/534.20.8 (KHTML, like Gecko) Version/5.1 Safari/534.20.8", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.26.17 (KHTML like Gecko) Version/6.0.2 Safari/536.26.17", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.78.1 (KHTML like Gecko) Version/7.0.6 Safari/537.78.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.8 (KHTML, like Gecko) Version/10.1 Safari/603.1.30", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.105 Safari/537.36 Vivaldi/1.0.162.9", - "ELinks (0.4pre5; Linux 2.6.10-ac7 i686; 80x33)", - "ELinks/0.9.3 (textmode; Linux 2.6.9-kanotix-8 i686; 127x41)", - "ELinks/0.12~pre5-4", - "Links/0.9.1 (Linux 2.4.24; i386;)", - "Links (2.1pre15; Linux 2.4.26 i686; 158x61)", - "Links (2.3pre1; Linux 2.6.38-8-generic x86_64; 170x48)", - "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/0.8.12", - "w3m/0.5.1", - "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.4 (KHTML, like Gecko) Chrome/4.0.237.0 Safari/532.4 Debian", - "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.277.0 Safari/532.8", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.309.0 Safari/532.9", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/9.1.0.0 Safari/540.0", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.613.0 Safari/534.15", - "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.613.0 Chrome/10.0.613.0 Safari/534.15", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1", - "Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Ubuntu/11.04 Chromium/14.0.825.0 Chrome/14.0.825.0 Safari/535.1", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.120 Chrome/15.0.874.120 Safari/535.2", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", - "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Epiphany/1.2.5", - "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8", - "Mozilla/5.0 (X11; U; Linux x86_64; sv-SE; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.10 (karmic) Firefox/3.0.11", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090803 Ubuntu/9.04 (jaunty) Shiretoko/3.5.2", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5) Gecko/20091107 Firefox/3.5.5", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Linux Mint/8 (Helena) Firefox/3.5.3", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9", - "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8", - "Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre", - "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (X11; Linux x86_64; rv:2.2a1pre) Gecko/20100101 Firefox/4.2a1pre", - "Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20100101 Firefox/6.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:7.0a1) Gecko/20110623 Firefox/7.0a1", - "Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0", - "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1", - "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Galeon/1.3.14", - "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.8.1.13) Gecko/20080313 Iceape/1.1.9 (Debian-1.1.9-5)", - "Mozilla/5.0 (X11; U; Linux i686; pt-PT; rv:1.9.2.3) Gecko/20100402 Iceweasel/3.6.3 (like Firefox/3.6.3) GTB7.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0 Iceweasel/5.0", - "Mozilla/5.0 (X11; Linux i686; rv:6.0a2) Gecko/20110615 Firefox/6.0a2 Iceweasel/6.0a2", - "Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20100101 Firefox/14.0.1 Iceweasel/14.0.1", - "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120724 Debian Iceweasel/15.02", - "Konqueror/3.0-rc4; (Konqueror/3.0-rc4; i686 Linux;;datecode)", - "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8-gentoo-r3; X11;", - "Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.30-7.dmz.1-liquorix-686; X11) KHTML/3.5.10 (like Gecko) (Debian package 4:3.5.10.dfsg.1-1 b1)", - "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; en_US) KHTML/3.5.6 (like Gecko) (Kubuntu)", - "Mozilla/5.0 (X11; Linux x86_64; en-US; rv:2.0b2pre) Gecko/20100712 Minefield/4.0b2pre", - "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Debian/1.6-7", - "MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23", - "Opera/9.64 (X11; Linux i686; U; Linux Mint; nb) Presto/2.1.1", - "Opera/9.80 (X11; Linux i686; U; en) Presto/2.2.15 Version/10.10", - "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) QupZilla/1.2.0 Safari/534.34", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.17) Gecko/20110123 SeaMonkey/2.0.12", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)", - "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.1", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b4pre) Gecko/20100815 Minefield/4.0b4pre", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0a2) Gecko/20110622 Firefox/6.0a2", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0", + "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20130401 Firefox/21.0", + "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", + "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", + "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 635) like Gecko", + "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 920) like Geckoo", + "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36 OPR/28.0.1750.40", + "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0) Gecko/16.0 Firefox/16.0", + "Mozilla/5.0 (Windows NT 6.2; rv:19.0) Gecko/20121129 Firefox/19.0", + "Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0", + "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", + "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49", + "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0", + "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0", + "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko", + "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 630) like Gecko", + "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) like Gecko", + "Mozilla/5.0 (Windows; U; ; en-NZ) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.8.0", + "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko Netscape/7.1 (ax)", + "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.2b) Gecko/20021001 Phoenix/0.2", + "Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.800) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090825 SeaMonkey/1.1.18", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)", + "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9", + "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", + "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.6 (Change: )", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Maxthon/3.0.8.2 Safari/533.1", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB5", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.17) Gecko/20110123 (like Firefox/3.x) SeaMonkey/2.0.12", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14", + "Mozilla/5.0 (Windows; U; Windows NT 6.2; es-US ) AppleWebKit/540.0 (KHTML like Gecko) Version/6.0 Safari/8900.00", + "Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a", + "Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; CentOS; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0", + "Mozilla/5.0 (X11; CrOS aarch64 14388.61.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.107 Safari/537.36", + "Mozilla/5.0 (X11; CrOS aarch64 14526.89.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.56 Safari/537.4", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1478.0 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 13982.88.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.162 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14469.59.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.94 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14526.89.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14526.89.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14588.98.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.59 Safari/537.36", "Mozilla/5.0 (X11; CrOS x86_64 5841.83.0) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.138 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.125 Safari/537.36", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2166.2 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36", - "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36", + "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2876.0 Safari/537.36", - "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3187.0 Safari/537.366", "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3178.0 Safari/537.36", + "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/535.22+ (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/535.22+ Epiphany/2.30.6", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/536.5 (KHTML like Gecko) Chrome/19.0.1084.56 Safari/536.5", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", + "Mozilla/5.0 (X11; FreeBSD amd64; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (X11; FreeBSD amd64; rv:54.0) Gecko/20100101 Firefox/54.0", + "Mozilla/5.0 (X11; FreeBSD i386; rv:28.0) Gecko/20100101 Firefox/28.0 SeaMonkey/2.25", + "Mozilla/5.0 (X11; Linux 3.8-6.dmz.1-liquorix-686) KHTML/4.8.4 (like Gecko) Konqueror/4.8", + "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3187.0 Safari/537.366", + "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) QupZilla/1.2.0 Safari/534.34", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Ubuntu/11.04 Chromium/14.0.825.0 Chrome/14.0.825.0 Safari/535.1", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.120 Chrome/15.0.874.120 Safari/535.2", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/33.0.1750.152 Chrome/33.0.1750.152 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1478.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2166.2 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36 OPR/40.0.2308.62", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/51.0.2704.79 Chrome/51.0.2704.79 Safari/537.36", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/60.0.3112.78 Chrome/60.0.3112.78 Safari/537.36", - "Mozilla/4.0 (compatible; Dillo 3.0)", - "Mozilla/5.0 (X11; U; Linux i686; en-us) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) lt-GtkLauncher", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.32 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.32 Epiphany/3.8.2", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/604.1 (KHTML, like Gecko) Version/11.0 Safari/604.1 Ubuntu/17.04 (3.24.1-0ubuntu1) Epiphany/3.24.1", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.6 Safari/538.1", + "Mozilla/5.0 (X11; Linux i686; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", + "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0", + "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20120502 Firefox/12.0 SeaMonkey/2.9.1", + "Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20100101 Firefox/14.0.1 Iceweasel/14.0.1", "Mozilla/5.0 (X11; Linux i686; rv:16.0) Gecko/20100101 Firefox/16.0", - "Mozilla/5.0 (X11; U; Linux i686; rv:19.0) Gecko/20100101 Slackware/13 Firefox/19.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0", + "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre", "Mozilla/5.0 (X11; Linux i686; rv:20.0) Gecko/20100101 Firefox/20.0", "Mozilla/5.0 (X11; Linux i686; rv:25.0) Gecko/20100101 Firefox/25.0", "Mozilla/5.0 (X11; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0", "Mozilla/5.0 (X11; Linux i686; rv:32.0) Gecko/20100101 Firefox/32.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", - "Mozilla/5.0 (X11; CentOS; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0", "Mozilla/5.0 (X11; Linux i686; rv:40.0) Gecko/20100101 Firefox/40.0", "Mozilla/5.0 (X11; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0", "Mozilla/5.0 (X11; Linux i686; rv:46.0) Gecko/20100101 Firefox/46.0", "Mozilla/5.0 (X11; Linux i686; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Galeon/2.0.6 (Ubuntu 2.0.6-2)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.16) Gecko/20080716 (Gentoo) Galeon/2.0.6", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.13) Gecko/20100916 Iceape/2.0.8", - "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 Iceweasel/19.0.2", - "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1", - "Mozilla/5.0 (compatible; Konqueror/4.2; Linux) KHTML/4.2.4 (like Gecko) Slackware/13.0", - "Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.1 (like Gecko) Fedora/4.3.1-3.fc11", - "Mozilla/5.0 (compatible; Konqueror/4.4; Linux) KHTML/4.4.1 (like Gecko) Fedora/4.4.1-1.fc12", - "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", - "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", - "Mozilla/5.0 (X11; Linux 3.8-6.dmz.1-liquorix-686) KHTML/4.8.4 (like Gecko) Konqueror/4.8", - "Mozilla/5.0 (X11; Linux) KHTML/4.9.1 (like Gecko) Konqueror/4.9", + "Mozilla/5.0 (X11; Linux i686; rv:49.0) Gecko/20100101 Firefox/49.0 SeaMonkey/2.46", + "Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20100101 Firefox/6.0", + "Mozilla/5.0 (X11; Linux i686; rv:6.0a2) Gecko/20110615 Firefox/6.0a2 Iceweasel/6.0a2", + "Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) konqueror/4.14.10 Safari/537.21", - "Midori/0.1.10 (X11; Linux i686; U; en-us) WebKit/(531).(2)", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a3pre) Gecko/20070330", - "Opera/9.80 (X11; Linux i686) Presto/2.12.388 Version/12.16", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.166 Safari/537.36 OPR/20.0.1396.73172", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.32 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.32 Epiphany/3.8.2", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.125 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.50", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.59", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.147 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.4997.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.9999.0 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.166 Safari/537.36 OPR/20.0.1396.73172", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36 OPR/40.0.2308.62", - "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.8.0.2965AT", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.6 Safari/538.1", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.9.0 Safari/538.1", - "Mozilla/5.0 (X11; Linux i686; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", - "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20120502 Firefox/12.0 SeaMonkey/2.9.1", - "Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", - "Mozilla/5.0 (X11; Linux i686; rv:49.0) Gecko/20100101 Firefox/49.0 SeaMonkey/2.46", - "Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0", - "Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.2.3) Gecko/20100406 Firefox/3.6.3 (Swiftfox)", - "Uzbl (Webkit 1.3) (Linux i686 [i686])", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 Vivaldi/1.0.344.37", - "ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)", - "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 196x84)", - "Lynx/2.8.7dev.4 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8d", - "w3m/0.5.1", - "Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.207.0 Safari/532.0", - "Mozilla/5.0 (X11; U; OpenBSD i386; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.359.0 Safari/533.3", - "Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16", - "Mozilla/5.0 (X11; U; SunOS sun4m; en-US; rv:1.4b) Gecko/20030517 Mozilla Firebird/0.6", - "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.9.1b3) Gecko/20090429 Firefox/3.1b3", - "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.1) Gecko/20090702 Firefox/3.5", - "Mozilla/5.0 (X11; U; FreeBSD i386; de-CH; rv:1.9.2.8) Gecko/20100729 Firefox/3.6.8", - "Mozilla/5.0 (X11; FreeBSD amd64; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040406 Galeon/1.3.15", - "Mozilla/5.0 (compatible; Konqueror/3.5; NetBSD 4.0_RC3; X11) KHTML/3.5.7 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/3.5; SunOS) KHTML/3.5.1 (like Gecko)", - "Mozilla/5.0 (X11; U; FreeBSD; i386; en-US; rv:1.7) Gecko", - "Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)", - "Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)", - "Mozilla/5.0 (Unknown; U; UNIX BSD/SYSV system; C -) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.2", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/536.5 (KHTML like Gecko) Chrome/19.0.1084.56 Safari/536.5", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", - "Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36", - "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36", - "Mozilla/5.0 (X11; NetBSD x86; en-us) AppleWebKit/666.6+ (KHTML, like Gecko) Chromium/20.0.0000.00 Chrome/20.0.0000.00 Safari/666.6+", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/535.22+ (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/535.22+ Epiphany/2.30.6", - "Mozilla/5.0 (X11; U; OpenBSD arm; en-us) AppleWebKit/531.2 (KHTML, like Gecko) Safari/531.2 Epiphany/2.30.0", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2876.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.3 Chrome/87.0.4280.144 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/33.0.1750.152 Chrome/33.0.1750.152 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) obsidian/0.14.6 Chrome/100.0.4896.75 Electron/18.0.4 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.56 Safari/537.4", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.9.0 Safari/538.1", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/10.0 Safari/602.1", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/604.1 (KHTML, like Gecko) Version/11.0 Safari/604.1 Ubuntu/17.04 (3.24.1-0ubuntu1) Epiphany/3.24.1", + "Mozilla/5.0 (X11; Linux x86_64; en-US; rv:2.0b2pre) Gecko/20100712 Minefield/4.0b2pre", + "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", + "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120724 Debian Iceweasel/15.02", + "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 Iceweasel/19.0.2", + "Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; Linux x86_64; rv:2.2a1pre) Gecko/20100101 Firefox/4.2a1pre", + "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0", + "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1", + "Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0 Iceweasel/5.0", + "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", + "Mozilla/5.0 (X11; Linux x86_64; rv:7.0a1) Gecko/20110623 Firefox/7.0a1", + "Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0", + "Mozilla/5.0 (X11; Linux) KHTML/4.9.1 (like Gecko) Konqueror/4.9", "Mozilla/5.0 (X11; NetBSD amd64; rv:16.0) Gecko/20121102 Firefox/16.0", - "Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0", "Mozilla/5.0 (X11; NetBSD amd64; rv:30.0) Gecko/20100101 Firefox/30.0", + "Mozilla/5.0 (X11; NetBSD x86; en-us) AppleWebKit/666.6+ (KHTML, like Gecko) Chromium/20.0.0000.00 Chrome/20.0.0000.00 Safari/666.6+", + "Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36", + "Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0", "Mozilla/5.0 (X11; OpenBSD amd64; rv:30.0) Gecko/20100101 Firefox/30.0", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", - "Mozilla/5.0 (X11; FreeBSD amd64; rv:54.0) Gecko/20100101 Firefox/54.0", - "Mozilla/5.0 (compatible; Konqueror/4.1; DragonFly) KHTML/4.1.4 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/4.5; NetBSD 5.0.2; X11; amd64; en_US) KHTML/4.5.4 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)", - "Mozilla/5.0 (X11; U; NetBSD amd64; en-US; rv:1.9.2.15) Gecko/20110308 Namoroka/3.6.15", - "NetSurf/1.2 (NetBSD; amd64)", - "Opera/9.80 (X11; FreeBSD 8.1-RELEASE i386; Edition Next) Presto/2.12.388 Version/12.10", - "Mozilla/5.0 (Unknown; UNIX BSD/SYSV system) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.7.0 Safari/538.1", - "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1.12) Gecko/20080303 SeaMonkey/1.1.8", - "Mozilla/5.0 (X11; FreeBSD i386; rv:28.0) Gecko/20100101 Firefox/28.0 SeaMonkey/2.25", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.800) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0", - "Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)", - "Mozilla/1.22 (compatible; MSIE 5.01; PalmOS 3.0) EudoraWeb 2.1", - "Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36", + "Mozilla/5.0 (X11; U; FreeBSD i386; de-CH; rv:1.9.2.8) Gecko/20100729 Firefox/3.6.8", + "Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.207.0 Safari/532.0", + "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040406 Galeon/1.3.15", + "Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16", + "Mozilla/5.0 (X11; U; FreeBSD; i386; en-US; rv:1.7) Gecko", + "Mozilla/5.0 (X11; U; Linux arm7tdmi; rv:1.8.1.11) Gecko/20071130 Minimo/0.025", "Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1", - "Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", - "Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0", - "Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016", "Mozilla/5.0 (X11; U; Linux armv6l; rv 1.8.1.5pre) Gecko/20070619 Minimo/0.020", - "Mozilla/5.0 (X11; U; Linux arm7tdmi; rv:1.8.1.11) Gecko/20071130 Minimo/0.025", - "Mozilla/4.0 (PDA; PalmOS/sony/model prmr/Revision:1.1.54 (en)) NetFront/3.0", - "Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)", - "Opera/9.60 (J2ME/MIDP; Opera Mini/4.1.11320/608; U; en) Presto/2.2.0", - "Opera/9.60 (J2ME/MIDP; Opera Mini/4.2.14320/554; U; cs) Presto/2.2.0", - "Opera/9.80 (S60; SymbOS; Opera Mobi/499; U; ru) Presto/2.4.18 Version/10.00", - "Opera/10.61 (J2ME/MIDP; Opera Mini/5.1.21219/19.999; en-US; rv:1.9.3a5) WebKit/534.5 Presto/2.6.30", - "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.1010", - "Opera/9.80 (J2ME/MIDP; Opera Mini/8.0.35626/37.8918; U; en) Presto/2.12.423 Version/12.16", - "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", - "Opera/9.80 (Android; Opera Mini/9.0.1829/66.318; U; en) Presto/2.12.423 Version/12.16", - "Opera/9.80 (Linux i686; Opera Mobi/1040; U; en) Presto/2.5.24 Version/10.00", - "POLARIS/6.01 (BREW 3.1.5; U; en-us; LG; LX265; POLARIS/6.01/WAP) MMP/2.0 profile/MIDP-2.1 Configuration/CLDC-1.1", + "Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+", + "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)", + "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.4 (KHTML, like Gecko) Chrome/4.0.237.0 Safari/532.4 Debian", + "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.277.0 Safari/532.8", + "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.613.0 Chrome/10.0.613.0 Safari/534.15", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7 MG(Novarra-Vision/6.9)", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.16) Gecko/20080716 (Gentoo) Galeon/2.0.6", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.10 (karmic) Firefox/3.0.11", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Galeon/2.0.6 (Ubuntu 2.0.6-2)", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090803 Ubuntu/9.04 (jaunty) Shiretoko/3.5.2", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a3pre) Gecko/20070330", + "Mozilla/5.0 (X11; U; Linux i686; en-gb) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.0.5603M", + "Mozilla/5.0 (X11; U; Linux i686; en-us) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) lt-GtkLauncher", + "Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.2.3) Gecko/20100406 Firefox/3.6.3 (Swiftfox)", + "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8", + "Mozilla/5.0 (X11; U; Linux i686; pt-PT; rv:1.9.2.3) Gecko/20100402 Iceweasel/3.6.3 (like Firefox/3.6.3) GTB7.0", + "Mozilla/5.0 (X11; U; Linux i686; rv:19.0) Gecko/20100101 Slackware/13 Firefox/19.0", + "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.8.1.13) Gecko/20080313 Iceape/1.1.9 (Debian-1.1.9-5)", + "Mozilla/5.0 (X11; U; Linux x86_64; en-AU) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IT", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.309.0 Safari/532.9", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.613.0 Safari/534.15", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/9.1.0.0 Safari/540.0", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.13) Gecko/20100916 Iceape/2.0.8", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.17) Gecko/20110123 SeaMonkey/2.0.12", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Linux Mint/8 (Helena) Firefox/3.5.3", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5) Gecko/20091107 Firefox/3.5.5", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9", "Mozilla/5.0 (X11; U; Linux x86_64; en-gb) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.9174AP", "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.9174AT", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 6_1 like Mac OS X; en-HK) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IP Mobile", - "Mozilla/5.0 (X11; U; Linux x86_64; en-AU) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IT", - "Mozilla/5.0 (X11; U; Linux i686; en-gb) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.0.5603M", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25", + "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.8.0.2965AT", + "Mozilla/5.0 (X11; U; Linux x86_64; sv-SE; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12", + "Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0", + "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.1", + "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Debian/1.6-7", + "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Epiphany/1.2.5", + "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Galeon/1.3.14", + "Mozilla/5.0 (X11; U; NetBSD amd64; en-US; rv:1.9.2.15) Gecko/20110308 Namoroka/3.6.15", + "Mozilla/5.0 (X11; U; OpenBSD arm; en-us) AppleWebKit/531.2 (KHTML, like Gecko) Safari/531.2 Epiphany/2.30.0", + "Mozilla/5.0 (X11; U; OpenBSD i386; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.359.0 Safari/533.3", + "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.1) Gecko/20090702 Firefox/3.5", + "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1.12) Gecko/20080303 SeaMonkey/1.1.8", + "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.9.1b3) Gecko/20090429 Firefox/3.1b3", + "Mozilla/5.0 (X11; U; SunOS sun4m; en-US; rv:1.4b) Gecko/20030517 Mozilla Firebird/0.6", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", + "Mozilla/5.0 (compatible; Exabot/3.0; http://www.exabot.com/go/robot)", + "Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)", + "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8-gentoo-r3; X11;", + "Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.30-7.dmz.1-liquorix-686; X11) KHTML/3.5.10 (like Gecko) (Debian package 4:3.5.10.dfsg.1-1 b1)", + "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; en_US) KHTML/3.5.6 (like Gecko) (Kubuntu)", + "Mozilla/5.0 (compatible; Konqueror/3.5; NetBSD 4.0_RC3; X11) KHTML/3.5.7 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/3.5; SunOS) KHTML/3.5.1 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.1; DragonFly) KHTML/4.1.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.2; Linux) KHTML/4.2.4 (like Gecko) Slackware/13.0", + "Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.1 (like Gecko) Fedora/4.3.1-3.fc11", + "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", + "Mozilla/5.0 (compatible; Konqueror/4.4; Linux) KHTML/4.4.1 (like Gecko) Fedora/4.4.1-1.fc12", + "Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.5; NetBSD 5.0.2; X11; amd64; en_US) KHTML/4.5.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.5; Windows) KHTML/4.5.4 (like Gecko)", + "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", + "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)", + "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", + "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; XBLWP7; ZuneWP7) UCBrowser/2.9.0.263", - "Mozilla/5.0 (Linux; U; Android 2.3.3; en-us ; LS670 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1/UCBrowser/8.6.1.262/145/355", - "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/5.0 (Linux; U; Android 4.1; en-us; sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.1 Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 4.2; en-us; sdk Build/MR1) AppleWebKit/535.19 (KHTML, like Gecko) Version/4.2 Safari/535.19", - "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.9174AT", - "Mozilla/5.0 (X11; U; Linux x86_64; en-AU) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IT", - "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10", - "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPad; U; CPU OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Trident/5.0)", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", + "Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)", + "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)", + "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)", + "Mozilla/5.0 (compatible; YandexNews/4.0; +http://yandex.com/bots)", + "Mozilla/5.0 (compatible; alexa site audit/1.0; +http://www.alexa.com/help/webmasters; )", + "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)", + "Mozilla/5.0 (compatible; archive.org_bot; Wayback Machine Live Record; +http://archive.org/details/archive.org_bot)", + "Mozilla/5.0 (compatible; bingbot/2.0 http://www.bing.com/bingbot.htm)", + "Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13", + "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0", + "Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/49.0.2623.109 Mobile/14A5335b Safari/601.1.46", + "Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/100.0.4896.85 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/99.0.4844.59 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Flipboard/4.2.142", + "Mozilla/5.0 (iPad; CPU OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", "Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko ) Version/5.1 Mobile/9B176 Safari/7534.48.3", "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25", + "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25 (3B92C18B-D9DE-4CB7-A02A-22FD2AF17C8F)", + "Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", "Mozilla/5.0 (iPad; CPU OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML like Gecko) Mobile/12A405 Version/7.0 Safari/9537.53", "Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4", "Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1", - "Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/49.0.2623.109 Mobile/14A5335b Safari/601.1.46", - "Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7;en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17", - "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0", - "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true", - "Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36", - "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", - "Mozilla/5.0 (Linux; U; Android 1.5; de-de; Galaxy Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; GT-P5210 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7100 Build/HRI83) AppleWebkit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 600x800)", - "Mozilla/5.0 (Linux U; en-US) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) Version/4.0 Kindle/3.0 (screen 600x800; rotate)", - "Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+", - "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true", "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10", "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", "Mozilla/5.0 (iPad; U; CPU OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5", "Mozilla/5.0 (iPad; U; CPU iPad OS 5_0_1 like Mac OS X; en-us) AppleWebKit/535.1+ (KHTML like Gecko) Version/7.2.0.0 Safari/6533.18.5", - "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25", - "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25 (3B92C18B-D9DE-4CB7-A02A-22FD2AF17C8F)", - "Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", - "Mozilla/5.0 (iPad; CPU OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML like Gecko) Mobile/12A405 Version/7.0 Safari/9537.53", - "Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4", - "Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", - "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.200", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/531.22.7", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3", + "Mozilla/5.0 (iPhone; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.25 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/28.0 Mobile/15E148 Safari/605.1.15", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/18.0.130791545 Mobile/14A5345a Safari/600.1.4", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A346 Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G60 Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.80 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/101.0.4951.58 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 OPT/3.2.13", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X; zh-CN) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19B81 UCBrowser/13.7.2.1636 Mobile AliApp(TUnionSDK/0.1.20.4) dv(iPh14,5);pr(UCBrowser/13.7.2.1636);ov(15_1_1);ss(390x844);bt(UC);pm(0);bv(0);nm(0);im(0);nt(1);", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari Line/12.6.0", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/100.0.4896.77 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/101.0.4951.44 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/101.0.4951.58 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/96.0.4664.101 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/99.0.4844.59 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/209.1.445234187 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/99.3 Mobile/15E148 Safari/605.1.15", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Zalo iOS/448 ZaloTheme/light ZaloLanguage/en", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/605.1 NAVER(inapp; search; 1000; 11.5.7; XR)", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1", "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25", - "UCWEB/8.8 (iPhone; CPU OS_6; en-US)AppleWebKit/534.1 U3/3.0.0 Mobile", "Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", "Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4", "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12H321 Safari/600.1.4", "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13C75 Safari/601.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A346 Safari/602.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/18.0.130791545 Mobile/14A5345a Safari/600.1.4", - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1_1 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7C145", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.200", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/531.22.7", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8F190", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", + "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3", "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML like Gecko) Version/7.0 Mobile/11D167 Safari/123E71C", "Mozilla/5.0 (iPod; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/44.0.2403.67 Mobile/12H143 Safari/600.1.4", - "nook browser/1.0", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7;en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; BNTV250 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1", - "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36", - "BlackBerry7100i/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/103", - "BlackBerry8300/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/107 UP.Link/6.2.3.15.0", - "BlackBerry8320/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/100", - "BlackBerry8330/4.3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/105", - "BlackBerry9000/4.6.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102", - "BlackBerry9530/4.7.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102 UP.Link/6.3.1.20.0", - "BlackBerry9700/5.0.0.351 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/123", - "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1 (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1", - "Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.267 Mobile Safari/534.11+", - "Mozilla/5.0 (Linux; Android 7.1.1; BBB100-1 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", - "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.1.0.2342 Mobile Safari/537.10+", - "Mozilla/5.0 (Linux; Android 5.1.1; Coolpad 3622A Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.1; Coolpad 3632A Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; sdk Build/CUPCAKE) AppleWebkit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.2; Nexus 6P Build/N2G48C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.135 Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", - "Mozilla/5.0 (Linux; Android 7.0; Nexus 9 Build/NRD90R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.2; Pixel Build/NHG47N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0", - "Mozilla/5.0 (Linux; webOS/2.2.4; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) webOSBrowser/221.56 Safari/534.6 Pre/3.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) Sprint:PPC6800", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) XV6800", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; htc_bahamas Build/CRB17) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.1-update1; de-de; HTC Desire 1.19.161.5 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 1.5; de-ch; HTC Hero Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.1; en-us; HTC Legend Build/cupcake) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 1.5; de-de; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 FirePHP/0.3", - "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "HTC-ST7377/1.59.502.3 (67150) Opera/9.50 (Windows NT 5.1; U; en) UP.Link/6.3.1.17.0", - "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.89 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.1; C6740N Build/LMY47O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; LG-P870/P87020d Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "LG-LX550 AU-MIC-LX550/2.0 MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/5.0 (Linux; Android 6.0; LG-D850 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.97 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LG-H918 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LGL84VL Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LGUS997 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; LGMS323 Build/KOT49I.MS32310b) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Mobile Safari/537.36", - "POLARIS/6.01(BREW 3.1.5;U;en-us;LG;LX265;POLARIS/6.01/WAP;)MMP/2.0 profile/MIDP-201 Configuration /CLDC-1.1", - "LG-GC900/V10a Obigo/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1", - "Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Safari/537.36", - "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; MDA Pro/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1)", - "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; T-Mobile G1 Build/CRB43) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari 525.20.1", - "Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile_G2_Touch Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "MOT-L7v/08.B7.5DR MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.0.1; de-de; Milestone Build/SHOLS_U2_01.14.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; Android 7.0; Moto G (5) Plus Build/NPNS25.137-35-5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.1; XT1710-02 Build/NDS26.74-36) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0", - "MOTORIZR-Z8/46.00.00 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 356) Opera 8.65 [it] UP.Link/6.3.0.0.0", - "MOT-V177/0.1.75 UP.Browser/6.2.3.9.c.12 (GUI) MMP/2.0 UP.Link/6.3.1.13.0", - "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; Android 4.4.4; XT1032 Build/KXB21.14-L1.61) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", - "portalmmm/2.0 N410i(c20;TB)", - "Nokia3230/2.0 (5.0614.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia5700/3.27; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia6120c/3.70; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Nokia6230/2.0 (04.44) Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Nokia6230i/2.0 (03.80) Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 6600;452) Opera 6.20 [en-US]", - "Nokia6630/1.0 (2.39.15) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Nokia7250/1.0 (3.14) Profile/MIDP-1.0 Configuration/CLDC-1.0", - "Mozilla/4.0 (compatible; MSIE 5.0; Series80/2.0 Nokia9500/4.51 Profile/MIDP-2.0 Configuration/CLDC-1.1)", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC6-01/011.010; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.2 3gpp-gba", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC7-00/012.003; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es50", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE6-00/021.002; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.16 Mobile Safari/533.4 3gpp-gba", - "UCWEB/8.8 (SymbianOS/9.2; U; en-US; NokiaE63) AppleWebKit/534.1 UCBrowser/8.8.0.245 Mobile", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es65", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE7-00/010.016; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es70", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.2.3.18.0", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 630) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 635) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 920) like Geckoo", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) like Gecko", - "NokiaN70-1/5.0609.2.0.1 Series60/2.8 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "NokiaN73-1/3.0649.0.0.1 Series60/3.0 Profile/MIDP2.0 Configuration/CLDC-1.1", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/014.002; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.4 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", - "Mozilla/5.0 (SymbianOS/9.1; U; de) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaN95/10.0.018; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.3.0.0.0", - "Mozilla/5.0 (MeeGo; NokiaN950-00/00) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", - "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaX7-00/021.004; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.21 Mobile Safari/533.4 3gpp-gba", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1_1 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7C145", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 6_1 like Mac OS X; en-HK) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IP Mobile", "Mozilla/5.0 (webOS/1.3; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320", - "SEC-SGHE900/1.0 NetFront/3.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1378; nl; U; ssr)", - "Mozilla/5.0 (Linux; U; Android 1.5; de-de; Galaxy Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-de; Galaxy S II Build/GRJ22) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "Mozilla/5.0 (Linux; Android 4.3; SPH-L710 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.0.1; SCH-R970 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-G900A Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; GT-P5210 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7100 Build/HRI83) AppleWebkit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41", + "NetSurf/1.2 (NetBSD; amd64)", + "Nokia3230/2.0 (5.0614.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0", + "Nokia6100/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0", + "Nokia6230/2.0 (04.44) Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia6230i/2.0 (03.80) Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia6630/1.0 (2.3.129) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia6630/1.0 (2.39.15) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia7250/1.0 (3.14) Profile/MIDP-1.0 Configuration/CLDC-1.0", + "NokiaN70-1/5.0609.2.0.1 Series60/2.8 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0", + "NokiaN73-1/3.0649.0.0.1 Series60/3.0 Profile/MIDP2.0 Configuration/CLDC-1.1", + "Offline Explorer/2.5", + "Opera/10.61 (J2ME/MIDP; Opera Mini/5.1.21219/19.999; en-US; rv:1.9.3a5) WebKit/534.5 Presto/2.6.30", + "Opera/7.50 (Windows ME; U) [en]", + "Opera/7.50 (Windows XP; U)", + "Opera/7.51 (Windows NT 5.1; U) [en]", + "Opera/8.01 (J2ME/MIDP; Opera Mini/1.0.1479/HiFi; SonyEricsson P900; no; U; ssr)", + "Opera/9.0 (Macintosh; PPC Mac OS X; U; en)", + "Opera/9.20 (Macintosh; Intel Mac OS X; U; en)", + "Opera/9.25 (Windows NT 6.0; U; en)", + "Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)", + "Opera/9.5 (Microsoft Windows; PPC; Opera Mobi; U) SonyEricssonX1i/R2AA Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)", + "Opera/9.60 (J2ME/MIDP; Opera Mini/4.1.11320/608; U; en) Presto/2.2.0", + "Opera/9.60 (J2ME/MIDP; Opera Mini/4.2.14320/554; U; cs) Presto/2.2.0", + "Opera/9.64 (Macintosh; PPC Mac OS X; U; en) Presto/2.1.1", + "Opera/9.64 (X11; Linux i686; U; Linux Mint; nb) Presto/2.1.1", + "Opera/9.80 (Android 4.0.4; Linux; Opera Mobi/ADR-1205181138; U; pl) Presto/2.10.254 Version/12.00", + "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.1010", + "Opera/9.80 (Android; Opera Mini/9.0.1829/66.318; U; en) Presto/2.12.423 Version/12.16", + "Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.16823/1428; U; en) Presto/2.2.0", + "Opera/9.80 (J2ME/MIDP; Opera Mini/8.0.35626/37.8918; U; en) Presto/2.12.423 Version/12.16", + "Opera/9.80 (Linux i686; Opera Mobi/1040; U; en) Presto/2.5.24 Version/10.00", + "Opera/9.80 (Macintosh; Intel Mac OS X 10.4.11; U; en) Presto/2.7.62 Version/11.00", + "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", + "Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.6.30 Version/10.61", + "Opera/9.80 (S60; SymbOS; Opera Mobi/499; U; ru) Presto/2.4.18 Version/10.00", + "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10", + "Opera/9.80 (Windows NT 5.2; U; en) Presto/2.2.15 Version/10.10", + "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", + "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.7.62 Version/11.01", + "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00", + "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16", + "Opera/9.80 (X11; FreeBSD 8.1-RELEASE i386; Edition Next) Presto/2.12.388 Version/12.10", + "Opera/9.80 (X11; Linux i686) Presto/2.12.388 Version/12.16", + "Opera/9.80 (X11; Linux i686; U; en) Presto/2.2.15 Version/10.10", + "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00", + "P3P Validator", + "POLARIS/6.01 (BREW 3.1.5; U; en-us; LG; LX265; POLARIS/6.01/WAP) MMP/2.0 profile/MIDP-2.1 Configuration/CLDC-1.1", + "POLARIS/6.01(BREW 3.1.5;U;en-us;LG;LX265;POLARIS/6.01/WAP;)MMP/2.0 profile/MIDP-201 Configuration /CLDC-1.1", + "Peach/1.01 (Ubuntu 8.04 LTS; U; en)", + "Python-urllib/2.5", + "Roku/DVP-4.1 (024.01E01250A)", "SAMSUNG-S8000/S8000XXIF3 SHP/VPP/R5 Jasmine/1.0 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 FirePHP/0.3", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; SPH-M900 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", "SAMSUNG-SGH-A867/A867UCHJ3 SHP/VPP/R5 NetFront/35 SMM-MMS/1.2.0 profile/MIDP-2.0 configuration/CLDC-1.1 UP.Link/6.3.0.0.0", + "SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", + "SEC-SGHE900/1.0 NetFront/3.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1378; nl; U; ssr)", "SEC-SGHX210/1.0 UP.Link/6.3.1.13.0", - "Mozilla/5.0 (Linux; Android 6.0.1; SM-G900H Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G925R6 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 1.5; fr-fr; GT-I5700 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", "SEC-SGHX820/1.0 NetFront/3.2 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Screaming Frog SEO Spider/8.1", + "SearchExpress", "SonyEricssonK310iv/R4DA Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0", "SonyEricssonK550i/R1JD Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonK610i/R1CB Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonK750i/R1CA Browser/SEMC-Browser/4.2 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.16823/1428; U; en) Presto/2.2.0", "SonyEricssonK800i/R1CB Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", "SonyEricssonK810i/R1KG Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Opera/8.01 (J2ME/MIDP; Opera Mini/1.0.1479/HiFi; SonyEricsson P900; no; U; ssr)", "SonyEricssonS500i/R6BC Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 SonyEricssonP100/01; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 Safari/525", - "SonyEricssonT68/R201A", "SonyEricssonT100/R101", "SonyEricssonT610/R201 Profile/MIDP-1.0 Configuration/CLDC-1.0", "SonyEricssonT650i/R7AA Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "SonyEricssonT68/R201A", "SonyEricssonW580i/R6BC Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonW660i/R6AD Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonW810i/R4EA Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", "SonyEricssonW850i/R1ED Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonW950i/R100 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 323) Opera 8.60 [en-US]", "SonyEricssonW995/R1EA Profile/MIDP-2.1 Configuration/CLDC-1.1 UNTRUSTED/1.0", - "Mozilla/5.0 (Linux; U; Android 1.6; es-es; SonyEricssonX10i Build/R1FA016) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 1.6; en-us; SonyEricssonX10i Build/R1AA056) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Opera/9.5 (Microsoft Windows; PPC; Opera Mobi; U) SonyEricssonX1i/R2AA Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonZ800/R1Y Browser/SEMC-Browser/4.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", - "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.1010", - "Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0", - "Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0", - "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522 (KHTML, like Gecko) Safari/419.3", - "Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Android; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-de; Galaxy S II Build/GRJ22) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "Opera/9.80 (Android 4.0.4; Linux; Opera Mobi/ADR-1205181138; U; pl) Presto/2.10.254 Version/12.00", - "Mozilla/5.0 (Android; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", - "Mozilla/5.0 (Linux; Android 4.1.2; SHV-E250S Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.82 Mobile Safari/537.36", - "Mozilla/5.0 (Android 4.2; rv:19.0) Gecko/20121129 Firefox/19.0", - "Mozilla/5.0 (Linux; U; Android 4.3; en-us; sdk Build/MR1) AppleWebKit/536.23 (KHTML, like Gecko) Version/4.3 Mobile Safari/536.23", - "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SM-T230NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.0.1; SCH-R970 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", - "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0; LG-D850 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.97 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0.1; SM-G900H Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; Nexus 9 Build/NRD90R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LG-H918 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.200", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16", - "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10", - "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8F190", - "MobileSafari/600.1.4 CFNetwork/711.1.12 Darwin/14.0.0", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3", - "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13C75 Safari/601.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", - "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (webOS/1.3; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/014.002; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.4 3gpp-gba", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaX7-00/021.004; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.21 Mobile Safari/533.4 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.2.3.18.0", - "Mozilla/5.0 (SymbianOS 9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", - "Opera/9.80 (S60; SymbOS; Opera Mobi/499; U; ru) Presto/2.4.18 Version/10.00", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) Sprint:PPC6800", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile6.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 630) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 635) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 920) like Geckoo", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) like Gecko", - "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 929) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537", - "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0", - "Mozilla/5.0 (Windows NT 10.0; ARM; Lumia 950 Dual SIM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393", - "DoCoMo/2.0 SH901iC(c100;TB;W24H12)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7 MG(Novarra-Vision/6.9)", - "Mozilla/4.0 (compatible; MSIE 6.0; j2me) ReqwirelessWeb/3.5", - "Vodafone/1.0/V802SE/SEJ001 Browser/SEMC-Browser/4.1", - "BlackBerry7520/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/5.0.3.3 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)", - "Nokia6100/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0", - "Nokia6630/1.0 (2.3.129) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)", - "Baiduspider ( http://www.baidu.com/search/spider.htm)", - "Mozilla/5.0 (compatible; bingbot/2.0 http://www.bing.com/bingbot.htm)", - "Mozilla/5.0 (compatible; Exabot/3.0; http://www.exabot.com/go/robot)", - "FAST-WebCrawler/3.8 (crawler at trd dot overture dot com; http://www.alltheweb.com/help/webmaster/crawler)", - "AdsBot-Google ( http://www.google.com/adsbot.html)", - "Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)", - "Googlebot/2.1 ( http://www.googlebot.com/bot.html)", - "Googlebot-Image/1.0", - "Mediapartners-Google", - "DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", - "SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", - "Googlebot-News", - "Googlebot-Video/1.0", - "Mozilla/4.0 (compatible; GoogleToolbar 4.0.1019.5266-big; Windows XP 5.1; MSIE 6.0.2900.2180)", - "Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13", - "msnbot/1.0 ( http://search.msn.com/msnbot.htm)", - "msnbot/1.1 ( http://search.msn.com/msnbot.htm)", - "msnbot/0.11 ( http://search.msn.com/msnbot.htm)", - "msnbot-media/1.1 ( http://search.msn.com/msnbot.htm)", - "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)", - "Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)", - "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)", - "Mozilla/5.0 (compatible; YandexNews/4.0; +http://yandex.com/bots)", - "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)", - "Mozilla/5.0 (compatible; archive.org_bot; Wayback Machine Live Record; +http://archive.org/details/archive.org_bot)", - "Mozilla/5.0 (compatible; alexa site audit/1.0; +http://www.alexa.com/help/webmasters; )", - "EmailWolf 1.00", - "facebookexternalhit/1.1", - "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", - "Facebot", - "Gaisbot/3.0 (robot@gais.cs.ccu.edu.tw; http://gais.cs.ccu.edu.tw/robot.php)", - "grub-client-1.5.3; (grub-client-1.5.3; Crawl your own stuff with http://grub.org)", - "Gulper Web Bot 0.2.4 (www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/Link/GulperBot)", - "Screaming Frog SEO Spider/8.1", + "SuperBot/4.4.0.60 (Windows XP)", "TurnitinBot (https://turnitin.com/robot/crawlerinfo.html)", "Twitterbot/1.0", - "Xenu Link Sleuth/1.3.8", - "Mozilla/3.0 (compatible; NetPositive/2.1.1; BeOS)", - "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.9a1) Gecko/20060702 SeaMonkey/1.5a", - "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Arora/0.11.0 Safari/533.3", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20100101 Firefox/10.0.12", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0", - "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) QupZilla/1.3.1 Safari/533.3", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20130108 Firefox/10.0.12 SeaMonkey/2.7.2", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0 SeaMonkey/2.21", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0 SeaMonkey/2.28", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0 SeaMonkey/2.42.9esr", - "Adobe Application Manager 2.0", - "AndroidDownloadManager/5.1 (Linux; U; Android 5.1; Z820 Build/LMY47D)", - "Download Demon/3.5.0.11", - "Offline Explorer/2.5", - "SuperBot/4.4.0.60 (Windows XP)", - "WebCopier v4.6", + "UCWEB/8.8 (SymbianOS/9.2; U; en-US; NokiaE63) AppleWebKit/534.1 UCBrowser/8.8.0.245 Mobile", + "UCWEB/8.8 (iPhone; CPU OS_6; en-US)AppleWebKit/534.1 U3/3.0.0 Mobile", + "Uzbl (Webkit 1.3) (Linux i686 [i686])", + "Vodafone/1.0/V802SE/SEJ001 Browser/SEMC-Browser/4.1", + "W3C_Validator/1.305.2.12 libwww-perl/5.64", + "W3C_Validator/1.654", + "WDG_Validator/1.6.2", "Web Downloader/6.9", + "WebCopier v4.6", "WebZIP/3.5 (http://www.spidersoft.com)", + "Wget/1.12 (freebsd8.1)", "Wget/1.9 cvs-stable (Red Hat modified)", "Wget/1.9.1", - "Wget/1.12 (freebsd8.1)", - "Bloglines/3.1 (http://www.bloglines.com)", + "Xenu Link Sleuth/1.3.8", "everyfeed-spider/2.0 (http://www.everyfeed.com)", - "FeedFetcher-Google; ( http://www.google.com/feedfetcher.html)", - "Gregarius/0.5.2 ( http://devlog.gregarius.net/docs/ua)", - "Mozilla/5.0 (PLAYSTATION 3; 2.00)", - "Mozilla/5.0 (PLAYSTATION 3; 1.10)", - "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)", - "Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)", - "wii libnup/1.0", - "Java/1.6.0_13", - "libwww-perl/5.820", - "Peach/1.01 (Ubuntu 8.04 LTS; U; en)", - "Python-urllib/2.5", - "HTMLParser/1.6", - "Jigsaw/2.2.5 W3C_CSS_Validator_JFouffa/2.0", - "W3C_Validator/1.654", - "W3C_Validator/1.305.2.12 libwww-perl/5.64", - "P3P Validator", - "CSSCheck/1.2.2", - "WDG_Validator/1.6.2", + "facebookexternalhit/1.1", + "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", "facebookscraper/1.0( http://www.facebook.com/sharescraper_help.php)", "grub-client-1.5.3; (grub-client-1.5.3; Crawl your own stuff with http://grub.org)", "iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)", - "Microsoft URL Control - 6.00.8862", - "Roku/DVP-4.1 (024.01E01250A)", - "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebkit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42", - "SearchExpress", + "iTunes/9.0.2 (Windows; N)", + "iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)", + "libwww-perl/5.820", + "msnbot-media/1.1 ( http://search.msn.com/msnbot.htm)", + "msnbot/0.11 ( http://search.msn.com/msnbot.htm)", + "msnbot/1.0 ( http://search.msn.com/msnbot.htm)", + "msnbot/1.1 ( http://search.msn.com/msnbot.htm)", + "nook browser/1.0", + "portalmmm/2.0 N410i(c20;TB)", + "w3m/0.5.1", + "wii libnup/1.0", } ) diff --git a/vendor/github.com/corpix/uarand/useragents.mk b/vendor/github.com/corpix/uarand/useragents.mk deleted file mode 100644 index 2e2e457bd..000000000 --- a/vendor/github.com/corpix/uarand/useragents.mk +++ /dev/null @@ -1,10 +0,0 @@ -.PHONY: useragents.go -useragents.go: - curl -Ls -H'User-Agent: gotohellwithyour403' \ - http://techpatterns.com/downloads/firefox/useragentswitcher.xml \ - | ./scripts/extract-user-agents \ - | ./scripts/generate-useragents-go $(name) \ - > $@ - go fmt $@ - -dependencies:: useragents.go diff --git a/vendor/github.com/dghubble/sling/.travis.yml b/vendor/github.com/dghubble/sling/.travis.yml deleted file mode 100644 index 909175016..000000000 --- a/vendor/github.com/dghubble/sling/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: go -go: - - 1.9 - - "1.10.x" - - "1.11.x" - - tip -install: - - go get golang.org/x/lint/golint - - go get -v -t . -script: - - ./test diff --git a/vendor/github.com/dghubble/sling/CHANGES.md b/vendor/github.com/dghubble/sling/CHANGES.md index f867e0d7a..3ba8622b6 100644 --- a/vendor/github.com/dghubble/sling/CHANGES.md +++ b/vendor/github.com/dghubble/sling/CHANGES.md @@ -4,6 +4,24 @@ Notable changes between releases. ## Latest +## v1.4.2 + +* Update Go module dependencies + +## v1.4.1 + +* Update minimum Go version to v1.18 ([#76](https://github.com/dghubble/sling/pull/76)) + +## v1.4.0 + +* `Do` reads Body to reuse HTTP/1.x "keep-alive" TCP connections ([#59](https://github.com/dghubble/sling/pull/59)) +* `Receive` skips decoding if status is 204 (no content) ([#63](https://github.com/dghubble/sling/pull/63)) + +## v1.3.0 + +* Add Sling `ResponseDecoder` setter for receiving responses with a custom `ResponseDecoder` ([#49](https://github.com/dghubble/sling/pull/49)) +* Add Go module support (i.e. `go.mod`). Exclude `examples` (multi-module). ([#52](https://github.com/dghubble/sling/pull/52)) + ## v1.2.0 * Add `Connect`, `Options`, and `Trace` HTTP methods ([c51967](https://github.com/dghubble/sling/commit/c519674860ff275e0ceb12caf5d87b31765c4e71)) diff --git a/vendor/github.com/dghubble/sling/README.md b/vendor/github.com/dghubble/sling/README.md index ff793c60e..e790161c5 100644 --- a/vendor/github.com/dghubble/sling/README.md +++ b/vendor/github.com/dghubble/sling/README.md @@ -1,4 +1,9 @@ -# Sling [![Build Status](https://travis-ci.org/dghubble/sling.svg?branch=master)](https://travis-ci.org/dghubble/sling) [![GoDoc](https://godoc.org/github.com/dghubble/sling?status.svg)](https://godoc.org/github.com/dghubble/sling) +# Sling +[![GoDoc](https://pkg.go.dev/badge/github.com/dghubble/sling.svg)](https://pkg.go.dev/github.com/dghubble/sling) +[![Workflow](https://github.com/dghubble/sling/actions/workflows/test.yaml/badge.svg)](https://github.com/dghubble/sling/actions/workflows/test.yaml?query=branch%3Amain) +[![Sponsors](https://img.shields.io/github/sponsors/dghubble?logo=github)](https://github.com/sponsors/dghubble) +[![Mastodon](https://img.shields.io/badge/follow-news-6364ff?logo=mastodon)](https://fosstodon.org/@typhoon) + Sling is a Go HTTP client library for creating and sending API requests. @@ -272,11 +277,10 @@ func (s *IssueService) ListByRepo(owner, repo string, params *IssueListParams) ( * GoSquared [drinkin/go-gosquared](https://github.com/drinkin/go-gosquared) * Kala [ajvb/kala](https://github.com/ajvb/kala) * Parse [fergstar/go-parse](https://github.com/fergstar/go-parse) -* Rdio [apriendeau/shares](https://github.com/apriendeau/shares) * Swagger Generator [swagger-api/swagger-codegen](https://github.com/swagger-api/swagger-codegen) * Twitter [dghubble/go-twitter](https://github.com/dghubble/go-twitter) -* Hacker News [mirceamironenco/go-hackernews](https://github.com/mirceamironenco/go-hackernews) * Stacksmith [jesustinoco/go-smith](https://github.com/jesustinoco/go-smith) +* Spotify [omegastreamtv/Spotify](https://github.com/omegastreamtv/Spotify) Create a Pull Request to add a link to your own API. diff --git a/vendor/github.com/dghubble/sling/doc.go b/vendor/github.com/dghubble/sling/doc.go index dd2efb7e3..f48836c17 100644 --- a/vendor/github.com/dghubble/sling/doc.go +++ b/vendor/github.com/dghubble/sling/doc.go @@ -5,7 +5,7 @@ Slings store HTTP Request properties to simplify sending requests and decoding responses. Check the examples to learn how to compose a Sling into your API client. -Usage +# Usage Use a Sling to set path, method, header, query, or body properties and create an http.Request. @@ -18,7 +18,7 @@ http.Request. req, err := sling.New().Get("https://example.com").QueryStruct(params).Request() client.Do(req) -Path +# Path Use Path to set or extend the URL for created Requests. Extension means the path will be resolved relative to the existing URL. @@ -31,14 +31,14 @@ except they set the HTTP method too. req, err := sling.New().Post("http://upload.com/gophers") -Headers +# Headers Add or Set headers for requests created by a Sling. s := sling.New().Base(baseUrl).Set("User-Agent", "Gophergram API Client") req, err := s.New().Get("gophergram/list").Request() -QueryStruct +# QueryStruct Define url parameter structs (https://godoc.org/github.com/google/go-querystring/query). Use QueryStruct to encode a struct as query parameters on requests. @@ -59,7 +59,7 @@ Use QueryStruct to encode a struct as query parameters on requests. params := &IssueParams{Sort: "updated", State: "open"} req, err := githubBase.New().Get(path).QueryStruct(params).Request() -Json Body +# Json Body Define JSON tagged structs (https://golang.org/pkg/encoding/json/). Use BodyJSON to JSON encode a struct as the Body on requests. @@ -83,7 +83,7 @@ Use BodyJSON to JSON encode a struct as the Body on requests. Requests will include an "application/json" Content-Type header. -Form Body +# Form Body Define url tagged structs (https://godoc.org/github.com/google/go-querystring/query). Use BodyForm to form url encode a struct as the Body on requests. @@ -100,7 +100,7 @@ Use BodyForm to form url encode a struct as the Body on requests. Requests will include an "application/x-www-form-urlencoded" Content-Type header. -Plain Body +# Plain Body Use Body to set a plain io.Reader on requests created by a Sling. @@ -109,7 +109,7 @@ Use Body to set a plain io.Reader on requests created by a Sling. Set a content type header, if desired (e.g. Set("Content-Type", "text/plain")). -Extend a Sling +# Extend a Sling Each Sling generates an http.Request (say with some path and query params) each time Request() is called, based on its state. When creating @@ -137,7 +137,7 @@ is undesired. Recap: If you wish to extend a Sling, create a new child copy with New(). -Receive +# Receive Define a JSON struct to decode a type from 2XX success responses. Use ReceiveSuccess(successV interface{}) to send a new Request and decode the diff --git a/vendor/github.com/dghubble/sling/sling.go b/vendor/github.com/dghubble/sling/sling.go index c75fd678a..5492ef2e8 100644 --- a/vendor/github.com/dghubble/sling/sling.go +++ b/vendor/github.com/dghubble/sling/sling.go @@ -2,7 +2,6 @@ package sling import ( "encoding/base64" - "encoding/json" "io" "net/http" "net/url" @@ -37,24 +36,27 @@ type Sling struct { queryStructs []interface{} // body provider bodyProvider BodyProvider + // response decoder + responseDecoder ResponseDecoder } // New returns a new Sling with an http DefaultClient. func New() *Sling { return &Sling{ - httpClient: http.DefaultClient, - method: "GET", - header: make(http.Header), - queryStructs: make([]interface{}, 0), + httpClient: http.DefaultClient, + method: "GET", + header: make(http.Header), + queryStructs: make([]interface{}, 0), + responseDecoder: jsonDecoder{}, } } // New returns a copy of a Sling for creating a new Sling with properties // from a parent Sling. For example, // -// parentSling := sling.New().Client(client).Base("https://api.io/") -// fooSling := parentSling.New().Get("foo/") -// barSling := parentSling.New().Get("bar/") +// parentSling := sling.New().Client(client).Base("https://api.io/") +// fooSling := parentSling.New().Get("foo/") +// barSling := parentSling.New().Get("bar/") // // fooSling and barSling will both use the same client, but send requests to // https://api.io/foo/ and https://api.io/bar/ respectively. @@ -68,12 +70,13 @@ func (s *Sling) New() *Sling { headerCopy[k] = v } return &Sling{ - httpClient: s.httpClient, - method: s.method, - rawURL: s.rawURL, - header: headerCopy, - queryStructs: append([]interface{}{}, s.queryStructs...), - bodyProvider: s.bodyProvider, + httpClient: s.httpClient, + method: s.method, + rawURL: s.rawURL, + header: headerCopy, + queryStructs: append([]interface{}{}, s.queryStructs...), + bodyProvider: s.bodyProvider, + responseDecoder: s.responseDecoder, } } @@ -336,6 +339,15 @@ func addHeaders(req *http.Request, header http.Header) { // Sending +// ResponseDecoder sets the Sling's response decoder. +func (s *Sling) ResponseDecoder(decoder ResponseDecoder) *Sling { + if decoder == nil { + return s + } + s.responseDecoder = decoder + return s +} + // ReceiveSuccess creates a new HTTP request and returns the response. Success // responses (2XX) are JSON decoded into the value pointed to by successV. // Any error creating the request, sending it, or decoding a 2XX response @@ -347,8 +359,9 @@ func (s *Sling) ReceiveSuccess(successV interface{}) (*http.Response, error) { // Receive creates a new HTTP request and returns the response. Success // responses (2XX) are JSON decoded into the value pointed to by successV and // other responses are JSON decoded into the value pointed to by failureV. -// Any error creating the request, sending it, or decoding the response is -// returned. +// If the status code of response is 204(no content) or the Content-Lenght is 0, +// decoding is skipped. Any error creating the request, sending it, or decoding +// the response is returned. // Receive is shorthand for calling Request and Do. func (s *Sling) Receive(successV, failureV interface{}) (*http.Response, error) { req, err := s.Request() @@ -361,7 +374,9 @@ func (s *Sling) Receive(successV, failureV interface{}) (*http.Response, error) // Do sends an HTTP request and returns the response. Success responses (2XX) // are JSON decoded into the value pointed to by successV and other responses // are JSON decoded into the value pointed to by failureV. -// Any error sending the request or decoding the response is returned. +// If the status code of response is 204(no content) or the Content-Length is 0, +// decoding is skipped. Any error sending the request or decoding the response +// is returned. func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Response, error) { resp, err := s.httpClient.Do(req) if err != nil { @@ -370,14 +385,20 @@ func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Res // when err is nil, resp contains a non-nil resp.Body which must be closed defer resp.Body.Close() - // Don't try to decode on 204s - if resp.StatusCode == 204 { + // The default HTTP client's Transport may not + // reuse HTTP/1.x "keep-alive" TCP connections if the Body is + // not read to completion and closed. + // See: https://golang.org/pkg/net/http/#Response + defer io.Copy(io.Discard, resp.Body) + + // Don't try to decode on 204s or Content-Length is 0 + if resp.StatusCode == http.StatusNoContent || resp.ContentLength == 0 { return resp, nil } // Decode from json if successV != nil || failureV != nil { - err = decodeResponseJSON(resp, successV, failureV) + err = decodeResponse(resp, s.responseDecoder, successV, failureV) } return resp, err } @@ -387,22 +408,15 @@ func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Res // otherwise. If the successV or failureV argument to decode into is nil, // decoding is skipped. // Caller is responsible for closing the resp.Body. -func decodeResponseJSON(resp *http.Response, successV, failureV interface{}) error { +func decodeResponse(resp *http.Response, decoder ResponseDecoder, successV, failureV interface{}) error { if code := resp.StatusCode; 200 <= code && code <= 299 { if successV != nil { - return decodeResponseBodyJSON(resp, successV) + return decoder.Decode(resp, successV) } } else { if failureV != nil { - return decodeResponseBodyJSON(resp, failureV) + return decoder.Decode(resp, failureV) } } return nil } - -// decodeResponseBodyJSON JSON decodes a Response Body into the value pointed -// to by v. -// Caller must provide a non-nil v and close the resp.Body. -func decodeResponseBodyJSON(resp *http.Response, v interface{}) error { - return json.NewDecoder(resp.Body).Decode(v) -} diff --git a/vendor/github.com/dghubble/sling/test b/vendor/github.com/dghubble/sling/test deleted file mode 100644 index fa845c625..000000000 --- a/vendor/github.com/dghubble/sling/test +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e - -PKGS=$(go list ./... | grep -v /examples) -FORMATTABLE="$(find . -maxdepth 1 -type d)" -LINTABLE=$(go list ./...) - -go test $PKGS -cover -go vet $PKGS - -echo "Checking gofmt..." -fmtRes=$(gofmt -l $FORMATTABLE) -if [ -n "${fmtRes}" ]; then - echo -e "gofmt checking failed:\n${fmtRes}" - exit 2 -fi - -echo "Checking golint..." -lintRes=$(echo $LINTABLE | xargs -n 1 golint) -if [ -n "${lintRes}" ]; then - echo -e "golint checking failed:\n${lintRes}" - exit 2 -fi \ No newline at end of file diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/fsnotify/fsnotify/.editorconfig deleted file mode 100644 index fad895851..000000000 --- a/vendor/github.com/fsnotify/fsnotify/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -root = true - -[*.go] -indent_style = tab -indent_size = 4 -insert_final_newline = true - -[*.{yml,yaml}] -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes deleted file mode 100644 index 32f1001be..000000000 --- a/vendor/github.com/fsnotify/fsnotify/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -go.sum linguist-generated diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore index 4cd0cbaf4..daea9dd6d 100644 --- a/vendor/github.com/fsnotify/fsnotify/.gitignore +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -1,6 +1,10 @@ -# Setup a Global .gitignore for OS and editor generated files: -# https://help.github.com/articles/ignoring-files -# git config --global core.excludesfile ~/.gitignore_global +# go test -c output +*.test +*.test.exe -.vagrant -*.sublime-project +# Output of go build ./cmd/fsnotify +/fsnotify +/fsnotify.exe + +/test/kqueue +/test/a.out diff --git a/vendor/github.com/fsnotify/fsnotify/AUTHORS b/vendor/github.com/fsnotify/fsnotify/AUTHORS deleted file mode 100644 index 6cbabe5ef..000000000 --- a/vendor/github.com/fsnotify/fsnotify/AUTHORS +++ /dev/null @@ -1,62 +0,0 @@ -# Names should be added to this file as -# Name or Organization -# The email address is not required for organizations. - -# You can update this list using the following command: -# -# $ (head -n10 AUTHORS && git shortlog -se | sed -E 's/^\s+[0-9]+\t//') | tee AUTHORS - -# Please keep the list sorted. - -Aaron L -Adrien Bustany -Alexey Kazakov -Amit Krishnan -Anmol Sethi -Bjørn Erik Pedersen -Brian Goff -Bruno Bigras -Caleb Spare -Case Nelson -Chris Howey -Christoffer Buchholz -Daniel Wagner-Hall -Dave Cheney -Eric Lin -Evan Phoenix -Francisco Souza -Gautam Dey -Hari haran -Ichinose Shogo -Johannes Ebke -John C Barstow -Kelvin Fo -Ken-ichirou MATSUZAWA -Matt Layher -Matthias Stone -Nathan Youngman -Nickolai Zeldovich -Oliver Bristow -Patrick -Paul Hammond -Pawel Knap -Pieter Droogendijk -Pratik Shinde -Pursuit92 -Riku Voipio -Rob Figueiredo -Rodrigo Chiossi -Slawek Ligus -Soge Zhang -Tiffany Jernigan -Tilak Sharma -Tobias Klauser -Tom Payne -Travis Cline -Tudor Golubenco -Vahe Khachikyan -Yukang -bronze1man -debrando -henrikedwards -铁哥 diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index cc01c08f5..fa854785d 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,11 +1,199 @@ # Changelog -All notable changes to this project will be documented in this file. +1.8.0 2023-10-31 +---------------- -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### Additions -## [Unreleased] +- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619]) + +### Changes and fixes + +- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610]) + +- kqueue: ignore events with Ident=0 ([#590]) + +- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617]) + +- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625]) + +- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620]) + +- inotify: fix panic when calling Remove() in a goroutine ([#650]) + +- fen: allow watching subdirectories of watched directories ([#621]) + +[#590]: https://github.com/fsnotify/fsnotify/pull/590 +[#610]: https://github.com/fsnotify/fsnotify/pull/610 +[#617]: https://github.com/fsnotify/fsnotify/pull/617 +[#619]: https://github.com/fsnotify/fsnotify/pull/619 +[#620]: https://github.com/fsnotify/fsnotify/pull/620 +[#621]: https://github.com/fsnotify/fsnotify/pull/621 +[#625]: https://github.com/fsnotify/fsnotify/pull/625 +[#650]: https://github.com/fsnotify/fsnotify/pull/650 + +1.7.0 - 2023-10-22 +------------------ +This version of fsnotify needs Go 1.17. + +### Additions + +- illumos: add FEN backend to support illumos and Solaris. ([#371]) + +- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful + in cases where you can't control the kernel buffer and receive a large number + of events in bursts. ([#550], [#572]) + +- all: add `AddWith()`, which is identical to `Add()` but allows passing + options. ([#521]) + +- windows: allow setting the ReadDirectoryChangesW() buffer size with + `fsnotify.WithBufferSize()`; the default of 64K is the highest value that + works on all platforms and is enough for most purposes, but in some cases a + highest buffer is needed. ([#521]) + +### Changes and fixes + +- inotify: remove watcher if a watched path is renamed ([#518]) + + After a rename the reported name wasn't updated, or even an empty string. + Inotify doesn't provide any good facilities to update it, so just remove the + watcher. This is already how it worked on kqueue and FEN. + + On Windows this does work, and remains working. + +- windows: don't listen for file attribute changes ([#520]) + + File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API, + with no way to see if they're a file write or attribute change, so would show + up as a fsnotify.Write event. This is never useful, and could result in many + spurious Write events. + +- windows: return `ErrEventOverflow` if the buffer is full ([#525]) + + Before it would merely return "short read", making it hard to detect this + error. + +- kqueue: make sure events for all files are delivered properly when removing a + watched directory ([#526]) + + Previously they would get sent with `""` (empty string) or `"."` as the path + name. + +- kqueue: don't emit spurious Create events for symbolic links ([#524]) + + The link would get resolved but kqueue would "forget" it already saw the link + itself, resulting on a Create for every Write event for the directory. + +- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516]) + +- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in + `backend_other.go`, making it easier to use on unsupported platforms such as + WASM, AIX, etc. ([#528]) + +- other: use the `backend_other.go` no-op if the `appengine` build tag is set; + Google AppEngine forbids usage of the unsafe package so the inotify backend + won't compile there. + +[#371]: https://github.com/fsnotify/fsnotify/pull/371 +[#516]: https://github.com/fsnotify/fsnotify/pull/516 +[#518]: https://github.com/fsnotify/fsnotify/pull/518 +[#520]: https://github.com/fsnotify/fsnotify/pull/520 +[#521]: https://github.com/fsnotify/fsnotify/pull/521 +[#524]: https://github.com/fsnotify/fsnotify/pull/524 +[#525]: https://github.com/fsnotify/fsnotify/pull/525 +[#526]: https://github.com/fsnotify/fsnotify/pull/526 +[#528]: https://github.com/fsnotify/fsnotify/pull/528 +[#537]: https://github.com/fsnotify/fsnotify/pull/537 +[#550]: https://github.com/fsnotify/fsnotify/pull/550 +[#572]: https://github.com/fsnotify/fsnotify/pull/572 + +1.6.0 - 2022-10-13 +------------------ +This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1, +but not documented). It also increases the minimum Linux version to 2.6.32. + +### Additions + +- all: add `Event.Has()` and `Op.Has()` ([#477]) + + This makes checking events a lot easier; for example: + + if event.Op&Write == Write && !(event.Op&Remove == Remove) { + } + + Becomes: + + if event.Has(Write) && !event.Has(Remove) { + } + +- all: add cmd/fsnotify ([#463]) + + A command-line utility for testing and some examples. + +### Changes and fixes + +- inotify: don't ignore events for files that don't exist ([#260], [#470]) + + Previously the inotify watcher would call `os.Lstat()` to check if a file + still exists before emitting events. + + This was inconsistent with other platforms and resulted in inconsistent event + reporting (e.g. when a file is quickly removed and re-created), and generally + a source of confusion. It was added in 2013 to fix a memory leak that no + longer exists. + +- all: return `ErrNonExistentWatch` when `Remove()` is called on a path that's + not watched ([#460]) + +- inotify: replace epoll() with non-blocking inotify ([#434]) + + Non-blocking inotify was not generally available at the time this library was + written in 2014, but now it is. As a result, the minimum Linux version is + bumped from 2.6.27 to 2.6.32. This hugely simplifies the code and is faster. + +- kqueue: don't check for events every 100ms ([#480]) + + The watcher would wake up every 100ms, even when there was nothing to do. Now + it waits until there is something to do. + +- macos: retry opening files on EINTR ([#475]) + +- kqueue: skip unreadable files ([#479]) + + kqueue requires a file descriptor for every file in a directory; this would + fail if a file was unreadable by the current user. Now these files are simply + skipped. + +- windows: fix renaming a watched directory if the parent is also watched ([#370]) + +- windows: increase buffer size from 4K to 64K ([#485]) + +- windows: close file handle on Remove() ([#288]) + +- kqueue: put pathname in the error if watching a file fails ([#471]) + +- inotify, windows: calling Close() more than once could race ([#465]) + +- kqueue: improve Close() performance ([#233]) + +- all: various documentation additions and clarifications. + +[#233]: https://github.com/fsnotify/fsnotify/pull/233 +[#260]: https://github.com/fsnotify/fsnotify/pull/260 +[#288]: https://github.com/fsnotify/fsnotify/pull/288 +[#370]: https://github.com/fsnotify/fsnotify/pull/370 +[#434]: https://github.com/fsnotify/fsnotify/pull/434 +[#460]: https://github.com/fsnotify/fsnotify/pull/460 +[#463]: https://github.com/fsnotify/fsnotify/pull/463 +[#465]: https://github.com/fsnotify/fsnotify/pull/465 +[#470]: https://github.com/fsnotify/fsnotify/pull/470 +[#471]: https://github.com/fsnotify/fsnotify/pull/471 +[#475]: https://github.com/fsnotify/fsnotify/pull/475 +[#477]: https://github.com/fsnotify/fsnotify/pull/477 +[#479]: https://github.com/fsnotify/fsnotify/pull/479 +[#480]: https://github.com/fsnotify/fsnotify/pull/480 +[#485]: https://github.com/fsnotify/fsnotify/pull/485 ## [1.5.4] - 2022-04-25 @@ -40,6 +228,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#385](https://github.com/fsnotify/fsnotify/pull/385) * Go 1.14+: Fix unsafe pointer conversion [#325](https://github.com/fsnotify/fsnotify/pull/325) +## [1.4.9] - 2020-03-11 + +* Move example usage to the readme #329. This may resolve #328. + +## [1.4.8] - 2020-03-10 + +* CI: test more go versions (@nathany 1d13583d846ea9d66dcabbfefbfb9d8e6fb05216) +* Tests: Queued inotify events could have been read by the test before max_queued_events was hit (@matthias-stone #265) +* Tests: t.Fatalf -> t.Errorf in go routines (@gdey #266) +* CI: Less verbosity (@nathany #267) +* Tests: Darwin: Exchangedata is deprecated on 10.13 (@nathany #267) +* Tests: Check if channels are closed in the example (@alexeykazakov #244) +* CI: Only run golint on latest version of go and fix issues (@cpuguy83 #284) +* CI: Add windows to travis matrix (@cpuguy83 #284) +* Docs: Remover appveyor badge (@nathany 11844c0959f6fff69ba325d097fce35bd85a8e93) +* Linux: create epoll and pipe fds with close-on-exec (@JohannesEbke #219) +* Linux: open files with close-on-exec (@linxiulei #273) +* Docs: Plan to support fanotify (@nathany ab058b44498e8b7566a799372a39d150d9ea0119 ) +* Project: Add go.mod (@nathany #309) +* Project: Revise editor config (@nathany #309) +* Project: Update copyright for 2019 (@nathany #309) +* CI: Drop go1.8 from CI matrix (@nathany #309) +* Docs: Updating the FAQ section for supportability with NFS & FUSE filesystems (@Pratik32 4bf2d1fec78374803a39307bfb8d340688f4f28e ) + ## [1.4.7] - 2018-01-09 * BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md index 8a642563d..e4ac2a2ff 100644 --- a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md +++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -1,60 +1,144 @@ -# Contributing +Thank you for your interest in contributing to fsnotify! We try to review and +merge PRs in a reasonable timeframe, but please be aware that: -## Issues +- To avoid "wasted" work, please discuss changes on the issue tracker first. You + can just send PRs, but they may end up being rejected for one reason or the + other. -* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues). -* Please indicate the platform you are using fsnotify on. -* A code example to reproduce the problem is appreciated. +- fsnotify is a cross-platform library, and changes must work reasonably well on + all supported platforms. -## Pull Requests +- Changes will need to be compatible; old code should still compile, and the + runtime behaviour can't change in ways that are likely to lead to problems for + users. -### Contributor License Agreement +Testing +------- +Just `go test ./...` runs all the tests; the CI runs this on all supported +platforms. Testing different platforms locally can be done with something like +[goon] or [Vagrant], but this isn't super-easy to set up at the moment. -fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). +Use the `-short` flag to make the "stress test" run faster. -Please indicate that you have signed the CLA in your pull request. +Writing new tests +----------------- +Scripts in the testdata directory allow creating test cases in a "shell-like" +syntax. The basic format is: -### How fsnotify is Developed + script -* Development is done on feature branches. -* Tests are run on BSD, Linux, macOS and Windows. -* Pull requests are reviewed and [applied to master][am] using [hub][]. - * Maintainers may modify or squash commits rather than asking contributors to. -* To issue a new release, the maintainers will: - * Update the CHANGELOG - * Tag a version, which will become available through gopkg.in. - -### How to Fork + Output: + desired output -For smooth sailing, always use the original import path. Installing with `go get` makes this easy. +For example: -1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Ensure everything works and the tests pass (see below) -4. Commit your changes (`git commit -am 'Add some feature'`) + # Create a new empty file with some data. + watch / + echo data >/file -Contribute upstream: + Output: + create /file + write /file -1. Fork fsnotify on GitHub -2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) -3. Push to the branch (`git push fork my-new-feature`) -4. Create a new Pull Request on GitHub +Just create a new file to add a new test; select which tests to run with +`-run TestScript/[path]`. -This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/). +script +------ +The script is a "shell-like" script: -### Testing + cmd arg arg -fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Windows. +Comments are supported with `#`: -Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. + # Comment + cmd arg arg # Comment -### Maintainers +All operations are done in a temp directory; a path like "/foo" is rewritten to +"/tmp/TestFoo/foo". -Help maintaining fsnotify is welcome. To be a maintainer: +Arguments can be quoted with `"` or `'`; there are no escapes and they're +functionally identical right now, but this may change in the future, so best to +assume shell-like rules. -* Submit a pull request and sign the CLA as above. -* You must be able to run the test suite on Mac, Windows, Linux and BSD. + touch "/file with spaces" -All code changes should be internal pull requests. +End-of-line escapes with `\` are not supported. -Releases are tagged using [Semantic Versioning](http://semver.org/). +### Supported commands + + watch path [ops] # Watch the path, reporting events for it. Nothing is + # watched by default. Optionally a list of ops can be + # given, as with AddWith(path, WithOps(...)). + unwatch path # Stop watching the path. + watchlist n # Assert watchlist length. + + stop # Stop running the script; for debugging. + debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in + parallel by default, so -parallel=1 is probably a good + idea). + + touch path + mkdir [-p] dir + ln -s target link # Only ln -s supported. + mkfifo path + mknod dev path + mv src dst + rm [-r] path + chmod mode path # Octal only + sleep time-in-ms + + cat path # Read path (does nothing with the data; just reads it). + echo str >>path # Append "str" to "path". + echo str >path # Truncate "path" and write "str". + + require reason # Skip the test if "reason" is true; "skip" and + skip reason # "require" behave identical; it supports both for + # readability. Possible reasons are: + # + # always Always skip this test. + # symlink Symlinks are supported (requires admin + # permissions on Windows). + # mkfifo Platform doesn't support FIFO named sockets. + # mknod Platform doesn't support device nodes. + + +output +------ +After `Output:` the desired output is given; this is indented by convention, but +that's not required. + +The format of that is: + + # Comment + event path # Comment + + system: + event path + system2: + event path + +Every event is one line, and any whitespace between the event and path are +ignored. The path can optionally be surrounded in ". Anything after a "#" is +ignored. + +Platform-specific tests can be added after GOOS; for example: + + watch / + touch /file + + Output: + # Tested if nothing else matches + create /file + + # Windows-specific test. + windows: + write /file + +You can specify multiple platforms with a comma (e.g. "windows, linux:"). +"kqueue" is a shortcut for all kqueue systems (BSD, macOS). + + +[goon]: https://github.com/arp242/goon +[Vagrant]: https://www.vagrantup.com/ +[integration_test.go]: /integration_test.go diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE index e180c8fb0..fb03ade75 100644 --- a/vendor/github.com/fsnotify/fsnotify/LICENSE +++ b/vendor/github.com/fsnotify/fsnotify/LICENSE @@ -1,28 +1,25 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012-2019 fsnotify Authors. All rights reserved. +Copyright © 2012 The Go Authors. All rights reserved. +Copyright © fsnotify Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index 0731c5ef8..e480733d1 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -1,120 +1,184 @@ -# File system notifications for Go +fsnotify is a Go library to provide cross-platform filesystem notifications on +Windows, Linux, macOS, BSD, and illumos. -[![Go Reference](https://pkg.go.dev/badge/github.com/fsnotify/fsnotify.svg)](https://pkg.go.dev/github.com/fsnotify/fsnotify) [![Go Report Card](https://goreportcard.com/badge/github.com/fsnotify/fsnotify)](https://goreportcard.com/report/github.com/fsnotify/fsnotify) [![Maintainers Wanted](https://img.shields.io/badge/maintainers-wanted-red.svg)](https://github.com/fsnotify/fsnotify/issues/413) +Go 1.17 or newer is required; the full documentation is at +https://pkg.go.dev/github.com/fsnotify/fsnotify -fsnotify utilizes [`golang.org/x/sys`](https://pkg.go.dev/golang.org/x/sys) rather than [`syscall`](https://pkg.go.dev/syscall) from the standard library. +--- -Cross platform: Windows, Linux, BSD and macOS. +Platform support: -| Adapter | OS | Status | -| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| inotify | Linux 2.6.27 or later, Android\* | Supported | -| kqueue | BSD, macOS, iOS\* | Supported | -| ReadDirectoryChangesW | Windows | Supported | -| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | -| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) | -| fanotify | Linux 2.6.37+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) | -| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | -| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | +| Backend | OS | Status | +| :-------------------- | :--------- | :------------------------------------------------------------------------ | +| inotify | Linux | Supported | +| kqueue | BSD, macOS | Supported | +| ReadDirectoryChangesW | Windows | Supported | +| FEN | illumos | Supported | +| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) | +| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment | +| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] | +| USN Journals | Windows | [Needs support in x/sys/windows][usn] | +| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) | -\* Android and iOS are untested. +Linux and illumos should include Android and Solaris, but these are currently +untested. -Please see [the documentation](https://pkg.go.dev/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information. +[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120 +[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847 +[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129 -## API stability - -fsnotify is a fork of [howeyc/fsnotify](https://github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA). - -All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). - -## Usage +Usage +----- +A basic example: ```go package main import ( - "log" + "log" - "github.com/fsnotify/fsnotify" + "github.com/fsnotify/fsnotify" ) func main() { - watcher, err := fsnotify.NewWatcher() - if err != nil { - log.Fatal(err) - } - defer watcher.Close() - - done := make(chan bool) - go func() { - for { - select { - case event, ok := <-watcher.Events: - if !ok { - return - } - log.Println("event:", event) - if event.Op&fsnotify.Write == fsnotify.Write { - log.Println("modified file:", event.Name) - } - case err, ok := <-watcher.Errors: - if !ok { - return - } - log.Println("error:", err) - } - } - }() - - err = watcher.Add("/tmp/foo") - if err != nil { - log.Fatal(err) - } - <-done + // Create new watcher. + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + // Start listening for events. + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + log.Println("event:", event) + if event.Has(fsnotify.Write) { + log.Println("modified file:", event.Name) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Println("error:", err) + } + } + }() + + // Add a path. + err = watcher.Add("/tmp") + if err != nil { + log.Fatal(err) + } + + // Block main goroutine forever. + <-make(chan struct{}) } ``` -## Contributing +Some more examples can be found in [cmd/fsnotify](cmd/fsnotify), which can be +run with: + + % go run ./cmd/fsnotify -Please refer to [CONTRIBUTING][] before opening an issue or pull request. +Further detailed documentation can be found in godoc: +https://pkg.go.dev/github.com/fsnotify/fsnotify -## FAQ +FAQ +--- +### Will a file still be watched when it's moved to another directory? +No, not unless you are watching the location it was moved to. -**When a file is moved to another directory is it still being watched?** +### Are subdirectories watched? +No, you must add watches for any directory you want to watch (a recursive +watcher is on the roadmap: [#18]). -No (it shouldn't be, unless you are watching where it was moved to). +[#18]: https://github.com/fsnotify/fsnotify/issues/18 -**When I watch a directory, are all subdirectories watched as well?** +### Do I have to watch the Error and Event channels in a goroutine? +Yes. You can read both channels in the same goroutine using `select` (you don't +need a separate goroutine for both channels; see the example). -No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap [#18][]). +### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys? +fsnotify requires support from underlying OS to work. The current NFS and SMB +protocols does not provide network level support for file notifications, and +neither do the /proc and /sys virtual filesystems. -**Do I have to watch the Error and Event channels in a separate goroutine?** +This could be fixed with a polling watcher ([#9]), but it's not yet implemented. -As of now, yes. Looking into making this single-thread friendly (see [howeyc #7][#7]) +[#9]: https://github.com/fsnotify/fsnotify/issues/9 -**Why am I receiving multiple events for the same file on OS X?** +### Why do I get many Chmod events? +Some programs may generate a lot of attribute changes; for example Spotlight on +macOS, anti-virus programs, backup applications, and some others are known to do +this. As a rule, it's typically best to ignore Chmod events. They're often not +useful, and tend to cause problems. -Spotlight indexing on OS X can result in multiple events (see [howeyc #62][#62]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#11][]). +Spotlight indexing on macOS can result in multiple events (see [#15]). A +temporary workaround is to add your folder(s) to the *Spotlight Privacy +settings* until we have a native FSEvents implementation (see [#11]). -**How many files can be watched at once?** +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#15]: https://github.com/fsnotify/fsnotify/issues/15 -There are OS-specific limits as to how many watches can be created: -* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. -* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. +### Watching a file doesn't work well +Watching individual files (rather than directories) is generally not recommended +as many programs (especially editors) update files atomically: it will write to +a temporary file which is then moved to to destination, overwriting the original +(or some variant thereof). The watcher on the original file is now lost, as that +no longer exists. -**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?** +The upshot of this is that a power failure or crash won't leave a half-written +file. -fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications. +Watch the parent directory and use `Event.Name` to filter out files you're not +interested in. There is an example of this in `cmd/fsnotify/file.go`. -[#62]: https://github.com/howeyc/fsnotify/issues/62 -[#18]: https://github.com/fsnotify/fsnotify/issues/18 -[#11]: https://github.com/fsnotify/fsnotify/issues/11 -[#7]: https://github.com/howeyc/fsnotify/issues/7 +Platform-specific notes +----------------------- +### Linux +When a file is removed a REMOVE event won't be emitted until all file +descriptors are closed; it will emit a CHMOD instead: + + fp := os.Open("file") + os.Remove("file") // CHMOD + fp.Close() // REMOVE + +This is the event that inotify sends, so not much can be changed about this. + +The `fs.inotify.max_user_watches` sysctl variable specifies the upper limit for +the number of watches per user, and `fs.inotify.max_user_instances` specifies +the maximum number of inotify instances per user. Every Watcher you create is an +"instance", and every path you add is a "watch". + +These are also exposed in `/proc` as `/proc/sys/fs/inotify/max_user_watches` and +`/proc/sys/fs/inotify/max_user_instances` + +To increase them you can use `sysctl` or write the value to proc file: + + # The default values on Linux 5.18 + sysctl fs.inotify.max_user_watches=124983 + sysctl fs.inotify.max_user_instances=128 + +To make the changes persist on reboot edit `/etc/sysctl.conf` or +`/usr/lib/sysctl.d/50-default.conf` (details differ per Linux distro; check your +distro's documentation): -[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md + fs.inotify.max_user_watches=124983 + fs.inotify.max_user_instances=128 -## Related Projects +Reaching the limit will result in a "no space left on device" or "too many open +files" error. -* [notify](https://github.com/rjeczalik/notify) -* [fsevents](https://github.com/fsnotify/fsevents) +### kqueue (macOS, all BSD systems) +kqueue requires opening a file descriptor for every file that's being watched; +so if you're watching a directory with five files then that's six file +descriptors. You will run in to your system's "max open files" limit faster on +these platforms. +The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to +control the maximum number of open files. diff --git a/vendor/github.com/fsnotify/fsnotify/fen.go b/vendor/github.com/fsnotify/fsnotify/fen.go deleted file mode 100644 index b3ac3d8f5..000000000 --- a/vendor/github.com/fsnotify/fsnotify/fen.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build solaris -// +build solaris - -package fsnotify - -import ( - "errors" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - return nil -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - return nil -} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 0f4ee52e8..0760efe91 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -1,69 +1,494 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !plan9 -// +build !plan9 - -// Package fsnotify provides a platform-independent interface for file system notifications. +// Package fsnotify provides a cross-platform interface for file system +// notifications. +// +// Currently supported systems: +// +// - Linux via inotify +// - BSD, macOS via kqueue +// - Windows via ReadDirectoryChangesW +// - illumos via FEN +// +// # FSNOTIFY_DEBUG +// +// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to +// stderr. This can be useful to track down some problems, especially in cases +// where fsnotify is used as an indirect dependency. +// +// Every event will be printed as soon as there's something useful to print, +// with as little processing from fsnotify. +// +// Example output: +// +// FSNOTIFY_DEBUG: 11:34:23.633087586 256:IN_CREATE → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:23.633202319 4:IN_ATTRIB → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:28.989728764 512:IN_DELETE → "/tmp/file-1" package fsnotify import ( - "bytes" "errors" "fmt" + "os" + "path/filepath" + "strings" ) -// Event represents a single file system notification. +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # Windows notes +// +// Paths can be added as "C:\\path\\to\\dir", but forward slashes +// ("C:/path/to/dir") will also work. +// +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all files, sometimes it will send no +// events, and often only for some files. +// +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. +type Watcher struct { + b backend + + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // when a file is truncated. On Windows it's never + // sent. + Events chan Event + + // Errors sends any errors. + Errors chan error +} + +// Event represents a file system notification. type Event struct { - Name string // Relative path to the file or directory. - Op Op // File operation that triggered the event. + // Path to the file or directory. + // + // Paths are relative to the input; for example with Add("dir") the Name + // will be set to "dir/file" if you create that file, but if you use + // Add("/path/to/dir") it will be "/path/to/dir/file". + Name string + + // File operation that triggered the event. + // + // This is a bitmask and some systems may send multiple operations at once. + // Use the Event.Has() method instead of comparing with ==. + Op Op + + // Create events will have this set to the old path if it's a rename. This + // only works when both the source and destination are watched. It's not + // reliable when watching individual files, only directories. + // + // For example "mv /tmp/file /tmp/rename" will emit: + // + // Event{Op: Rename, Name: "/tmp/file"} + // Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"} + renamedFrom string } // Op describes a set of file operations. type Op uint32 -// These are the generalized file operations that can trigger a notification. +// The operations fsnotify can trigger; see the documentation on [Watcher] for a +// full description, and check them with [Event.Has]. const ( + // A new pathname was created. Create Op = 1 << iota + + // The pathname was written to; this does *not* mean the write has finished, + // and a write can be followed by more writes. Write + + // The path was removed; any watches on it will be removed. Some "remove" + // operations may trigger a Rename if the file is actually moved (for + // example "remove to trash" is often a rename). Remove + + // The path was renamed to something else; any watches on it will be + // removed. Rename + + // File attributes were changed. + // + // It's generally not recommended to take action on this event, as it may + // get triggered very frequently by some software. For example, Spotlight + // indexing on macOS, anti-virus software, backup software, etc. Chmod + + // File descriptor was opened. + // + // Only works on Linux and FreeBSD. + xUnportableOpen + + // File was read from. + // + // Only works on Linux and FreeBSD. + xUnportableRead + + // File opened for writing was closed. + // + // Only works on Linux and FreeBSD. + // + // The advantage of using this over Write is that it's more reliable than + // waiting for Write events to stop. It's also faster (if you're not + // listening to Write events): copying a file of a few GB can easily + // generate tens of thousands of Write events in a short span of time. + xUnportableCloseWrite + + // File opened for reading was closed. + // + // Only works on Linux and FreeBSD. + xUnportableCloseRead ) -func (op Op) String() string { - // Use a buffer for efficient string concatenation - var buffer bytes.Buffer +var ( + // ErrNonExistentWatch is used when Remove() is called on a path that's not + // added. + ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch") + + // ErrClosed is used when trying to operate on a closed Watcher. + ErrClosed = errors.New("fsnotify: watcher already closed") + + // ErrEventOverflow is reported from the Errors channel when there are too + // many events: + // + // - inotify: inotify returns IN_Q_OVERFLOW – because there are too + // many queued events (the fs.inotify.max_queued_events + // sysctl can be used to increase this). + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. + ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow") + + // ErrUnsupported is returned by AddWith() when WithOps() specified an + // Unportable event that's not supported on this platform. + xErrUnsupported = errors.New("fsnotify: not supported with this backend") +) + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBackend(ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBufferedBackend(sz, ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. +// +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(path string) error { return w.b.Add(path) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) } + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) Remove(path string) error { return w.b.Remove(path) } + +// Close removes all watches and closes the Events channel. +func (w *Watcher) Close() error { return w.b.Close() } - if op&Create == Create { - buffer.WriteString("|CREATE") +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) WatchList() []string { return w.b.WatchList() } + +// Supports reports if all the listed operations are supported by this platform. +// +// Create, Write, Remove, Rename, and Chmod are always supported. It can only +// return false for an Op starting with Unportable. +func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) } + +func (o Op) String() string { + var b strings.Builder + if o.Has(Create) { + b.WriteString("|CREATE") + } + if o.Has(Remove) { + b.WriteString("|REMOVE") + } + if o.Has(Write) { + b.WriteString("|WRITE") } - if op&Remove == Remove { - buffer.WriteString("|REMOVE") + if o.Has(xUnportableOpen) { + b.WriteString("|OPEN") } - if op&Write == Write { - buffer.WriteString("|WRITE") + if o.Has(xUnportableRead) { + b.WriteString("|READ") } - if op&Rename == Rename { - buffer.WriteString("|RENAME") + if o.Has(xUnportableCloseWrite) { + b.WriteString("|CLOSE_WRITE") } - if op&Chmod == Chmod { - buffer.WriteString("|CHMOD") + if o.Has(xUnportableCloseRead) { + b.WriteString("|CLOSE_READ") } - if buffer.Len() == 0 { - return "" + if o.Has(Rename) { + b.WriteString("|RENAME") } - return buffer.String()[1:] // Strip leading pipe + if o.Has(Chmod) { + b.WriteString("|CHMOD") + } + if b.Len() == 0 { + return "[no events]" + } + return b.String()[1:] } -// String returns a string representation of the event in the form -// "file: REMOVE|WRITE|..." +// Has reports if this operation has the given operation. +func (o Op) Has(h Op) bool { return o&h != 0 } + +// Has reports if this event has the given operation. +func (e Event) Has(op Op) bool { return e.Op.Has(op) } + +// String returns a string representation of the event with their path. func (e Event) String() string { - return fmt.Sprintf("%q: %s", e.Name, e.Op.String()) + if e.renamedFrom != "" { + return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom) + } + return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name) } -// Common errors that can be reported by a watcher -var ( - ErrEventOverflow = errors.New("fsnotify queue overflow") +type ( + backend interface { + Add(string) error + AddWith(string, ...addOpt) error + Remove(string) error + WatchList() []string + Close() error + xSupports(Op) bool + } + addOpt func(opt *withOpts) + withOpts struct { + bufsize int + op Op + noFollow bool + sendCreate bool + } ) + +var debug = func() bool { + // Check for exactly "1" (rather than mere existence) so we can add + // options/flags in the future. I don't know if we ever want that, but it's + // nice to leave the option open. + return os.Getenv("FSNOTIFY_DEBUG") == "1" +}() + +var defaultOpts = withOpts{ + bufsize: 65536, // 64K + op: Create | Write | Remove | Rename | Chmod, +} + +func getOptions(opts ...addOpt) withOpts { + with := defaultOpts + for _, o := range opts { + if o != nil { + o(&with) + } + } + return with +} + +// WithBufferSize sets the [ReadDirectoryChangesW] buffer size. +// +// This only has effect on Windows systems, and is a no-op for other backends. +// +// The default value is 64K (65536 bytes) which is the highest value that works +// on all filesystems and should be enough for most applications, but if you +// have a large burst of events it may not be enough. You can increase it if +// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]). +// +// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw +func WithBufferSize(bytes int) addOpt { + return func(opt *withOpts) { opt.bufsize = bytes } +} + +// WithOps sets which operations to listen for. The default is [Create], +// [Write], [Remove], [Rename], and [Chmod]. +// +// Excluding operations you're not interested in can save quite a bit of CPU +// time; in some use cases there may be hundreds of thousands of useless Write +// or Chmod operations per second. +// +// This can also be used to add unportable operations not supported by all +// platforms; unportable operations all start with "Unportable": +// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and +// [UnportableCloseRead]. +// +// AddWith returns an error when using an unportable operation that's not +// supported. Use [Watcher.Support] to check for support. +func withOps(op Op) addOpt { + return func(opt *withOpts) { opt.op = op } +} + +// WithNoFollow disables following symlinks, so the symlinks themselves are +// watched. +func withNoFollow() addOpt { + return func(opt *withOpts) { opt.noFollow = true } +} + +// "Internal" option for recursive watches on inotify. +func withCreate() addOpt { + return func(opt *withOpts) { opt.sendCreate = true } +} + +var enableRecurse = false + +// Check if this path is recursive (ends with "/..." or "\..."), and return the +// path with the /... stripped. +func recursivePath(path string) (string, bool) { + path = filepath.Clean(path) + if !enableRecurse { // Only enabled in tests for now. + return path, false + } + if filepath.Base(path) == "..." { + return filepath.Dir(path), true + } + return path, false +} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go b/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go deleted file mode 100644 index 596885598..000000000 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows -// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows - -package fsnotify - -import ( - "fmt" - "runtime" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct{} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - return nil -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - return nil -} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify.go b/vendor/github.com/fsnotify/fsnotify/inotify.go deleted file mode 100644 index a6d0e0ec8..000000000 --- a/vendor/github.com/fsnotify/fsnotify/inotify.go +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux -// +build linux - -package fsnotify - -import ( - "errors" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "sync" - "unsafe" - - "golang.org/x/sys/unix" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - mu sync.Mutex // Map access - fd int - poller *fdPoller - watches map[string]*watch // Map of inotify watches (key: path) - paths map[int]string // Map of watched paths (key: watch descriptor) - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - doneResp chan struct{} // Channel to respond to Close -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - // Create inotify fd - fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC) - if fd == -1 { - return nil, errno - } - // Create epoll - poller, err := newFdPoller(fd) - if err != nil { - unix.Close(fd) - return nil, err - } - w := &Watcher{ - fd: fd, - poller: poller, - watches: make(map[string]*watch), - paths: make(map[int]string), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), - doneResp: make(chan struct{}), - } - - go w.readEvents() - return w, nil -} - -func (w *Watcher) isClosed() bool { - select { - case <-w.done: - return true - default: - return false - } -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - if w.isClosed() { - return nil - } - - // Send 'close' signal to goroutine, and set the Watcher to closed. - close(w.done) - - // Wake up goroutine - w.poller.wake() - - // Wait for goroutine to close - <-w.doneResp - - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - name = filepath.Clean(name) - if w.isClosed() { - return errors.New("inotify instance already closed") - } - - const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | - unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | - unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF - - var flags uint32 = agnosticEvents - - w.mu.Lock() - defer w.mu.Unlock() - watchEntry := w.watches[name] - if watchEntry != nil { - flags |= watchEntry.flags | unix.IN_MASK_ADD - } - wd, errno := unix.InotifyAddWatch(w.fd, name, flags) - if wd == -1 { - return errno - } - - if watchEntry == nil { - w.watches[name] = &watch{wd: uint32(wd), flags: flags} - w.paths[wd] = name - } else { - watchEntry.wd = uint32(wd) - watchEntry.flags = flags - } - - return nil -} - -// Remove stops watching the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - - // Fetch the watch. - w.mu.Lock() - defer w.mu.Unlock() - watch, ok := w.watches[name] - - // Remove it from inotify. - if !ok { - return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) - } - - // We successfully removed the watch if InotifyRmWatch doesn't return an - // error, we need to clean up our internal state to ensure it matches - // inotify's kernel state. - delete(w.paths, int(watch.wd)) - delete(w.watches, name) - - // inotify_rm_watch will return EINVAL if the file has been deleted; - // the inotify will already have been removed. - // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously - // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE - // so that EINVAL means that the wd is being rm_watch()ed or its file removed - // by another thread and we have not received IN_IGNORE event. - success, errno := unix.InotifyRmWatch(w.fd, watch.wd) - if success == -1 { - // TODO: Perhaps it's not helpful to return an error here in every case. - // the only two possible errors are: - // EBADF, which happens when w.fd is not a valid file descriptor of any kind. - // EINVAL, which is when fd is not an inotify descriptor or wd is not a valid watch descriptor. - // Watch descriptors are invalidated when they are removed explicitly or implicitly; - // explicitly by inotify_rm_watch, implicitly when the file they are watching is deleted. - return errno - } - - return nil -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { - entries = append(entries, pathname) - } - - return entries -} - -type watch struct { - wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) - flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) -} - -// readEvents reads from the inotify file descriptor, converts the -// received events into Event objects and sends them via the Events channel -func (w *Watcher) readEvents() { - var ( - buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events - n int // Number of bytes read with read() - errno error // Syscall errno - ok bool // For poller.wait - ) - - defer close(w.doneResp) - defer close(w.Errors) - defer close(w.Events) - defer unix.Close(w.fd) - defer w.poller.close() - - for { - // See if we have been closed. - if w.isClosed() { - return - } - - ok, errno = w.poller.wait() - if errno != nil { - select { - case w.Errors <- errno: - case <-w.done: - return - } - continue - } - - if !ok { - continue - } - - n, errno = unix.Read(w.fd, buf[:]) - // If a signal interrupted execution, see if we've been asked to close, and try again. - // http://man7.org/linux/man-pages/man7/signal.7.html : - // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" - if errno == unix.EINTR { - continue - } - - // unix.Read might have been woken up by Close. If so, we're done. - if w.isClosed() { - return - } - - if n < unix.SizeofInotifyEvent { - var err error - if n == 0 { - // If EOF is received. This should really never happen. - err = io.EOF - } else if n < 0 { - // If an error occurred while reading. - err = errno - } else { - // Read was too short. - err = errors.New("notify: short read in readEvents()") - } - select { - case w.Errors <- err: - case <-w.done: - return - } - continue - } - - var offset uint32 - // We don't know how many events we just read into the buffer - // While the offset points to at least one whole event... - for offset <= uint32(n-unix.SizeofInotifyEvent) { - // Point "raw" to the event in the buffer - raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) - - mask := uint32(raw.Mask) - nameLen := uint32(raw.Len) - - if mask&unix.IN_Q_OVERFLOW != 0 { - select { - case w.Errors <- ErrEventOverflow: - case <-w.done: - return - } - } - - // If the event happened to the watched directory or the watched file, the kernel - // doesn't append the filename to the event, but we would like to always fill the - // the "Name" field with a valid filename. We retrieve the path of the watch from - // the "paths" map. - w.mu.Lock() - name, ok := w.paths[int(raw.Wd)] - // IN_DELETE_SELF occurs when the file/directory being watched is removed. - // This is a sign to clean up the maps, otherwise we are no longer in sync - // with the inotify kernel state which has already deleted the watch - // automatically. - if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { - delete(w.paths, int(raw.Wd)) - delete(w.watches, name) - } - w.mu.Unlock() - - if nameLen > 0 { - // Point "bytes" at the first byte of the filename - bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] - // The filename is padded with NULL bytes. TrimRight() gets rid of those. - name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") - } - - event := newEvent(name, mask) - - // Send the events that are not ignored on the events channel - if !event.ignoreLinux(mask) { - select { - case w.Events <- event: - case <-w.done: - return - } - } - - // Move to the next event in the buffer - offset += unix.SizeofInotifyEvent + nameLen - } - } -} - -// Certain types of events can be "ignored" and not sent over the Events -// channel. Such as events marked ignore by the kernel, or MODIFY events -// against files that do not exist. -func (e *Event) ignoreLinux(mask uint32) bool { - // Ignore anything the inotify API says to ignore - if mask&unix.IN_IGNORED == unix.IN_IGNORED { - return true - } - - // If the event is not a DELETE or RENAME, the file must exist. - // Otherwise the event is ignored. - // *Note*: this was put in place because it was seen that a MODIFY - // event was sent after the DELETE. This ignores that MODIFY and - // assumes a DELETE will come or has come if the file doesn't exist. - if !(e.Op&Remove == Remove || e.Op&Rename == Rename) { - _, statErr := os.Lstat(e.Name) - return os.IsNotExist(statErr) - } - return false -} - -// newEvent returns an platform-independent Event based on an inotify mask. -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { - e.Op |= Create - } - if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { - e.Op |= Remove - } - if mask&unix.IN_MODIFY == unix.IN_MODIFY { - e.Op |= Write - } - if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { - e.Op |= Rename - } - if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { - e.Op |= Chmod - } - return e -} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go deleted file mode 100644 index b572a37c3..000000000 --- a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux -// +build linux - -package fsnotify - -import ( - "errors" - - "golang.org/x/sys/unix" -) - -type fdPoller struct { - fd int // File descriptor (as returned by the inotify_init() syscall) - epfd int // Epoll file descriptor - pipe [2]int // Pipe for waking up -} - -func emptyPoller(fd int) *fdPoller { - poller := new(fdPoller) - poller.fd = fd - poller.epfd = -1 - poller.pipe[0] = -1 - poller.pipe[1] = -1 - return poller -} - -// Create a new inotify poller. -// This creates an inotify handler, and an epoll handler. -func newFdPoller(fd int) (*fdPoller, error) { - var errno error - poller := emptyPoller(fd) - defer func() { - if errno != nil { - poller.close() - } - }() - - // Create epoll fd - poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC) - if poller.epfd == -1 { - return nil, errno - } - // Create pipe; pipe[0] is the read end, pipe[1] the write end. - errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC) - if errno != nil { - return nil, errno - } - - // Register inotify fd with epoll - event := unix.EpollEvent{ - Fd: int32(poller.fd), - Events: unix.EPOLLIN, - } - errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event) - if errno != nil { - return nil, errno - } - - // Register pipe fd with epoll - event = unix.EpollEvent{ - Fd: int32(poller.pipe[0]), - Events: unix.EPOLLIN, - } - errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event) - if errno != nil { - return nil, errno - } - - return poller, nil -} - -// Wait using epoll. -// Returns true if something is ready to be read, -// false if there is not. -func (poller *fdPoller) wait() (bool, error) { - // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. - // I don't know whether epoll_wait returns the number of events returned, - // or the total number of events ready. - // I decided to catch both by making the buffer one larger than the maximum. - events := make([]unix.EpollEvent, 7) - for { - n, errno := unix.EpollWait(poller.epfd, events, -1) - if n == -1 { - if errno == unix.EINTR { - continue - } - return false, errno - } - if n == 0 { - // If there are no events, try again. - continue - } - if n > 6 { - // This should never happen. More events were returned than should be possible. - return false, errors.New("epoll_wait returned more events than I know what to do with") - } - ready := events[:n] - epollhup := false - epollerr := false - epollin := false - for _, event := range ready { - if event.Fd == int32(poller.fd) { - if event.Events&unix.EPOLLHUP != 0 { - // This should not happen, but if it does, treat it as a wakeup. - epollhup = true - } - if event.Events&unix.EPOLLERR != 0 { - // If an error is waiting on the file descriptor, we should pretend - // something is ready to read, and let unix.Read pick up the error. - epollerr = true - } - if event.Events&unix.EPOLLIN != 0 { - // There is data to read. - epollin = true - } - } - if event.Fd == int32(poller.pipe[0]) { - if event.Events&unix.EPOLLHUP != 0 { - // Write pipe descriptor was closed, by us. This means we're closing down the - // watcher, and we should wake up. - } - if event.Events&unix.EPOLLERR != 0 { - // If an error is waiting on the pipe file descriptor. - // This is an absolute mystery, and should never ever happen. - return false, errors.New("Error on the pipe descriptor.") - } - if event.Events&unix.EPOLLIN != 0 { - // This is a regular wakeup, so we have to clear the buffer. - err := poller.clearWake() - if err != nil { - return false, err - } - } - } - } - - if epollhup || epollerr || epollin { - return true, nil - } - return false, nil - } -} - -// Close the write end of the poller. -func (poller *fdPoller) wake() error { - buf := make([]byte, 1) - n, errno := unix.Write(poller.pipe[1], buf) - if n == -1 { - if errno == unix.EAGAIN { - // Buffer is full, poller will wake. - return nil - } - return errno - } - return nil -} - -func (poller *fdPoller) clearWake() error { - // You have to be woken up a LOT in order to get to 100! - buf := make([]byte, 100) - n, errno := unix.Read(poller.pipe[0], buf) - if n == -1 { - if errno == unix.EAGAIN { - // Buffer is empty, someone else cleared our wake. - return nil - } - return errno - } - return nil -} - -// Close all poller file descriptors, but not the one passed to it. -func (poller *fdPoller) close() { - if poller.pipe[1] != -1 { - unix.Close(poller.pipe[1]) - } - if poller.pipe[0] != -1 { - unix.Close(poller.pipe[0]) - } - if poller.epfd != -1 { - unix.Close(poller.epfd) - } -} diff --git a/vendor/github.com/fsnotify/fsnotify/kqueue.go b/vendor/github.com/fsnotify/fsnotify/kqueue.go deleted file mode 100644 index 6fb8d8532..000000000 --- a/vendor/github.com/fsnotify/fsnotify/kqueue.go +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd || dragonfly || darwin -// +build freebsd openbsd netbsd dragonfly darwin - -package fsnotify - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sync" - "time" - - "golang.org/x/sys/unix" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - - kq int // File descriptor (as returned by the kqueue() syscall). - - mu sync.Mutex // Protects access to watcher data - watches map[string]int // Map of watched file descriptors (key: path). - externalWatches map[string]bool // Map of watches added by user of the library. - dirFlags map[string]uint32 // Map of watched directories to fflags used in kqueue. - paths map[int]pathInfo // Map file descriptors to path names for processing kqueue events. - fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events). - isClosed bool // Set to true when Close() is first called -} - -type pathInfo struct { - name string - isDir bool -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - kq, err := kqueue() - if err != nil { - return nil, err - } - - w := &Watcher{ - kq: kq, - watches: make(map[string]int), - dirFlags: make(map[string]uint32), - paths: make(map[int]pathInfo), - fileExists: make(map[string]bool), - externalWatches: make(map[string]bool), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), - } - - go w.readEvents() - return w, nil -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return nil - } - w.isClosed = true - - // copy paths to remove while locked - var pathsToRemove = make([]string, 0, len(w.watches)) - for name := range w.watches { - pathsToRemove = append(pathsToRemove, name) - } - w.mu.Unlock() - // unlock before calling Remove, which also locks - - for _, name := range pathsToRemove { - w.Remove(name) - } - - // send a "quit" message to the reader goroutine - close(w.done) - - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - w.mu.Lock() - w.externalWatches[name] = true - w.mu.Unlock() - _, err := w.addWatch(name, noteAllEvents) - return err -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - w.mu.Lock() - watchfd, ok := w.watches[name] - w.mu.Unlock() - if !ok { - return fmt.Errorf("can't remove non-existent kevent watch for: %s", name) - } - - const registerRemove = unix.EV_DELETE - if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil { - return err - } - - unix.Close(watchfd) - - w.mu.Lock() - isDir := w.paths[watchfd].isDir - delete(w.watches, name) - delete(w.paths, watchfd) - delete(w.dirFlags, name) - w.mu.Unlock() - - // Find all watched paths that are in this directory that are not external. - if isDir { - var pathsToRemove []string - w.mu.Lock() - for _, path := range w.paths { - wdir, _ := filepath.Split(path.name) - if filepath.Clean(wdir) == name { - if !w.externalWatches[path.name] { - pathsToRemove = append(pathsToRemove, path.name) - } - } - } - w.mu.Unlock() - for _, name := range pathsToRemove { - // Since these are internal, not much sense in propagating error - // to the user, as that will just confuse them with an error about - // a path they did not explicitly watch themselves. - w.Remove(name) - } - } - - return nil -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { - entries = append(entries, pathname) - } - - return entries -} - -// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) -const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME - -// keventWaitTime to block on each read from kevent -var keventWaitTime = durationToTimespec(100 * time.Millisecond) - -// addWatch adds name to the watched file set. -// The flags are interpreted as described in kevent(2). -// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. -func (w *Watcher) addWatch(name string, flags uint32) (string, error) { - var isDir bool - // Make ./name and name equivalent - name = filepath.Clean(name) - - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return "", errors.New("kevent instance already closed") - } - watchfd, alreadyWatching := w.watches[name] - // We already have a watch, but we can still override flags. - if alreadyWatching { - isDir = w.paths[watchfd].isDir - } - w.mu.Unlock() - - if !alreadyWatching { - fi, err := os.Lstat(name) - if err != nil { - return "", err - } - - // Don't watch sockets. - if fi.Mode()&os.ModeSocket == os.ModeSocket { - return "", nil - } - - // Don't watch named pipes. - if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { - return "", nil - } - - // Follow Symlinks - // Unfortunately, Linux can add bogus symlinks to watch list without - // issue, and Windows can't do symlinks period (AFAIK). To maintain - // consistency, we will act like everything is fine. There will simply - // be no file events for broken symlinks. - // Hence the returns of nil on errors. - if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - name, err = filepath.EvalSymlinks(name) - if err != nil { - return "", nil - } - - w.mu.Lock() - _, alreadyWatching = w.watches[name] - w.mu.Unlock() - - if alreadyWatching { - return name, nil - } - - fi, err = os.Lstat(name) - if err != nil { - return "", nil - } - } - - watchfd, err = unix.Open(name, openMode, 0700) - if watchfd == -1 { - return "", err - } - - isDir = fi.IsDir() - } - - const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE - if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { - unix.Close(watchfd) - return "", err - } - - if !alreadyWatching { - w.mu.Lock() - w.watches[name] = watchfd - w.paths[watchfd] = pathInfo{name: name, isDir: isDir} - w.mu.Unlock() - } - - if isDir { - // Watch the directory if it has not been watched before, - // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) - w.mu.Lock() - - watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && - (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) - // Store flags so this watch can be updated later - w.dirFlags[name] = flags - w.mu.Unlock() - - if watchDir { - if err := w.watchDirectoryFiles(name); err != nil { - return "", err - } - } - } - return name, nil -} - -// readEvents reads from kqueue and converts the received kevents into -// Event values that it sends down the Events channel. -func (w *Watcher) readEvents() { - eventBuffer := make([]unix.Kevent_t, 10) - -loop: - for { - // See if there is a message on the "done" channel - select { - case <-w.done: - break loop - default: - } - - // Get new events - kevents, err := read(w.kq, eventBuffer, &keventWaitTime) - // EINTR is okay, the syscall was interrupted before timeout expired. - if err != nil && err != unix.EINTR { - select { - case w.Errors <- err: - case <-w.done: - break loop - } - continue - } - - // Flush the events we received to the Events channel - for len(kevents) > 0 { - kevent := &kevents[0] - watchfd := int(kevent.Ident) - mask := uint32(kevent.Fflags) - w.mu.Lock() - path := w.paths[watchfd] - w.mu.Unlock() - event := newEvent(path.name, mask) - - if path.isDir && !(event.Op&Remove == Remove) { - // Double check to make sure the directory exists. This can happen when - // we do a rm -fr on a recursively watched folders and we receive a - // modification event first but the folder has been deleted and later - // receive the delete event - if _, err := os.Lstat(event.Name); os.IsNotExist(err) { - // mark is as delete event - event.Op |= Remove - } - } - - if event.Op&Rename == Rename || event.Op&Remove == Remove { - w.Remove(event.Name) - w.mu.Lock() - delete(w.fileExists, event.Name) - w.mu.Unlock() - } - - if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) { - w.sendDirectoryChangeEvents(event.Name) - } else { - // Send the event on the Events channel. - select { - case w.Events <- event: - case <-w.done: - break loop - } - } - - if event.Op&Remove == Remove { - // Look for a file that may have overwritten this. - // For example, mv f1 f2 will delete f2, then create f2. - if path.isDir { - fileDir := filepath.Clean(event.Name) - w.mu.Lock() - _, found := w.watches[fileDir] - w.mu.Unlock() - if found { - // make sure the directory exists before we watch for changes. When we - // do a recursive watch and perform rm -fr, the parent directory might - // have gone missing, ignore the missing directory and let the - // upcoming delete event remove the watch from the parent directory. - if _, err := os.Lstat(fileDir); err == nil { - w.sendDirectoryChangeEvents(fileDir) - } - } - } else { - filePath := filepath.Clean(event.Name) - if fileInfo, err := os.Lstat(filePath); err == nil { - w.sendFileCreatedEventIfNew(filePath, fileInfo) - } - } - } - - // Move to next event - kevents = kevents[1:] - } - } - - // cleanup - err := unix.Close(w.kq) - if err != nil { - // only way the previous loop breaks is if w.done was closed so we need to async send to w.Errors. - select { - case w.Errors <- err: - default: - } - } - close(w.Events) - close(w.Errors) -} - -// newEvent returns an platform-independent Event based on kqueue Fflags. -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { - e.Op |= Remove - } - if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { - e.Op |= Write - } - if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { - e.Op |= Rename - } - if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { - e.Op |= Chmod - } - return e -} - -func newCreateEvent(name string) Event { - return Event{Name: name, Op: Create} -} - -// watchDirectoryFiles to mimic inotify when adding a watch on a directory -func (w *Watcher) watchDirectoryFiles(dirPath string) error { - // Get all files - files, err := ioutil.ReadDir(dirPath) - if err != nil { - return err - } - - for _, fileInfo := range files { - filePath := filepath.Join(dirPath, fileInfo.Name()) - filePath, err = w.internalWatch(filePath, fileInfo) - if err != nil { - return err - } - - w.mu.Lock() - w.fileExists[filePath] = true - w.mu.Unlock() - } - - return nil -} - -// sendDirectoryEvents searches the directory for newly created files -// and sends them over the event channel. This functionality is to have -// the BSD version of fsnotify match Linux inotify which provides a -// create event for files created in a watched directory. -func (w *Watcher) sendDirectoryChangeEvents(dirPath string) { - // Get all files - files, err := ioutil.ReadDir(dirPath) - if err != nil { - select { - case w.Errors <- err: - case <-w.done: - return - } - } - - // Search for new files - for _, fileInfo := range files { - filePath := filepath.Join(dirPath, fileInfo.Name()) - err := w.sendFileCreatedEventIfNew(filePath, fileInfo) - - if err != nil { - return - } - } -} - -// sendFileCreatedEvent sends a create event if the file isn't already being tracked. -func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { - w.mu.Lock() - _, doesExist := w.fileExists[filePath] - w.mu.Unlock() - if !doesExist { - // Send create event - select { - case w.Events <- newCreateEvent(filePath): - case <-w.done: - return - } - } - - // like watchDirectoryFiles (but without doing another ReadDir) - filePath, err = w.internalWatch(filePath, fileInfo) - if err != nil { - return err - } - - w.mu.Lock() - w.fileExists[filePath] = true - w.mu.Unlock() - - return nil -} - -func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { - if fileInfo.IsDir() { - // mimic Linux providing delete events for subdirectories - // but preserve the flags used if currently watching subdirectory - w.mu.Lock() - flags := w.dirFlags[name] - w.mu.Unlock() - - flags |= unix.NOTE_DELETE | unix.NOTE_RENAME - return w.addWatch(name, flags) - } - - // watch file to mimic Linux inotify - return w.addWatch(name, noteAllEvents) -} - -// kqueue creates a new kernel event queue and returns a descriptor. -func kqueue() (kq int, err error) { - kq, err = unix.Kqueue() - if kq == -1 { - return kq, err - } - return kq, nil -} - -// register events with the queue -func register(kq int, fds []int, flags int, fflags uint32) error { - changes := make([]unix.Kevent_t, len(fds)) - - for i, fd := range fds { - // SetKevent converts int to the platform-specific types: - unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) - changes[i].Fflags = fflags - } - - // register the events - success, err := unix.Kevent(kq, changes, nil, nil) - if success == -1 { - return err - } - return nil -} - -// read retrieves pending events, or waits until an event occurs. -// A timeout of nil blocks indefinitely, while 0 polls the queue. -func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]unix.Kevent_t, error) { - n, err := unix.Kevent(kq, nil, events, timeout) - if err != nil { - return nil, err - } - return events[0:n], nil -} - -// durationToTimespec prepares a timeout value -func durationToTimespec(d time.Duration) unix.Timespec { - return unix.NsecToTimespec(d.Nanoseconds()) -} diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go deleted file mode 100644 index 36cc3845b..000000000 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd || dragonfly -// +build freebsd openbsd netbsd dragonfly - -package fsnotify - -import "golang.org/x/sys/unix" - -const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go deleted file mode 100644 index 98cd8476f..000000000 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin -// +build darwin - -package fsnotify - -import "golang.org/x/sys/unix" - -// note: this constant is not defined on BSD -const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/windows.go b/vendor/github.com/fsnotify/fsnotify/windows.go deleted file mode 100644 index 02ce7deb0..000000000 --- a/vendor/github.com/fsnotify/fsnotify/windows.go +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -package fsnotify - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "reflect" - "runtime" - "sync" - "syscall" - "unsafe" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - isClosed bool // Set to true when Close() is first called - mu sync.Mutex // Map access - port syscall.Handle // Handle to completion port - watches watchMap // Map of watches (key: i-number) - input chan *input // Inputs to the reader are sent on this channel - quit chan chan<- error -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) - if e != nil { - return nil, os.NewSyscallError("CreateIoCompletionPort", e) - } - w := &Watcher{ - port: port, - watches: make(watchMap), - input: make(chan *input, 1), - Events: make(chan Event, 50), - Errors: make(chan error), - quit: make(chan chan<- error, 1), - } - go w.readEvents() - return w, nil -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - if w.isClosed { - return nil - } - w.isClosed = true - - // Send "quit" message to the reader goroutine - ch := make(chan error) - w.quit <- ch - if err := w.wakeupReader(); err != nil { - return err - } - return <-ch -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - if w.isClosed { - return errors.New("watcher already closed") - } - in := &input{ - op: opAddWatch, - path: filepath.Clean(name), - flags: sysFSALLEVENTS, - reply: make(chan error), - } - w.input <- in - if err := w.wakeupReader(); err != nil { - return err - } - return <-in.reply -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - in := &input{ - op: opRemoveWatch, - path: filepath.Clean(name), - reply: make(chan error), - } - w.input <- in - if err := w.wakeupReader(); err != nil { - return err - } - return <-in.reply -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for _, entry := range w.watches { - for _, watchEntry := range entry { - entries = append(entries, watchEntry.path) - } - } - - return entries -} - -const ( - // Options for AddWatch - sysFSONESHOT = 0x80000000 - sysFSONLYDIR = 0x1000000 - - // Events - sysFSACCESS = 0x1 - sysFSALLEVENTS = 0xfff - sysFSATTRIB = 0x4 - sysFSCLOSE = 0x18 - sysFSCREATE = 0x100 - sysFSDELETE = 0x200 - sysFSDELETESELF = 0x400 - sysFSMODIFY = 0x2 - sysFSMOVE = 0xc0 - sysFSMOVEDFROM = 0x40 - sysFSMOVEDTO = 0x80 - sysFSMOVESELF = 0x800 - - // Special events - sysFSIGNORED = 0x8000 - sysFSQOVERFLOW = 0x4000 -) - -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { - e.Op |= Create - } - if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { - e.Op |= Remove - } - if mask&sysFSMODIFY == sysFSMODIFY { - e.Op |= Write - } - if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { - e.Op |= Rename - } - if mask&sysFSATTRIB == sysFSATTRIB { - e.Op |= Chmod - } - return e -} - -const ( - opAddWatch = iota - opRemoveWatch -) - -const ( - provisional uint64 = 1 << (32 + iota) -) - -type input struct { - op int - path string - flags uint32 - reply chan error -} - -type inode struct { - handle syscall.Handle - volume uint32 - index uint64 -} - -type watch struct { - ov syscall.Overlapped - ino *inode // i-number - path string // Directory path - mask uint64 // Directory itself is being watched with these notify flags - names map[string]uint64 // Map of names being watched and their notify flags - rename string // Remembers the old name while renaming a file - buf [4096]byte -} - -type indexMap map[uint64]*watch -type watchMap map[uint32]indexMap - -func (w *Watcher) wakeupReader() error { - e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) - if e != nil { - return os.NewSyscallError("PostQueuedCompletionStatus", e) - } - return nil -} - -func getDir(pathname string) (dir string, err error) { - attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) - if e != nil { - return "", os.NewSyscallError("GetFileAttributes", e) - } - if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - dir = pathname - } else { - dir, _ = filepath.Split(pathname) - dir = filepath.Clean(dir) - } - return -} - -func getIno(path string) (ino *inode, err error) { - h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path), - syscall.FILE_LIST_DIRECTORY, - syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, - nil, syscall.OPEN_EXISTING, - syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) - if e != nil { - return nil, os.NewSyscallError("CreateFile", e) - } - var fi syscall.ByHandleFileInformation - if e = syscall.GetFileInformationByHandle(h, &fi); e != nil { - syscall.CloseHandle(h) - return nil, os.NewSyscallError("GetFileInformationByHandle", e) - } - ino = &inode{ - handle: h, - volume: fi.VolumeSerialNumber, - index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), - } - return ino, nil -} - -// Must run within the I/O thread. -func (m watchMap) get(ino *inode) *watch { - if i := m[ino.volume]; i != nil { - return i[ino.index] - } - return nil -} - -// Must run within the I/O thread. -func (m watchMap) set(ino *inode, watch *watch) { - i := m[ino.volume] - if i == nil { - i = make(indexMap) - m[ino.volume] = i - } - i[ino.index] = watch -} - -// Must run within the I/O thread. -func (w *Watcher) addWatch(pathname string, flags uint64) error { - dir, err := getDir(pathname) - if err != nil { - return err - } - if flags&sysFSONLYDIR != 0 && pathname != dir { - return nil - } - ino, err := getIno(dir) - if err != nil { - return err - } - w.mu.Lock() - watchEntry := w.watches.get(ino) - w.mu.Unlock() - if watchEntry == nil { - if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { - syscall.CloseHandle(ino.handle) - return os.NewSyscallError("CreateIoCompletionPort", e) - } - watchEntry = &watch{ - ino: ino, - path: dir, - names: make(map[string]uint64), - } - w.mu.Lock() - w.watches.set(ino, watchEntry) - w.mu.Unlock() - flags |= provisional - } else { - syscall.CloseHandle(ino.handle) - } - if pathname == dir { - watchEntry.mask |= flags - } else { - watchEntry.names[filepath.Base(pathname)] |= flags - } - if err = w.startRead(watchEntry); err != nil { - return err - } - if pathname == dir { - watchEntry.mask &= ^provisional - } else { - watchEntry.names[filepath.Base(pathname)] &= ^provisional - } - return nil -} - -// Must run within the I/O thread. -func (w *Watcher) remWatch(pathname string) error { - dir, err := getDir(pathname) - if err != nil { - return err - } - ino, err := getIno(dir) - if err != nil { - return err - } - w.mu.Lock() - watch := w.watches.get(ino) - w.mu.Unlock() - if watch == nil { - return fmt.Errorf("can't remove non-existent watch for: %s", pathname) - } - if pathname == dir { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) - watch.mask = 0 - } else { - name := filepath.Base(pathname) - w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) - delete(watch.names, name) - } - return w.startRead(watch) -} - -// Must run within the I/O thread. -func (w *Watcher) deleteWatch(watch *watch) { - for name, mask := range watch.names { - if mask&provisional == 0 { - w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) - } - delete(watch.names, name) - } - if watch.mask != 0 { - if watch.mask&provisional == 0 { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) - } - watch.mask = 0 - } -} - -// Must run within the I/O thread. -func (w *Watcher) startRead(watch *watch) error { - if e := syscall.CancelIo(watch.ino.handle); e != nil { - w.Errors <- os.NewSyscallError("CancelIo", e) - w.deleteWatch(watch) - } - mask := toWindowsFlags(watch.mask) - for _, m := range watch.names { - mask |= toWindowsFlags(m) - } - if mask == 0 { - if e := syscall.CloseHandle(watch.ino.handle); e != nil { - w.Errors <- os.NewSyscallError("CloseHandle", e) - } - w.mu.Lock() - delete(w.watches[watch.ino.volume], watch.ino.index) - w.mu.Unlock() - return nil - } - e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], - uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) - if e != nil { - err := os.NewSyscallError("ReadDirectoryChanges", e) - if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { - // Watched directory was probably removed - if w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) { - if watch.mask&sysFSONESHOT != 0 { - watch.mask = 0 - } - } - err = nil - } - w.deleteWatch(watch) - w.startRead(watch) - return err - } - return nil -} - -// readEvents reads from the I/O completion port, converts the -// received events into Event objects and sends them via the Events channel. -// Entry point to the I/O thread. -func (w *Watcher) readEvents() { - var ( - n, key uint32 - ov *syscall.Overlapped - ) - runtime.LockOSThread() - - for { - e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE) - watch := (*watch)(unsafe.Pointer(ov)) - - if watch == nil { - select { - case ch := <-w.quit: - w.mu.Lock() - var indexes []indexMap - for _, index := range w.watches { - indexes = append(indexes, index) - } - w.mu.Unlock() - for _, index := range indexes { - for _, watch := range index { - w.deleteWatch(watch) - w.startRead(watch) - } - } - var err error - if e := syscall.CloseHandle(w.port); e != nil { - err = os.NewSyscallError("CloseHandle", e) - } - close(w.Events) - close(w.Errors) - ch <- err - return - case in := <-w.input: - switch in.op { - case opAddWatch: - in.reply <- w.addWatch(in.path, uint64(in.flags)) - case opRemoveWatch: - in.reply <- w.remWatch(in.path) - } - default: - } - continue - } - - switch e { - case syscall.ERROR_MORE_DATA: - if watch == nil { - w.Errors <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer") - } else { - // The i/o succeeded but the buffer is full. - // In theory we should be building up a full packet. - // In practice we can get away with just carrying on. - n = uint32(unsafe.Sizeof(watch.buf)) - } - case syscall.ERROR_ACCESS_DENIED: - // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) - w.deleteWatch(watch) - w.startRead(watch) - continue - case syscall.ERROR_OPERATION_ABORTED: - // CancelIo was called on this handle - continue - default: - w.Errors <- os.NewSyscallError("GetQueuedCompletionPort", e) - continue - case nil: - } - - var offset uint32 - for { - if n == 0 { - w.Events <- newEvent("", sysFSQOVERFLOW) - w.Errors <- errors.New("short read in readEvents()") - break - } - - // Point "raw" to the event in the buffer - raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) - // TODO: Consider using unsafe.Slice that is available from go1.17 - // https://stackoverflow.com/questions/51187973/how-to-create-an-array-or-a-slice-from-an-array-unsafe-pointer-in-golang - // instead of using a fixed syscall.MAX_PATH buf, we create a buf that is the size of the path name - size := int(raw.FileNameLength / 2) - var buf []uint16 - sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) - sh.Data = uintptr(unsafe.Pointer(&raw.FileName)) - sh.Len = size - sh.Cap = size - name := syscall.UTF16ToString(buf) - fullname := filepath.Join(watch.path, name) - - var mask uint64 - switch raw.Action { - case syscall.FILE_ACTION_REMOVED: - mask = sysFSDELETESELF - case syscall.FILE_ACTION_MODIFIED: - mask = sysFSMODIFY - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - watch.rename = name - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - if watch.names[watch.rename] != 0 { - watch.names[name] |= watch.names[watch.rename] - delete(watch.names, watch.rename) - mask = sysFSMOVESELF - } - } - - sendNameEvent := func() { - if w.sendEvent(fullname, watch.names[name]&mask) { - if watch.names[name]&sysFSONESHOT != 0 { - delete(watch.names, name) - } - } - } - if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME { - sendNameEvent() - } - if raw.Action == syscall.FILE_ACTION_REMOVED { - w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) - delete(watch.names, name) - } - if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) { - if watch.mask&sysFSONESHOT != 0 { - watch.mask = 0 - } - } - if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME { - fullname = filepath.Join(watch.path, watch.rename) - sendNameEvent() - } - - // Move to the next event in the buffer - if raw.NextEntryOffset == 0 { - break - } - offset += raw.NextEntryOffset - - // Error! - if offset >= n { - w.Errors <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.") - break - } - } - - if err := w.startRead(watch); err != nil { - w.Errors <- err - } - } -} - -func (w *Watcher) sendEvent(name string, mask uint64) bool { - if mask == 0 { - return false - } - event := newEvent(name, uint32(mask)) - select { - case ch := <-w.quit: - w.quit <- ch - case w.Events <- event: - } - return true -} - -func toWindowsFlags(mask uint64) uint32 { - var m uint32 - if mask&sysFSACCESS != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS - } - if mask&sysFSMODIFY != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE - } - if mask&sysFSATTRIB != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES - } - if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME - } - return m -} - -func toFSnotifyFlags(action uint32) uint64 { - switch action { - case syscall.FILE_ACTION_ADDED: - return sysFSCREATE - case syscall.FILE_ACTION_REMOVED: - return sysFSDELETE - case syscall.FILE_ACTION_MODIFIED: - return sysFSMODIFY - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - return sysFSMOVEDFROM - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - return sysFSMOVEDTO - } - return 0 -} diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go index 19437b34f..91198f819 100644 --- a/vendor/github.com/google/go-querystring/query/encode.go +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -51,8 +51,8 @@ type Encoder interface { // - the field is empty and its tag specifies the "omitempty" option // // The empty values are false, 0, any nil pointer or interface value, any array -// slice, map, or string of length zero, and any time.Time that returns true -// for IsZero(). +// slice, map, or string of length zero, and any type (such as time.Time) that +// returns true for IsZero(). // // The URL parameter name defaults to the struct field name but can be // specified in the struct field's tag value. The "url" key in the struct @@ -82,7 +82,14 @@ type Encoder interface { // // time.Time values default to encoding as RFC3339 timestamps. Including the // "unix" option signals that the field should be encoded as a Unix time (see -// time.Unix()) +// time.Unix()). The "unixmilli" and "unixnano" options will encode the number +// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see +// time.UnixNano()). Including the "layout" struct tag (separate from the +// "url" tag) will use the value of the "layout" tag as a layout passed to +// time.Format. For example: +// +// // Encode a time.Time as YYYY-MM-DD +// Field time.Time `layout:"2006-01-02"` // // Slice and Array values default to encoding as multiple URL values of the // same name. Including the "comma" option signals that the field should be @@ -92,7 +99,13 @@ type Encoder interface { // Including the "brackets" option signals that the multiple URL values should // have "[]" appended to the value name. "numbered" will append a number to // the end of each incidence of the value name, example: -// name0=value0&name1=value1, etc. +// name0=value0&name1=value1, etc. Including the "del" struct tag (separate +// from the "url" tag) will use the value of the "del" tag as the delimiter. +// For example: +// +// // Encode a slice of bools as ints ("1" for true, "0" for false), +// // separated by exclamation points "!". +// Field []bool `url:",int" del:"!"` // // Anonymous struct fields are usually encoded as if their inner exported // fields were fields in the outer struct, subject to the standard Go @@ -151,11 +164,15 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { continue } name, opts := parseTag(tag) + if name == "" { - if sf.Anonymous && sv.Kind() == reflect.Struct { - // save embedded struct for later processing - embedded = append(embedded, sv) - continue + if sf.Anonymous { + v := reflect.Indirect(sv) + if v.IsValid() && v.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, v) + continue + } } name = sf.Name @@ -170,7 +187,9 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } if sv.Type().Implements(encoderType) { - if !reflect.Indirect(sv).IsValid() { + // if sv is a nil pointer and the custom encoder is defined on a non-pointer + // method receiver, set sv to the zero value of the underlying type + if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) { sv = reflect.New(sv.Type().Elem()) } @@ -181,28 +200,38 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { continue } + // recursively dereference pointers. break on nil pointers + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { - var del byte + var del string if opts.Contains("comma") { - del = ',' + del = "," } else if opts.Contains("space") { - del = ' ' + del = " " } else if opts.Contains("semicolon") { - del = ';' + del = ";" } else if opts.Contains("brackets") { name = name + "[]" + } else { + del = sf.Tag.Get("del") } - if del != 0 { + if del != "" { s := new(bytes.Buffer) first := true for i := 0; i < sv.Len(); i++ { if first { first = false } else { - s.WriteByte(del) + s.WriteString(del) } - s.WriteString(valueString(sv.Index(i), opts)) + s.WriteString(valueString(sv.Index(i), opts, sf)) } values.Add(name, s.String()) } else { @@ -211,30 +240,25 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { if opts.Contains("numbered") { k = fmt.Sprintf("%s%d", name, i) } - values.Add(k, valueString(sv.Index(i), opts)) + values.Add(k, valueString(sv.Index(i), opts, sf)) } } continue } if sv.Type() == timeType { - values.Add(name, valueString(sv, opts)) + values.Add(name, valueString(sv, opts, sf)) continue } - for sv.Kind() == reflect.Ptr { - if sv.IsNil() { - break - } - sv = sv.Elem() - } - if sv.Kind() == reflect.Struct { - reflectValue(values, sv, name) + if err := reflectValue(values, sv, name); err != nil { + return err + } continue } - values.Add(name, valueString(sv, opts)) + values.Add(name, valueString(sv, opts, sf)) } for _, f := range embedded { @@ -247,7 +271,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } // valueString returns the string representation of a value. -func valueString(v reflect.Value, opts tagOptions) string { +func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string { for v.Kind() == reflect.Ptr { if v.IsNil() { return "" @@ -267,6 +291,15 @@ func valueString(v reflect.Value, opts tagOptions) string { if opts.Contains("unix") { return strconv.FormatInt(t.Unix(), 10) } + if opts.Contains("unixmilli") { + return strconv.FormatInt((t.UnixNano() / 1e6), 10) + } + if opts.Contains("unixnano") { + return strconv.FormatInt(t.UnixNano(), 10) + } + if layout := sf.Tag.Get("layout"); layout != "" { + return t.Format(layout) + } return t.Format(time.RFC3339) } @@ -291,8 +324,12 @@ func isEmptyValue(v reflect.Value) bool { return v.IsNil() } - if v.Type() == timeType { - return v.Interface().(time.Time).IsZero() + type zeroable interface { + IsZero() bool + } + + if z, ok := v.Interface().(zeroable); ok { + return z.IsZero() } return false diff --git a/vendor/github.com/gorilla/context/.travis.yml b/vendor/github.com/gorilla/context/.travis.yml deleted file mode 100644 index 24882fc7b..000000000 --- a/vendor/github.com/gorilla/context/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.3 - - go: 1.4 - - go: 1.5 - - go: 1.6 - - go: tip - allow_failures: - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go vet $(go list ./... | grep -v /vendor/) - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/context/LICENSE b/vendor/github.com/gorilla/context/LICENSE deleted file mode 100644 index 0e5fb8728..000000000 --- a/vendor/github.com/gorilla/context/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gorilla/context/README.md b/vendor/github.com/gorilla/context/README.md deleted file mode 100644 index c60a31b05..000000000 --- a/vendor/github.com/gorilla/context/README.md +++ /dev/null @@ -1,7 +0,0 @@ -context -======= -[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) - -gorilla/context is a general purpose registry for global request variables. - -Read the full documentation here: http://www.gorillatoolkit.org/pkg/context diff --git a/vendor/github.com/gorilla/context/context.go b/vendor/github.com/gorilla/context/context.go deleted file mode 100644 index 81cb128b1..000000000 --- a/vendor/github.com/gorilla/context/context.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context - -import ( - "net/http" - "sync" - "time" -) - -var ( - mutex sync.RWMutex - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) -) - -// Set stores a value for a given key in a given request. -func Set(r *http.Request, key, val interface{}) { - mutex.Lock() - if data[r] == nil { - data[r] = make(map[interface{}]interface{}) - datat[r] = time.Now().Unix() - } - data[r][key] = val - mutex.Unlock() -} - -// Get returns a value stored for a given key in a given request. -func Get(r *http.Request, key interface{}) interface{} { - mutex.RLock() - if ctx := data[r]; ctx != nil { - value := ctx[key] - mutex.RUnlock() - return value - } - mutex.RUnlock() - return nil -} - -// GetOk returns stored value and presence state like multi-value return of map access. -func GetOk(r *http.Request, key interface{}) (interface{}, bool) { - mutex.RLock() - if _, ok := data[r]; ok { - value, ok := data[r][key] - mutex.RUnlock() - return value, ok - } - mutex.RUnlock() - return nil, false -} - -// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. -func GetAll(r *http.Request) map[interface{}]interface{} { - mutex.RLock() - if context, ok := data[r]; ok { - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result - } - mutex.RUnlock() - return nil -} - -// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if -// the request was registered. -func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { - mutex.RLock() - context, ok := data[r] - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result, ok -} - -// Delete removes a value stored for a given key in a given request. -func Delete(r *http.Request, key interface{}) { - mutex.Lock() - if data[r] != nil { - delete(data[r], key) - } - mutex.Unlock() -} - -// Clear removes all values stored for a given request. -// -// This is usually called by a handler wrapper to clean up request -// variables at the end of a request lifetime. See ClearHandler(). -func Clear(r *http.Request) { - mutex.Lock() - clear(r) - mutex.Unlock() -} - -// clear is Clear without the lock. -func clear(r *http.Request) { - delete(data, r) - delete(datat, r) -} - -// Purge removes request data stored for longer than maxAge, in seconds. -// It returns the amount of requests removed. -// -// If maxAge <= 0, all request data is removed. -// -// This is only used for sanity check: in case context cleaning was not -// properly set some request data can be kept forever, consuming an increasing -// amount of memory. In case this is detected, Purge() must be called -// periodically until the problem is fixed. -func Purge(maxAge int) int { - mutex.Lock() - count := 0 - if maxAge <= 0 { - count = len(data) - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) - } else { - min := time.Now().Unix() - int64(maxAge) - for r := range data { - if datat[r] < min { - clear(r) - count++ - } - } - } - mutex.Unlock() - return count -} - -// ClearHandler wraps an http.Handler and clears request values at the end -// of a request lifetime. -func ClearHandler(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer Clear(r) - h.ServeHTTP(w, r) - }) -} diff --git a/vendor/github.com/gorilla/context/doc.go b/vendor/github.com/gorilla/context/doc.go deleted file mode 100644 index 73c740031..000000000 --- a/vendor/github.com/gorilla/context/doc.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package context stores values shared during a request lifetime. - -For example, a router can set variables extracted from the URL and later -application handlers can access those values, or it can be used to store -sessions values to be saved at the end of a request. There are several -others common uses. - -The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: - - http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 - -Here's the basic usage: first define the keys that you will need. The key -type is interface{} so a key can be of any type that supports equality. -Here we define a key using a custom int type to avoid name collisions: - - package foo - - import ( - "github.com/gorilla/context" - ) - - type key int - - const MyKey key = 0 - -Then set a variable. Variables are bound to an http.Request object, so you -need a request instance to set a value: - - context.Set(r, MyKey, "bar") - -The application can later access the variable using the same key you provided: - - func MyHandler(w http.ResponseWriter, r *http.Request) { - // val is "bar". - val := context.Get(r, foo.MyKey) - - // returns ("bar", true) - val, ok := context.GetOk(r, foo.MyKey) - // ... - } - -And that's all about the basic usage. We discuss some other ideas below. - -Any type can be stored in the context. To enforce a given type, make the key -private and wrap Get() and Set() to accept and return values of a specific -type: - - type key int - - const mykey key = 0 - - // GetMyKey returns a value for this package from the request values. - func GetMyKey(r *http.Request) SomeType { - if rv := context.Get(r, mykey); rv != nil { - return rv.(SomeType) - } - return nil - } - - // SetMyKey sets a value for this package in the request values. - func SetMyKey(r *http.Request, val SomeType) { - context.Set(r, mykey, val) - } - -Variables must be cleared at the end of a request, to remove all values -that were stored. This can be done in an http.Handler, after a request was -served. Just call Clear() passing the request: - - context.Clear(r) - -...or use ClearHandler(), which conveniently wraps an http.Handler to clear -variables at the end of a request lifetime. - -The Routers from the packages gorilla/mux and gorilla/pat call Clear() -so if you are using either of them you don't need to clear the context manually. -*/ -package context diff --git a/vendor/github.com/gorilla/mux/.travis.yml b/vendor/github.com/gorilla/mux/.travis.yml deleted file mode 100644 index f4084bd81..000000000 --- a/vendor/github.com/gorilla/mux/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.2 - - go: 1.3 - - go: 1.4 - - go: 1.5 - - go: 1.6 - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go tool vet . - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/mux/LICENSE b/vendor/github.com/gorilla/mux/LICENSE index 0e5fb8728..bb9d80bc9 100644 --- a/vendor/github.com/gorilla/mux/LICENSE +++ b/vendor/github.com/gorilla/mux/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. +Copyright (c) 2023 The Gorilla Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md index 9516c5191..382513d57 100644 --- a/vendor/github.com/gorilla/mux/README.md +++ b/vendor/github.com/gorilla/mux/README.md @@ -1,29 +1,60 @@ -mux -=== -[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) -[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux) +# gorilla/mux -http://www.gorillatoolkit.org/pkg/mux +![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux) +[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) -Package `gorilla/mux` implements a request router and dispatcher. + +![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5) + +Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to +their respective handler. The name mux stands for "HTTP request multiplexer". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: +* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. * Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. -* URL hosts and paths can have variables with an optional regular expression. +* URL hosts, paths and query values can have variables with an optional regular expression. * Registered URLs can be built, or "reversed", which helps maintaining references to resources. * Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching. -* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. + +--- + +* [Install](#install) +* [Examples](#examples) +* [Matching Routes](#matching-routes) +* [Static Files](#static-files) +* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.) +* [Registered URLs](#registered-urls) +* [Walking Routes](#walking-routes) +* [Graceful Shutdown](#graceful-shutdown) +* [Middleware](#middleware) +* [Handling CORS Requests](#handling-cors-requests) +* [Testing Handlers](#testing-handlers) +* [Full Example](#full-example) + +--- + +## Install + +With a [correctly configured](https://golang.org/doc/install#testing) Go toolchain: + +```sh +go get -u github.com/gorilla/mux +``` + +## Examples Let's start registering a couple of URL paths and handlers: ```go func main() { - r := mux.NewRouter() - r.HandleFunc("/", HomeHandler) - r.HandleFunc("/products", ProductsHandler) - r.HandleFunc("/articles", ArticlesHandler) - http.Handle("/", r) + r := mux.NewRouter() + r.HandleFunc("/", HomeHandler) + r.HandleFunc("/products", ProductsHandler) + r.HandleFunc("/articles", ArticlesHandler) + http.Handle("/", r) } ``` @@ -41,12 +72,17 @@ r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`: ```go -vars := mux.Vars(request) -category := vars["category"] +func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Category: %v\n", vars["category"]) +} ``` And this is all you need to know about the basic usage. More advanced options are explained below. +### Matching Routes + Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables: ```go @@ -54,7 +90,7 @@ r := mux.NewRouter() // Only matches if domain is "www.example.com". r.Host("www.example.com") // Matches a dynamic subdomain. -r.Host("{subdomain:[a-z]+}.domain.com") +r.Host("{subdomain:[a-z]+}.example.com") ``` There are several other matchers that can be added. To match path prefixes: @@ -91,7 +127,7 @@ r.Queries("key", "value") ```go r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { - return r.ProtoMajor == 0 + return r.ProtoMajor == 0 }) ``` @@ -104,6 +140,14 @@ r.HandleFunc("/products", ProductsHandler). Schemes("http") ``` +Routes are tested in the order they were added to the router. If two routes match, the first one wins: + +```go +r := mux.NewRouter() +r.HandleFunc("/specific", specificHandler) +r.PathPrefix("/").Handler(catchAllHandler) +``` + Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting". For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it: @@ -118,7 +162,7 @@ Then register routes in the subrouter: ```go s.HandleFunc("/products/", ProductsHandler) s.HandleFunc("/products/{key}", ProductHandler) -s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +s.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) ``` The three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route. @@ -138,6 +182,118 @@ s.HandleFunc("/{key}/", ProductHandler) s.HandleFunc("/{key}/details", ProductDetailsHandler) ``` + +### Static Files + +Note that the path provided to `PathPrefix()` represents a "wildcard": calling +`PathPrefix("/static/").Handler(...)` means that the handler will be passed any +request that matches "/static/\*". This makes it easy to serve static files with mux: + +```go +func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Serving Single Page Applications + +Most of the time it makes sense to serve your SPA on a separate web server from your API, +but sometimes it's desirable to serve them both from one place. It's possible to write a simple +handler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage +mux's powerful routing for your API endpoints. + +```go +package main + +import ( + "encoding/json" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gorilla/mux" +) + +// spaHandler implements the http.Handler interface, so we can use it +// to respond to HTTP requests. The path to the static directory and +// path to the index file within that static directory are used to +// serve the SPA in the given static directory. +type spaHandler struct { + staticPath string + indexPath string +} + +// ServeHTTP inspects the URL path to locate a file within the static dir +// on the SPA handler. If a file is found, it will be served. If not, the +// file located at the index path on the SPA handler will be served. This +// is suitable behavior for serving an SPA (single page application). +func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Join internally call path.Clean to prevent directory traversal + path := filepath.Join(h.staticPath, r.URL.Path) + + // check whether a file exists or is a directory at the given path + fi, err := os.Stat(path) + if os.IsNotExist(err) || fi.IsDir() { + // file does not exist or path is a directory, serve index.html + http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath)) + return + } + + if err != nil { + // if we got an error (that wasn't that the file doesn't exist) stating the + // file, return a 500 internal server error and stop + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // otherwise, use http.FileServer to serve the static file + http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r) +} + +func main() { + router := mux.NewRouter() + + router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + // an example API handler + json.NewEncoder(w).Encode(map[string]bool{"ok": true}) + }) + + spa := spaHandler{staticPath: "build", indexPath: "index.html"} + router.PathPrefix("/").Handler(spa) + + srv := &http.Server{ + Handler: router, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Registered URLs + Now let's see how to build registered URLs. Routes can be named. All routes that define a name can have their URLs built, or "reversed". We define a name calling `Name()` on a route. For example: @@ -160,19 +316,21 @@ url, err := r.Get("article").URL("category", "technology", "id", "42") "/articles/technology/42" ``` -This also works for host variables: +This also works for host and query value variables: ```go r := mux.NewRouter() -r.Host("{subdomain}.domain.com"). +r.Host("{subdomain}.example.com"). Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). HandlerFunc(ArticleHandler). Name("article") -// url.String() will be "http://news.domain.com/articles/technology/42" +// url.String() will be "http://news.example.com/articles/technology/42?filter=gorilla" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", - "id", "42") + "id", "42", + "filter", "gorilla") ``` All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match. @@ -188,7 +346,7 @@ r.HeadersRegexp("Content-Type", "application/(text|json)") There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do: ```go -// "http://news.domain.com/" +// "http://news.example.com/" host, err := r.Get("article").URLHost("subdomain", "news") // "/articles/technology/42" @@ -199,41 +357,453 @@ And if you use subrouters, host and path defined separately can be built as well ```go r := mux.NewRouter() -s := r.Host("{subdomain}.domain.com").Subrouter() +s := r.Host("{subdomain}.example.com").Subrouter() s.Path("/articles/{category}/{id:[0-9]+}"). HandlerFunc(ArticleHandler). Name("article") -// "http://news.domain.com/articles/technology/42" +// "http://news.example.com/articles/technology/42" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", "id", "42") ``` -## Full Example +To find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available: +```go +r := mux.NewRouter() +r.Host("{domain}"). + Path("/{group}/{item_id}"). + Queries("some_data1", "{some_data1}"). + Queries("some_data2", "{some_data2}"). + Name("article") -Here's a complete, runnable example of a small `mux` based server: +// Will print [domain group item_id some_data1 some_data2] +fmt.Println(r.Get("article").GetVarNames()) + +``` +### Walking Routes + +The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example, +the following prints all of the registered routes: ```go package main import ( + "fmt" "net/http" + "strings" "github.com/gorilla/mux" ) -func YourHandler(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Gorilla!\n")) +func handler(w http.ResponseWriter, r *http.Request) { + return } func main() { r := mux.NewRouter() - // Routes consist of a path and a handler function. - r.HandleFunc("/", YourHandler) + r.HandleFunc("/", handler) + r.HandleFunc("/products", handler).Methods("POST") + r.HandleFunc("/articles", handler).Methods("GET") + r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") + r.HandleFunc("/authors", handler).Queries("surname", "{surname}") + err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { + pathTemplate, err := route.GetPathTemplate() + if err == nil { + fmt.Println("ROUTE:", pathTemplate) + } + pathRegexp, err := route.GetPathRegexp() + if err == nil { + fmt.Println("Path regexp:", pathRegexp) + } + queriesTemplates, err := route.GetQueriesTemplates() + if err == nil { + fmt.Println("Queries templates:", strings.Join(queriesTemplates, ",")) + } + queriesRegexps, err := route.GetQueriesRegexp() + if err == nil { + fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ",")) + } + methods, err := route.GetMethods() + if err == nil { + fmt.Println("Methods:", strings.Join(methods, ",")) + } + fmt.Println() + return nil + }) + + if err != nil { + fmt.Println(err) + } + + http.Handle("/", r) +} +``` + +### Graceful Shutdown + +Go 1.8 introduced the ability to [gracefully shutdown](https://golang.org/doc/go1.8#http_shutdown) a `*http.Server`. Here's how to do that alongside `mux`: + +```go +package main + +import ( + "context" + "flag" + "log" + "net/http" + "os" + "os/signal" + "time" + + "github.com/gorilla/mux" +) + +func main() { + var wait time.Duration + flag.DurationVar(&wait, "graceful-timeout", time.Second * 15, "the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m") + flag.Parse() + + r := mux.NewRouter() + // Add your routes as needed + + srv := &http.Server{ + Addr: "0.0.0.0:8080", + // Good practice to set timeouts to avoid Slowloris attacks. + WriteTimeout: time.Second * 15, + ReadTimeout: time.Second * 15, + IdleTimeout: time.Second * 60, + Handler: r, // Pass our instance of gorilla/mux in. + } + + // Run our server in a goroutine so that it doesn't block. + go func() { + if err := srv.ListenAndServe(); err != nil { + log.Println(err) + } + }() + + c := make(chan os.Signal, 1) + // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C) + // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught. + signal.Notify(c, os.Interrupt) + + // Block until we receive our signal. + <-c + + // Create a deadline to wait for. + ctx, cancel := context.WithTimeout(context.Background(), wait) + defer cancel() + // Doesn't block if no connections, but will otherwise wait + // until the timeout deadline. + srv.Shutdown(ctx) + // Optionally, you could run srv.Shutdown in a goroutine and block on + // <-ctx.Done() if your application should wait for other services + // to finalize based on context cancellation. + log.Println("shutting down") + os.Exit(0) +} +``` + +### Middleware + +Mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters. +Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking. + +Mux middlewares are defined using the de facto standard type: + +```go +type MiddlewareFunc func(http.Handler) http.Handler +``` + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers. + +A very basic middleware which logs the URI of the request being handled could be written as: + +```go +func loggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) +} +``` + +Middlewares can be added to a router using `Router.Use()`: + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) +r.Use(loggingMiddleware) +``` + +A more complex authentication middleware, which maps session token to users, could be written as: + +```go +// Define our struct +type authenticationMiddleware struct { + tokenUsers map[string]string +} + +// Initialize it somewhere +func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" +} + +// Middleware function, which will be called for each request +func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + // Pass down the request to the next middleware (or final handler) + next.ServeHTTP(w, r) + } else { + // Write an error and stop the handler chain + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) +} +``` + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) + +amw := authenticationMiddleware{tokenUsers: make(map[string]string)} +amw.Populate() + +r.Use(amw.Middleware) +``` + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it. + +### Handling CORS Requests + +[CORSMethodMiddleware](https://godoc.org/github.com/gorilla/mux#CORSMethodMiddleware) intends to make it easier to strictly set the `Access-Control-Allow-Methods` response header. + +* You will still need to use your own CORS handler to set the other CORS headers such as `Access-Control-Allow-Origin` +* The middleware will set the `Access-Control-Allow-Methods` header to all the method matchers (e.g. `r.Methods(http.MethodGet, http.MethodPut, http.MethodOptions)` -> `Access-Control-Allow-Methods: GET,PUT,OPTIONS`) on a route +* If you do not specify any methods, then: +> _Important_: there must be an `OPTIONS` method matcher for the middleware to set the headers. + +Here is an example of using `CORSMethodMiddleware` along with a custom `OPTIONS` handler to set all the required CORS headers: + +```go +package main + +import ( + "net/http" + "github.com/gorilla/mux" +) + +func main() { + r := mux.NewRouter() + + // IMPORTANT: you must specify an OPTIONS method matcher for the middleware to set CORS headers + r.HandleFunc("/foo", fooHandler).Methods(http.MethodGet, http.MethodPut, http.MethodPatch, http.MethodOptions) + r.Use(mux.CORSMethodMiddleware(r)) + + http.ListenAndServe(":8080", r) +} + +func fooHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + if r.Method == http.MethodOptions { + return + } + + w.Write([]byte("foo")) +} +``` + +And an request to `/foo` using something like: + +```bash +curl localhost:8080/foo -v +``` + +Would look like: + +```bash +* Trying ::1... +* TCP_NODELAY set +* Connected to localhost (::1) port 8080 (#0) +> GET /foo HTTP/1.1 +> Host: localhost:8080 +> User-Agent: curl/7.59.0 +> Accept: */* +> +< HTTP/1.1 200 OK +< Access-Control-Allow-Methods: GET,PUT,PATCH,OPTIONS +< Access-Control-Allow-Origin: * +< Date: Fri, 28 Jun 2019 20:13:30 GMT +< Content-Length: 3 +< Content-Type: text/plain; charset=utf-8 +< +* Connection #0 to host localhost left intact +foo +``` + +### Testing Handlers + +Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_. + +First, our simple HTTP handler: + +```go +// endpoints.go +package main + +func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { + // A very simple health check. + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + // In the future we could report back on the status of our DB, or our cache + // (e.g. Redis) by performing a simple PING, and include them in the response. + io.WriteString(w, `{"alive": true}`) +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/health", HealthCheckHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test code: + +```go +// endpoints_test.go +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestHealthCheckHandler(t *testing.T) { + // Create a request to pass to our handler. We don't have any query parameters for now, so we'll + // pass 'nil' as the third parameter. + req, err := http.NewRequest("GET", "/health", nil) + if err != nil { + t.Fatal(err) + } + + // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. + rr := httptest.NewRecorder() + handler := http.HandlerFunc(HealthCheckHandler) + + // Our handlers satisfy http.Handler, so we can call their ServeHTTP method + // directly and pass in our Request and ResponseRecorder. + handler.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } + + // Check the response body is what we expect. + expected := `{"alive": true}` + if rr.Body.String() != expected { + t.Errorf("handler returned unexpected body: got %v want %v", + rr.Body.String(), expected) + } +} +``` + +In the case that our routes have [variables](#examples), we can pass those in the request. We could write +[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple +possible route variables as needed. + +```go +// endpoints.go +func main() { + r := mux.NewRouter() + // A route with a route variable: + r.HandleFunc("/metrics/{type}", MetricsHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test file, with a table-driven test of `routeVariables`: + +```go +// endpoints_test.go +func TestMetricsHandler(t *testing.T) { + tt := []struct{ + routeVariable string + shouldPass bool + }{ + {"goroutines", true}, + {"heap", true}, + {"counters", true}, + {"queries", true}, + {"adhadaeqm3k", false}, + } + + for _, tc := range tt { + path := fmt.Sprintf("/metrics/%s", tc.routeVariable) + req, err := http.NewRequest("GET", path, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + + // To add the vars to the context, + // we need to create a router through which we can pass the request. + router := mux.NewRouter() + router.HandleFunc("/metrics/{type}", MetricsHandler) + router.ServeHTTP(rr, req) + + // In this case, our MetricsHandler returns a non-200 response + // for a route variable it doesn't know about. + if rr.Code == http.StatusOK && !tc.shouldPass { + t.Errorf("handler should have failed on routeVariable %s: got %v want %v", + tc.routeVariable, rr.Code, http.StatusOK) + } + } +} +``` + +## Full Example + +Here's a complete, runnable example of a small `mux` based server: + +```go +package main + +import ( + "net/http" + "log" + "github.com/gorilla/mux" +) + +func YourHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Gorilla!\n")) +} + +func main() { + r := mux.NewRouter() + // Routes consist of a path and a handler function. + r.HandleFunc("/", YourHandler) - // Bind to a port and pass our router in - http.ListenAndServe(":8000", r) + // Bind to a port and pass our router in + log.Fatal(http.ListenAndServe(":8000", r)) } ``` diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go index 835f5342e..80601351f 100644 --- a/vendor/github.com/gorilla/mux/doc.go +++ b/vendor/github.com/gorilla/mux/doc.go @@ -10,18 +10,18 @@ http.ServeMux, mux.Router matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: - * Requests can be matched based on URL host, path, path prefix, schemes, - header and query values, HTTP methods or using custom matchers. - * URL hosts and paths can have variables with an optional regular - expression. - * Registered URLs can be built, or "reversed", which helps maintaining - references to resources. - * Routes can be used as subrouters: nested routes are only tested if the - parent route matches. This is useful to define groups of routes that - share common conditions like a host, a path prefix or other repeated - attributes. As a bonus, this optimizes request matching. - * It implements the http.Handler interface so it is compatible with the - standard http.ServeMux. + - Requests can be matched based on URL host, path, path prefix, schemes, + header and query values, HTTP methods or using custom matchers. + - URL hosts, paths and query values can have variables with an optional + regular expression. + - Registered URLs can be built, or "reversed", which helps maintaining + references to resources. + - Routes can be used as subrouters: nested routes are only tested if the + parent route matches. This is useful to define groups of routes that + share common conditions like a host, a path prefix or other repeated + attributes. As a bonus, this optimizes request matching. + - It implements the http.Handler interface so it is compatible with the + standard http.ServeMux. Let's start registering a couple of URL paths and handlers: @@ -47,12 +47,21 @@ variable will be anything until the next slash. For example: r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) +Groups can be used inside patterns, as long as they are non-capturing (?:re). For example: + + r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler) + The names are used to create a map of route variables which can be retrieved calling mux.Vars(): vars := mux.Vars(request) category := vars["category"] +Note that if any capturing groups are present, mux will panic() during parsing. To prevent +this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to +"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably +when capturing groups were present. + And this is all you need to know about the basic usage. More advanced options are explained below. @@ -136,6 +145,31 @@ the inner routes use it as base for their paths: // "/products/{key}/details" s.HandleFunc("/{key}/details", ProductDetailsHandler) +Note that the path provided to PathPrefix() represents a "wildcard": calling +PathPrefix("/static/").Handler(...) means that the handler will be passed any +request that matches "/static/*". This makes it easy to serve static files with mux: + + func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) + } + Now let's see how to build registered URLs. Routes can be named. All routes that define a name can have their URLs built, @@ -154,18 +188,20 @@ key/value pairs for the route variables. For the previous route, we would do: "/articles/technology/42" -This also works for host variables: +This also works for host and query value variables: r := mux.NewRouter() r.Host("{subdomain}.domain.com"). Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). HandlerFunc(ArticleHandler). Name("article") - // url.String() will be "http://news.domain.com/articles/technology/42" + // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", - "id", "42") + "id", "42", + "filter", "gorilla") All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a @@ -202,5 +238,68 @@ as well: url, err := r.Get("article").URL("subdomain", "news", "category", "technology", "id", "42") + +Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking. + + type MiddlewareFunc func(http.Handler) http.Handler + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created). + +A very basic middleware which logs the URI of the request being handled could be written as: + + func simpleMw(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) + } + +Middlewares can be added to a router using `Router.Use()`: + + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.Use(simpleMw) + +A more complex authentication middleware, which maps session token to users, could be written as: + + // Define our struct + type authenticationMiddleware struct { + tokenUsers map[string]string + } + + // Initialize it somewhere + func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" + } + + // Middleware function, which will be called for each request + func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + next.ServeHTTP(w, r) + } else { + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) + } + + r := mux.NewRouter() + r.HandleFunc("/", handler) + + amw := authenticationMiddleware{tokenUsers: make(map[string]string)} + amw.Populate() + + r.Use(amw.Middleware) + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. */ package mux diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go index 94f5ddd9c..1e089906f 100644 --- a/vendor/github.com/gorilla/mux/mux.go +++ b/vendor/github.com/gorilla/mux/mux.go @@ -5,18 +5,25 @@ package mux import ( + "context" "errors" "fmt" "net/http" "path" "regexp" +) - "github.com/gorilla/context" +var ( + // ErrMethodMismatch is returned when the method in the request does not match + // the method defined against the route. + ErrMethodMismatch = errors.New("method is not allowed") + // ErrNotFound is returned when no route match is found. + ErrNotFound = errors.New("no matching route was found") ) // NewRouter returns a new router instance. func NewRouter() *Router { - return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} + return &Router{namedRoutes: make(map[string]*Route)} } // Router registers routes to be matched and dispatches a handler. @@ -24,49 +31,140 @@ func NewRouter() *Router { // It implements the http.Handler interface, so it can be registered to serve // requests: // -// var router = mux.NewRouter() +// var router = mux.NewRouter() // -// func main() { -// http.Handle("/", router) -// } +// func main() { +// http.Handle("/", router) +// } // // Or, for Google App Engine, register it in a init() function: // -// func init() { -// http.Handle("/", router) -// } +// func init() { +// http.Handle("/", router) +// } // // This will send all incoming requests to the router. type Router struct { // Configurable Handler to be used when no route matches. + // This can be used to render your own 404 Not Found errors. NotFoundHandler http.Handler - // Parent route, if this is a subrouter. - parent parentRoute + + // Configurable Handler to be used when the request method does not match the route. + // This can be used to render your own 405 Method Not Allowed errors. + MethodNotAllowedHandler http.Handler + // Routes to be matched, in order. routes []*Route + // Routes by name for URL building. namedRoutes map[string]*Route - // See Router.StrictSlash(). This defines the flag for new routes. + + // If true, do not clear the request context after handling the request. + // + // Deprecated: No effect, since the context is stored on the request itself. + KeepContext bool + + // Slice of middlewares to be called after a match is found + middlewares []middleware + + // configuration shared with `Route` + routeConf +} + +// common route configuration shared between `Router` and `Route` +type routeConf struct { + // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to" + useEncodedPath bool + + // If true, when the path pattern is "/path/", accessing "/path" will + // redirect to the former and vice versa. strictSlash bool - // See Router.SkipClean(). This defines the flag for new routes. + + // If true, when the path pattern is "/path//to", accessing "/path//to" + // will not redirect skipClean bool - // If true, do not clear the request context after handling the request - KeepContext bool + + // Manager for the variables from host and path. + regexp routeRegexpGroup + + // List of matchers. + matchers []matcher + + // The scheme used when building URLs. + buildScheme string + + buildVarsFunc BuildVarsFunc } -// Match matches registered routes against the request. +// returns an effective deep copy of `routeConf` +func copyRouteConf(r routeConf) routeConf { + c := r + + if r.regexp.path != nil { + c.regexp.path = copyRouteRegexp(r.regexp.path) + } + + if r.regexp.host != nil { + c.regexp.host = copyRouteRegexp(r.regexp.host) + } + + c.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries)) + for _, q := range r.regexp.queries { + c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q)) + } + + c.matchers = make([]matcher, len(r.matchers)) + copy(c.matchers, r.matchers) + + return c +} + +func copyRouteRegexp(r *routeRegexp) *routeRegexp { + c := *r + return &c +} + +// Match attempts to match the given request against the router's registered routes. +// +// If the request matches a route of this router or one of its subrouters the Route, +// Handler, and Vars fields of the the match argument are filled and this function +// returns true. +// +// If the request does not match any of this router's or its subrouters' routes +// then this function returns false. If available, a reason for the match failure +// will be filled in the match argument's MatchErr field. If the match failure type +// (eg: not found) has a registered handler, the handler is assigned to the Handler +// field of the match argument. func (r *Router) Match(req *http.Request, match *RouteMatch) bool { for _, route := range r.routes { if route.Match(req, match) { + // Build middleware chain if no error was found + if match.MatchErr == nil { + for i := len(r.middlewares) - 1; i >= 0; i-- { + match.Handler = r.middlewares[i].Middleware(match.Handler) + } + } return true } } + if match.MatchErr == ErrMethodMismatch { + if r.MethodNotAllowedHandler != nil { + match.Handler = r.MethodNotAllowedHandler + return true + } + + return false + } + // Closest match for a router (includes sub-routers) if r.NotFoundHandler != nil { match.Handler = r.NotFoundHandler + match.MatchErr = ErrNotFound return true } + + match.MatchErr = ErrNotFound return false } @@ -76,8 +174,12 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool { // mux.Vars(request). func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if !r.skipClean { + path := req.URL.Path + if r.useEncodedPath { + path = req.URL.EscapedPath() + } // Clean path to canonical form and redirect. - if p := cleanPath(req.URL.Path); p != req.URL.Path { + if p := cleanPath(path); p != path { // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query. // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: @@ -95,39 +197,47 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { var handler http.Handler if r.Match(req, &match) { handler = match.Handler - setVars(req, match.Vars) - setCurrentRoute(req, match.Route) + req = requestWithVars(req, match.Vars) + req = requestWithRoute(req, match.Route) + } + + if handler == nil && match.MatchErr == ErrMethodMismatch { + handler = methodNotAllowedHandler() } + if handler == nil { handler = http.NotFoundHandler() } - if !r.KeepContext { - defer context.Clear(req) - } + handler.ServeHTTP(w, req) } // Get returns a route registered with the given name. func (r *Router) Get(name string) *Route { - return r.getNamedRoutes()[name] + return r.namedRoutes[name] } // GetRoute returns a route registered with the given name. This method // was renamed to Get() and remains here for backwards compatibility. func (r *Router) GetRoute(name string) *Route { - return r.getNamedRoutes()[name] + return r.namedRoutes[name] } // StrictSlash defines the trailing slash behavior for new routes. The initial // value is false. // -// When true, if the route path is "/path/", accessing "/path" will redirect +// When true, if the route path is "/path/", accessing "/path" will perform a redirect // to the former and vice versa. In other words, your application will always // see the path as specified in the route. // // When false, if the route path is "/path", accessing "/path/" will not match // this route and vice versa. // +// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for +// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed +// request will be made as a GET by most clients. Use middleware or client settings +// to modify this behaviour as needed. +// // Special case: when a route sets a path prefix using the PathPrefix() method, // strict slash is ignored for that route because the redirect behavior can't // be determined from a prefix alone. However, any subrouters created from that @@ -150,35 +260,15 @@ func (r *Router) SkipClean(value bool) *Router { return r } -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// getNamedRoutes returns the map where named routes are registered. -func (r *Router) getNamedRoutes() map[string]*Route { - if r.namedRoutes == nil { - if r.parent != nil { - r.namedRoutes = r.parent.getNamedRoutes() - } else { - r.namedRoutes = make(map[string]*Route) - } - } - return r.namedRoutes -} - -// getRegexpGroup returns regexp definitions from the parent route, if any. -func (r *Router) getRegexpGroup() *routeRegexpGroup { - if r.parent != nil { - return r.parent.getRegexpGroup() - } - return nil -} - -func (r *Router) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - return m +// UseEncodedPath tells the router to match the encoded original path +// to the routes. +// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to". +// +// If not called, the router will match the unencoded path to the routes. +// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to" +func (r *Router) UseEncodedPath() *Router { + r.useEncodedPath = true + return r } // ---------------------------------------------------------------------------- @@ -187,11 +277,18 @@ func (r *Router) buildVars(m map[string]string) map[string]string { // NewRoute registers an empty route. func (r *Router) NewRoute() *Route { - route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean} + // initialize a route with a copy of the parent router's configuration + route := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes} r.routes = append(r.routes, route) return route } +// Name registers a new route with a name. +// See Route.Name(). +func (r *Router) Name(name string) *Route { + return r.NewRoute().Name(name) +} + // Handle registers a new route with a matcher for the URL path. // See Route.Path() and Route.Handler(). func (r *Router) Handle(path string, handler http.Handler) *Route { @@ -277,20 +374,21 @@ type WalkFunc func(route *Route, router *Router, ancestors []*Route) error func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { for _, t := range r.routes { - if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" { - continue - } - err := walkFn(t, r, ancestors) if err == SkipRouter { continue } + if err != nil { + return err + } for _, sr := range t.matchers { if h, ok := sr.(*Router); ok { + ancestors = append(ancestors, t) err := h.walk(walkFn, ancestors) if err != nil { return err } + ancestors = ancestors[:len(ancestors)-1] } } if h, ok := t.handler.(*Router); ok { @@ -314,6 +412,11 @@ type RouteMatch struct { Route *Route Handler http.Handler Vars map[string]string + + // MatchErr is set to appropriate matching error + // It is set to ErrMethodMismatch if there is a mismatch in + // the request method and route method + MatchErr error } type contextKey int @@ -325,7 +428,7 @@ const ( // Vars returns the route variables for the current request, if any. func Vars(r *http.Request) map[string]string { - if rv := context.Get(r, varsKey); rv != nil { + if rv := r.Context().Value(varsKey); rv != nil { return rv.(map[string]string) } return nil @@ -334,25 +437,22 @@ func Vars(r *http.Request) map[string]string { // CurrentRoute returns the matched route for the current request, if any. // This only works when called inside the handler of the matched route // because the matched route is stored in the request context which is cleared -// after the handler returns, unless the KeepContext option is set on the -// Router. +// after the handler returns. func CurrentRoute(r *http.Request) *Route { - if rv := context.Get(r, routeKey); rv != nil { + if rv := r.Context().Value(routeKey); rv != nil { return rv.(*Route) } return nil } -func setVars(r *http.Request, val interface{}) { - if val != nil { - context.Set(r, varsKey, val) - } +func requestWithVars(r *http.Request, vars map[string]string) *http.Request { + ctx := context.WithValue(r.Context(), varsKey, vars) + return r.WithContext(ctx) } -func setCurrentRoute(r *http.Request, val interface{}) { - if val != nil { - context.Set(r, routeKey, val) - } +func requestWithRoute(r *http.Request, route *Route) *http.Request { + ctx := context.WithValue(r.Context(), routeKey, route) + return r.WithContext(ctx) } // ---------------------------------------------------------------------------- @@ -415,7 +515,7 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) { return m, nil } -// mapFromPairsToRegex converts variadic string paramers to a +// mapFromPairsToRegex converts variadic string parameters to a // string to regex map. func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { length, err := checkPairs(pairs...) @@ -497,3 +597,12 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s } return true } + +// methodNotAllowed replies to the request with an HTTP status code 405. +func methodNotAllowed(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusMethodNotAllowed) +} + +// methodNotAllowedHandler returns a simple request handler +// that replies to each request with a status code 405. +func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) } diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index 08710bc98..5d05cfa0e 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -14,6 +14,20 @@ import ( "strings" ) +type routeRegexpOptions struct { + strictSlash bool + useEncodedPath bool +} + +type regexpType int + +const ( + regexpTypePath regexpType = iota + regexpTypeHost + regexpTypePrefix + regexpTypeQuery +) + // newRouteRegexp parses a route template and returns a routeRegexp, // used to match a host, a path or a query string. // @@ -24,7 +38,7 @@ import ( // Previously we accepted only Python-like identifiers for variable // names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that // name and pattern can't be empty, and names can't contain a colon. -func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { +func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) { // Check if it is well-formed. idxs, errBraces := braceIndices(tpl) if errBraces != nil { @@ -34,19 +48,18 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash template := tpl // Now let's parse it. defaultPattern := "[^/]+" - if matchQuery { - defaultPattern = "[^?&]*" - } else if matchHost { + if typ == regexpTypeQuery { + defaultPattern = ".*" + } else if typ == regexpTypeHost { defaultPattern = "[^.]+" - matchPrefix = false } // Only match strict slash if not matching - if matchPrefix || matchHost || matchQuery { - strictSlash = false + if typ != regexpTypePath { + options.strictSlash = false } // Set a flag for strictSlash. endSlash := false - if strictSlash && strings.HasSuffix(tpl, "/") { + if options.strictSlash && strings.HasSuffix(tpl, "/") { tpl = tpl[:len(tpl)-1] endSlash = true } @@ -88,18 +101,25 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash // Add the remaining. raw := tpl[end:] pattern.WriteString(regexp.QuoteMeta(raw)) - if strictSlash { + if options.strictSlash { pattern.WriteString("[/]?") } - if matchQuery { + if typ == regexpTypeQuery { // Add the default pattern if the query value is empty if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { pattern.WriteString(defaultPattern) } } - if !matchPrefix { + if typ != regexpTypePrefix { pattern.WriteByte('$') } + + var wildcardHostPort bool + if typ == regexpTypeHost { + if !strings.Contains(pattern.String(), ":") { + wildcardHostPort = true + } + } reverse.WriteString(raw) if endSlash { reverse.WriteByte('/') @@ -109,16 +129,23 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash if errCompile != nil { return nil, errCompile } + + // Check for capturing groups which used to work in older versions + if reg.NumSubexp() != len(idxs)/2 { + panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + + "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") + } + // Done! return &routeRegexp{ - template: template, - matchHost: matchHost, - matchQuery: matchQuery, - strictSlash: strictSlash, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, + template: template, + regexpType: typ, + options: options, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, + wildcardHostPort: wildcardHostPort, }, nil } @@ -127,12 +154,10 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash type routeRegexp struct { // The unmodified template. template string - // True for host match, false for path or query string match. - matchHost bool - // True for query string match, false for path and host match. - matchQuery bool - // The strictSlash value defined on the route, but disabled if PathPrefix was used. - strictSlash bool + // The type of match + regexpType regexpType + // Options for matching + options routeRegexpOptions // Expanded regexp. regexp *regexp.Regexp // Reverse template. @@ -141,19 +166,31 @@ type routeRegexp struct { varsN []string // Variable regexps (validators). varsR []*regexp.Regexp + // Wildcard host-port (no strict port match in hostname) + wildcardHostPort bool } // Match matches the regexp against the URL host or path. func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if !r.matchHost { - if r.matchQuery { - return r.matchQueryString(req) + if r.regexpType == regexpTypeHost { + host := getHost(req) + if r.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } } - - return r.regexp.MatchString(req.URL.Path) + return r.regexp.MatchString(host) } - return r.regexp.MatchString(getHost(req)) + if r.regexpType == regexpTypeQuery { + return r.matchQueryString(req) + } + path := req.URL.Path + if r.options.useEncodedPath { + path = req.URL.EscapedPath() + } + return r.regexp.MatchString(path) } // url builds a URL part using the given values. @@ -164,6 +201,9 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { if !ok { return "", fmt.Errorf("mux: missing route variable %q", v) } + if r.regexpType == regexpTypeQuery { + value = url.QueryEscape(value) + } urlValues[k] = value } rv := fmt.Sprintf(r.reverse, urlValues...) @@ -186,18 +226,55 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { // For a URL with foo=bar&baz=ding, we return only the relevant key // value pair for the routeRegexp. func (r *routeRegexp) getURLQuery(req *http.Request) string { - if !r.matchQuery { + if r.regexpType != regexpTypeQuery { return "" } templateKey := strings.SplitN(r.template, "=", 2)[0] - for key, vals := range req.URL.Query() { - if key == templateKey && len(vals) > 0 { - return key + "=" + vals[0] - } + val, ok := findFirstQueryKey(req.URL.RawQuery, templateKey) + if ok { + return templateKey + "=" + val } return "" } +// findFirstQueryKey returns the same result as (*url.URL).Query()[key][0]. +// If key was not found, empty string and false is returned. +func findFirstQueryKey(rawQuery, key string) (value string, ok bool) { + query := []byte(rawQuery) + for len(query) > 0 { + foundKey := query + if i := bytes.IndexAny(foundKey, "&;"); i >= 0 { + foundKey, query = foundKey[:i], foundKey[i+1:] + } else { + query = query[:0] + } + if len(foundKey) == 0 { + continue + } + var value []byte + if i := bytes.IndexByte(foundKey, '='); i >= 0 { + foundKey, value = foundKey[:i], foundKey[i+1:] + } + if len(foundKey) < len(key) { + // Cannot possibly be key. + continue + } + keyString, err := url.QueryUnescape(string(foundKey)) + if err != nil { + continue + } + if keyString != key { + continue + } + valueString, err := url.QueryUnescape(string(value)) + if err != nil { + continue + } + return valueString, true + } + return "", false +} + func (r *routeRegexp) matchQueryString(req *http.Request) bool { return r.regexp.MatchString(r.getURLQuery(req)) } @@ -244,23 +321,33 @@ type routeRegexpGroup struct { } // setMatch extracts the variables from the URL once a route matches. -func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { +func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { // Store host variables. if v.host != nil { host := getHost(req) + if v.host.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } + } matches := v.host.regexp.FindStringSubmatchIndex(host) if len(matches) > 0 { extractVars(host, matches, v.host.varsN, m.Vars) } } + path := req.URL.Path + if r.useEncodedPath { + path = req.URL.EscapedPath() + } // Store path variables. if v.path != nil { - matches := v.path.regexp.FindStringSubmatchIndex(req.URL.Path) + matches := v.path.regexp.FindStringSubmatchIndex(path) if len(matches) > 0 { - extractVars(req.URL.Path, matches, v.path.varsN, m.Vars) + extractVars(path, matches, v.path.varsN, m.Vars) // Check if we should redirect. - if v.path.strictSlash { - p1 := strings.HasSuffix(req.URL.Path, "/") + if v.path.options.strictSlash { + p1 := strings.HasSuffix(path, "/") p2 := strings.HasSuffix(v.path.template, "/") if p1 != p2 { u, _ := url.Parse(req.URL.String()) @@ -269,7 +356,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } else { u.Path += "/" } - m.Handler = http.RedirectHandler(u.String(), 301) + m.Handler = http.RedirectHandler(u.String(), http.StatusMovedPermanently) } } } @@ -285,28 +372,17 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } // getHost tries its best to return the request host. +// According to section 14.23 of RFC 2616 the Host header +// can include the port number if the default value of 80 is not used. func getHost(r *http.Request) string { if r.URL.IsAbs() { return r.URL.Host } - host := r.Host - // Slice off any port information. - if i := strings.Index(host, ":"); i != -1 { - host = host[:i] - } - return host - + return r.Host } func extractVars(input string, matches []int, names []string, output map[string]string) { - matchesCount := 0 - prevEnd := -1 - for i := 2; i < len(matches) && matchesCount < len(names); i += 2 { - if prevEnd < matches[i+1] { - value := input[matches[i]:matches[i+1]] - output[names[matchesCount]] = value - prevEnd = matches[i+1] - matchesCount++ - } + for i, name := range names { + output[name] = input[matches[2*i+2]:matches[2*i+3]] } } diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go index 6c53f9f1d..e8f11df22 100644 --- a/vendor/github.com/gorilla/mux/route.go +++ b/vendor/github.com/gorilla/mux/route.go @@ -15,20 +15,8 @@ import ( // Route stores information to match a request and build URLs. type Route struct { - // Parent where the route was registered (a Router). - parent parentRoute // Request handler for the route. handler http.Handler - // List of matchers. - matchers []matcher - // Manager for the variables from host and path. - regexp *routeRegexpGroup - // If true, when the path pattern is "/path/", accessing "/path" will - // redirect to the former and vice versa. - strictSlash bool - // If true, when the path pattern is "/path//to", accessing "/path//to" - // will not redirect - skipClean bool // If true, this route never matches: it is only used to build URLs. buildOnly bool // The name used to build URLs. @@ -36,9 +24,15 @@ type Route struct { // Error resulted from building a route. err error - buildVarsFunc BuildVarsFunc + // "global" reference to all named routes + namedRoutes map[string]*Route + + // config possibly passed in from `Router` + routeConf } +// SkipClean reports whether path cleaning is enabled for this route via +// Router.SkipClean. func (r *Route) SkipClean() bool { return r.skipClean } @@ -48,12 +42,55 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if r.buildOnly || r.err != nil { return false } + + var matchErr error + // Match everything. for _, m := range r.matchers { if matched := m.Match(req, match); !matched { + if _, ok := m.(methodMatcher); ok { + matchErr = ErrMethodMismatch + continue + } + + // Ignore ErrNotFound errors. These errors arise from match call + // to Subrouters. + // + // This prevents subsequent matching subrouters from failing to + // run middleware. If not ignored, the middleware would see a + // non-nil MatchErr and be skipped, even when there was a + // matching route. + if match.MatchErr == ErrNotFound { + match.MatchErr = nil + } + + matchErr = nil // nolint:ineffassign return false + } else { + // Multiple routes may share the same path but use different HTTP methods. For instance: + // Route 1: POST "/users/{id}". + // Route 2: GET "/users/{id}", parameters: "id": "[0-9]+". + // + // The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2", + // The router should return a "Not Found" error as no route fully matches this request. + if match.MatchErr == ErrMethodMismatch { + match.MatchErr = nil + } } } + + if matchErr != nil { + match.MatchErr = matchErr + return false + } + + if match.MatchErr == ErrMethodMismatch && r.handler != nil { + // We found a route which matches request method, clear MatchErr + match.MatchErr = nil + // Then override the mis-matched handler + match.Handler = r.handler + } + // Yay, we have a match. Let's collect some info about it. if match.Route == nil { match.Route = r @@ -64,10 +101,9 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if match.Vars == nil { match.Vars = make(map[string]string) } + // Set variables. - if r.regexp != nil { - r.regexp.setMatch(req, match, r) - } + r.regexp.setMatch(req, match, r) return true } @@ -109,7 +145,7 @@ func (r *Route) GetHandler() http.Handler { // Name ----------------------------------------------------------------------- // Name sets the name for the route, used to build URLs. -// If the name was registered already it will be overwritten. +// It is an error to call Name more than once on a route. func (r *Route) Name(name string) *Route { if r.name != "" { r.err = fmt.Errorf("mux: route already has name %q, can't set %q", @@ -117,7 +153,7 @@ func (r *Route) Name(name string) *Route { } if r.err == nil { r.name = name - r.getNamedRoutes()[name] = r + r.namedRoutes[name] = r } return r } @@ -145,20 +181,22 @@ func (r *Route) addMatcher(m matcher) *Route { } // addRegexpMatcher adds a host or path matcher and builder to a route. -func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { +func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { if r.err != nil { return r.err } - r.regexp = r.getRegexpGroup() - if !matchHost && !matchQuery { - if len(tpl) == 0 || tpl[0] != '/' { + if typ == regexpTypePath || typ == regexpTypePrefix { + if len(tpl) > 0 && tpl[0] != '/' { return fmt.Errorf("mux: path must start with a slash, got %q", tpl) } if r.regexp.path != nil { tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl } } - rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash) + rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ + strictSlash: r.strictSlash, + useEncodedPath: r.useEncodedPath, + }) if err != nil { return err } @@ -167,7 +205,7 @@ func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery return err } } - if matchHost { + if typ == regexpTypeHost { if r.regexp.path != nil { if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { return err @@ -180,7 +218,7 @@ func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery return err } } - if matchQuery { + if typ == regexpTypeQuery { r.regexp.queries = append(r.regexp.queries, rr) } else { r.regexp.path = rr @@ -202,9 +240,9 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { // Headers adds a matcher for request header values. // It accepts a sequence of key/value pairs to be matched. For example: // -// r := mux.NewRouter() -// r.Headers("Content-Type", "application/json", -// "X-Requested-With", "XMLHttpRequest") +// r := mux.NewRouter().NewRoute() +// r.Headers("Content-Type", "application/json", +// "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both request header values match. // If the value is an empty string, it will match any value if the key is set. @@ -227,12 +265,13 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { // HeadersRegexp accepts a sequence of key/value pairs, where the value has regex // support. For example: // -// r := mux.NewRouter() -// r.HeadersRegexp("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") +// r := mux.NewRouter().NewRoute() +// r.HeadersRegexp("Content-Type", "application/(text|json)", +// "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both the request header matches both regular expressions. -// It the value is an empty string, it will match any value if the key is set. +// If the value is an empty string, it will match any value if the key is set. +// Use the start and end of string anchors (^ and $) to match an exact value. func (r *Route) HeadersRegexp(pairs ...string) *Route { if r.err == nil { var headers map[string]*regexp.Regexp @@ -254,15 +293,15 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route { // // For example: // -// r := mux.NewRouter() -// r.Host("www.example.com") -// r.Host("{subdomain}.domain.com") -// r.Host("{subdomain:[a-z]+}.domain.com") +// r := mux.NewRouter().NewRoute() +// r.Host("www.example.com") +// r.Host("{subdomain}.domain.com") +// r.Host("{subdomain:[a-z]+}.domain.com") // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Host(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, true, false, false) + r.err = r.addRegexpMatcher(tpl, regexpTypeHost) return r } @@ -313,16 +352,16 @@ func (r *Route) Methods(methods ...string) *Route { // // For example: // -// r := mux.NewRouter() -// r.Path("/products/").Handler(ProductsHandler) -// r.Path("/products/{key}").Handler(ProductsHandler) -// r.Path("/articles/{category}/{id:[0-9]+}"). -// Handler(ArticleHandler) +// r := mux.NewRouter().NewRoute() +// r.Path("/products/").Handler(ProductsHandler) +// r.Path("/products/{key}").Handler(ProductsHandler) +// r.Path("/articles/{category}/{id:[0-9]+}"). +// Handler(ArticleHandler) // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Path(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, false, false) + r.err = r.addRegexpMatcher(tpl, regexpTypePath) return r } @@ -338,7 +377,7 @@ func (r *Route) Path(tpl string) *Route { // Also note that the setting of Router.StrictSlash() has no effect on routes // with a PathPrefix matcher. func (r *Route) PathPrefix(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, true, false) + r.err = r.addRegexpMatcher(tpl, regexpTypePrefix) return r } @@ -348,13 +387,13 @@ func (r *Route) PathPrefix(tpl string) *Route { // It accepts a sequence of key/value pairs. Values may define variables. // For example: // -// r := mux.NewRouter() -// r.Queries("foo", "bar", "id", "{id:[0-9]+}") +// r := mux.NewRouter().NewRoute() +// r.Queries("foo", "bar", "id", "{id:[0-9]+}") // // The above route will only match if the URL contains the defined queries // values, e.g.: ?foo=bar&id=42. // -// It the value is an empty string, it will match any value if the key is set. +// If the value is an empty string, it will match any value if the key is set. // // Variables can define an optional regexp pattern to be matched: // @@ -369,7 +408,7 @@ func (r *Route) Queries(pairs ...string) *Route { return nil } for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, false, true); r.err != nil { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil { return r } } @@ -383,15 +422,37 @@ func (r *Route) Queries(pairs ...string) *Route { type schemeMatcher []string func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.URL.Scheme) + scheme := r.URL.Scheme + // https://golang.org/pkg/net/http/#Request + // "For [most] server requests, fields other than Path and RawQuery will be + // empty." + // Since we're an http muxer, the scheme is either going to be http or https + // though, so we can just set it based on the tls termination state. + if scheme == "" { + if r.TLS == nil { + scheme = "http" + } else { + scheme = "https" + } + } + return matchInArray(m, scheme) } // Schemes adds a matcher for URL schemes. // It accepts a sequence of schemes to be matched, e.g.: "http", "https". +// If the request's URL has a scheme set, it will be matched against. +// Generally, the URL scheme will only be set if a previous handler set it, +// such as the ProxyHeaders handler from gorilla/handlers. +// If unset, the scheme will be determined based on the request's TLS +// termination state. +// The first argument to Schemes will be used when constructing a route URL. func (r *Route) Schemes(schemes ...string) *Route { for k, v := range schemes { schemes[k] = strings.ToLower(v) } + if len(schemes) > 0 { + r.buildScheme = schemes[0] + } return r.addMatcher(schemeMatcher(schemes)) } @@ -404,7 +465,15 @@ type BuildVarsFunc func(map[string]string) map[string]string // BuildVarsFunc adds a custom function to be used to modify build variables // before a route's URL is built. func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { - r.buildVarsFunc = f + if r.buildVarsFunc != nil { + // compose the old and new functions + old := r.buildVarsFunc + r.buildVarsFunc = func(m map[string]string) map[string]string { + return f(old(m)) + } + } else { + r.buildVarsFunc = f + } return r } @@ -414,16 +483,17 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { // // It will test the inner routes only if the parent route matched. For example: // -// r := mux.NewRouter() -// s := r.Host("www.example.com").Subrouter() -// s.HandleFunc("/products/", ProductsHandler) -// s.HandleFunc("/products/{key}", ProductHandler) -// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +// r := mux.NewRouter().NewRoute() +// s := r.Host("www.example.com").Subrouter() +// s.HandleFunc("/products/", ProductsHandler) +// s.HandleFunc("/products/{key}", ProductHandler) +// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) // // Here, the routes registered in the subrouter won't be tested if the host // doesn't match. func (r *Route) Subrouter() *Router { - router := &Router{parent: r, strictSlash: r.strictSlash} + // initialize a subrouter with a copy of the parent route's configuration + router := &Router{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes} r.addMatcher(router) return router } @@ -437,29 +507,36 @@ func (r *Route) Subrouter() *Router { // It accepts a sequence of key/value pairs for the route variables. For // example, given this route: // -// r := mux.NewRouter() -// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Name("article") // // ...a URL for it can be built using: // -// url, err := r.Get("article").URL("category", "technology", "id", "42") +// url, err := r.Get("article").URL("category", "technology", "id", "42") // // ...which will return an url.URL with the following path: // -// "/articles/technology/42" +// "/articles/technology/42" // // This also works for host variables: // -// r := mux.NewRouter() -// r.Host("{subdomain}.domain.com"). -// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Host("{subdomain}.domain.com"). +// Name("article") +// +// // url.String() will be "http://news.domain.com/articles/technology/42" +// url, err := r.Get("article").URL("subdomain", "news", +// "category", "technology", +// "id", "42") // -// // url.String() will be "http://news.domain.com/articles/technology/42" -// url, err := r.Get("article").URL("subdomain", "news", -// "category", "technology", -// "id", "42") +// The scheme of the resulting url will be the first argument that was passed to Schemes: +// +// // url.String() will be "https://example.com" +// r := mux.NewRouter().NewRoute() +// url, err := r.Host("example.com") +// .Schemes("https", "http").URL() // // All variables defined in the route are required, and their values must // conform to the corresponding patterns. @@ -467,30 +544,38 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) { if r.err != nil { return nil, r.err } - if r.regexp == nil { - return nil, errors.New("mux: route doesn't have a host or path") - } values, err := r.prepareVars(pairs...) if err != nil { return nil, err } var scheme, host, path string + queries := make([]string, 0, len(r.regexp.queries)) if r.regexp.host != nil { - // Set a default scheme. - scheme = "http" if host, err = r.regexp.host.url(values); err != nil { return nil, err } + scheme = "http" + if r.buildScheme != "" { + scheme = r.buildScheme + } } if r.regexp.path != nil { if path, err = r.regexp.path.url(values); err != nil { return nil, err } } + for _, q := range r.regexp.queries { + var query string + if query, err = q.url(values); err != nil { + return nil, err + } + queries = append(queries, query) + } return &url.URL{ - Scheme: scheme, - Host: host, - Path: path, + Scheme: scheme, + Host: host, + Path: path, + RawQuery: strings.Join(queries, "&"), }, nil } @@ -501,7 +586,7 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) { if r.err != nil { return nil, r.err } - if r.regexp == nil || r.regexp.host == nil { + if r.regexp.host == nil { return nil, errors.New("mux: route doesn't have a host") } values, err := r.prepareVars(pairs...) @@ -512,10 +597,14 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) { if err != nil { return nil, err } - return &url.URL{ + u := &url.URL{ Scheme: "http", Host: host, - }, nil + } + if r.buildScheme != "" { + u.Scheme = r.buildScheme + } + return u, nil } // URLPath builds the path part of the URL for a route. See Route.URL(). @@ -525,7 +614,7 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) { if r.err != nil { return nil, r.err } - if r.regexp == nil || r.regexp.path == nil { + if r.regexp.path == nil { return nil, errors.New("mux: route doesn't have a path") } values, err := r.prepareVars(pairs...) @@ -550,12 +639,80 @@ func (r *Route) GetPathTemplate() (string, error) { if r.err != nil { return "", r.err } - if r.regexp == nil || r.regexp.path == nil { + if r.regexp.path == nil { return "", errors.New("mux: route doesn't have a path") } return r.regexp.path.template, nil } +// GetPathRegexp returns the expanded regular expression used to match route path. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define a path. +func (r *Route) GetPathRegexp() (string, error) { + if r.err != nil { + return "", r.err + } + if r.regexp.path == nil { + return "", errors.New("mux: route does not have a path") + } + return r.regexp.path.regexp.String(), nil +} + +// GetQueriesRegexp returns the expanded regular expressions used to match the +// route queries. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not have queries. +func (r *Route) GetQueriesRegexp() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + queries := make([]string, 0, len(r.regexp.queries)) + for _, query := range r.regexp.queries { + queries = append(queries, query.regexp.String()) + } + return queries, nil +} + +// GetQueriesTemplates returns the templates used to build the +// query matching. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define queries. +func (r *Route) GetQueriesTemplates() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + queries := make([]string, 0, len(r.regexp.queries)) + for _, query := range r.regexp.queries { + queries = append(queries, query.template) + } + return queries, nil +} + +// GetMethods returns the methods the route matches against +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if route does not have methods. +func (r *Route) GetMethods() ([]string, error) { + if r.err != nil { + return nil, r.err + } + for _, m := range r.matchers { + if methods, ok := m.(methodMatcher); ok { + return []string(methods), nil + } + } + return nil, errors.New("mux: route doesn't have methods") +} + // GetHostTemplate returns the template used to build the // route match. // This is useful for building simple REST API documentation and for instrumentation @@ -565,12 +722,31 @@ func (r *Route) GetHostTemplate() (string, error) { if r.err != nil { return "", r.err } - if r.regexp == nil || r.regexp.host == nil { + if r.regexp.host == nil { return "", errors.New("mux: route doesn't have a host") } return r.regexp.host.template, nil } +// GetVarNames returns the names of all variables added by regexp matchers +// These can be used to know which route variables should be passed into r.URL() +func (r *Route) GetVarNames() ([]string, error) { + if r.err != nil { + return nil, r.err + } + var varNames []string + if r.regexp.host != nil { + varNames = append(varNames, r.regexp.host.varsN...) + } + if r.regexp.path != nil { + varNames = append(varNames, r.regexp.path.varsN...) + } + for _, regx := range r.regexp.queries { + varNames = append(varNames, regx.varsN...) + } + return varNames, nil +} + // prepareVars converts the route variable pairs into a map. If the route has a // BuildVarsFunc, it is invoked. func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { @@ -582,53 +758,8 @@ func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { } func (r *Route) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } if r.buildVarsFunc != nil { m = r.buildVarsFunc(m) } return m } - -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// parentRoute allows routes to know about parent host and path definitions. -type parentRoute interface { - getNamedRoutes() map[string]*Route - getRegexpGroup() *routeRegexpGroup - buildVars(map[string]string) map[string]string -} - -// getNamedRoutes returns the map where named routes are registered. -func (r *Route) getNamedRoutes() map[string]*Route { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - return r.parent.getNamedRoutes() -} - -// getRegexpGroup returns regexp definitions from this route. -func (r *Route) getRegexpGroup() *routeRegexpGroup { - if r.regexp == nil { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - regexp := r.parent.getRegexpGroup() - if regexp == nil { - r.regexp = new(routeRegexpGroup) - } else { - // Copy. - r.regexp = &routeRegexpGroup{ - host: regexp.host, - path: regexp.path, - queries: regexp.queries, - } - } - } - return r.regexp -} diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md index 19aa2e75c..d33ed7fdd 100644 --- a/vendor/github.com/gorilla/websocket/README.md +++ b/vendor/github.com/gorilla/websocket/README.md @@ -6,6 +6,7 @@ Gorilla WebSocket is a [Go](http://golang.org/) implementation of the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. + ### Documentation * [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc) @@ -30,35 +31,3 @@ The Gorilla WebSocket package passes the server tests in the [Autobahn Test Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). -### Gorilla WebSocket compared with other packages - - - - - - - - - - - - - - - - - - -
github.com/gorillagolang.org/x/net
RFC 6455 Features
Passes Autobahn Test SuiteYesNo
Receive fragmented messageYesNo, see note 1
Send close messageYesNo
Send pings and receive pongsYesNo
Get the type of a received data messageYesYes, see note 2
Other Features
Compression ExtensionsExperimentalNo
Read message using io.ReaderYesNo, see note 3
Write message using io.WriteCloserYesNo, see note 3
- -Notes: - -1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html). -2. The application can get the type of a received data message by implementing - a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal) - function. -3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries. - Read returns when the input buffer is full or a frame boundary is - encountered. Each call to Write sends a single frame message. The Gorilla - io.Reader and io.WriteCloser operate on a single WebSocket message. - diff --git a/vendor/github.com/gorilla/websocket/client.go b/vendor/github.com/gorilla/websocket/client.go index 962c06a39..04fdafee1 100644 --- a/vendor/github.com/gorilla/websocket/client.go +++ b/vendor/github.com/gorilla/websocket/client.go @@ -9,6 +9,7 @@ import ( "context" "crypto/tls" "errors" + "fmt" "io" "io/ioutil" "net" @@ -48,15 +49,23 @@ func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufS } // A Dialer contains options for connecting to WebSocket server. +// +// It is safe to call Dialer's methods concurrently. type Dialer struct { // NetDial specifies the dial function for creating TCP connections. If // NetDial is nil, net.Dial is used. NetDial func(network, addr string) (net.Conn, error) // NetDialContext specifies the dial function for creating TCP connections. If - // NetDialContext is nil, net.DialContext is used. + // NetDialContext is nil, NetDial is used. NetDialContext func(ctx context.Context, network, addr string) (net.Conn, error) + // NetDialTLSContext specifies the dial function for creating TLS/TCP connections. If + // NetDialTLSContext is nil, NetDialContext is used. + // If NetDialTLSContext is set, Dial assumes the TLS handshake is done there and + // TLSClientConfig is ignored. + NetDialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error) + // Proxy specifies a function to return a proxy for a given // Request. If the function returns a non-nil error, the // request is aborted with the provided error. @@ -65,6 +74,8 @@ type Dialer struct { // TLSClientConfig specifies the TLS configuration to use with tls.Client. // If nil, the default configuration is used. + // If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake + // is done there and TLSClientConfig is ignored. TLSClientConfig *tls.Config // HandshakeTimeout specifies the duration for the handshake to complete. @@ -176,7 +187,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } req := &http.Request{ - Method: "GET", + Method: http.MethodGet, URL: u, Proto: "HTTP/1.1", ProtoMajor: 1, @@ -237,13 +248,32 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h // Get network dial function. var netDial func(network, add string) (net.Conn, error) - if d.NetDialContext != nil { - netDial = func(network, addr string) (net.Conn, error) { - return d.NetDialContext(ctx, network, addr) + switch u.Scheme { + case "http": + if d.NetDialContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialContext(ctx, network, addr) + } + } else if d.NetDial != nil { + netDial = d.NetDial } - } else if d.NetDial != nil { - netDial = d.NetDial - } else { + case "https": + if d.NetDialTLSContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialTLSContext(ctx, network, addr) + } + } else if d.NetDialContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialContext(ctx, network, addr) + } + } else if d.NetDial != nil { + netDial = d.NetDial + } + default: + return nil, nil, errMalformedURL + } + + if netDial == nil { netDialer := &net.Dialer{} netDial = func(network, addr string) (net.Conn, error) { return netDialer.DialContext(ctx, network, addr) @@ -289,14 +319,14 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } netConn, err := netDial("tcp", hostPort) + if err != nil { + return nil, nil, err + } if trace != nil && trace.GotConn != nil { trace.GotConn(httptrace.GotConnInfo{ Conn: netConn, }) } - if err != nil { - return nil, nil, err - } defer func() { if netConn != nil { @@ -304,7 +334,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } }() - if u.Scheme == "https" { + if u.Scheme == "https" && d.NetDialTLSContext == nil { + // If NetDialTLSContext is set, assume that the TLS handshake has already been done + cfg := cloneTLSConfig(d.TLSClientConfig) if cfg.ServerName == "" { cfg.ServerName = hostNoPort @@ -312,11 +344,12 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h tlsConn := tls.Client(netConn, cfg) netConn = tlsConn - var err error - if trace != nil { - err = doHandshakeWithTrace(trace, tlsConn, cfg) - } else { - err = doHandshake(tlsConn, cfg) + if trace != nil && trace.TLSHandshakeStart != nil { + trace.TLSHandshakeStart() + } + err := doHandshake(ctx, tlsConn, cfg) + if trace != nil && trace.TLSHandshakeDone != nil { + trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) } if err != nil { @@ -338,6 +371,17 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h resp, err := http.ReadResponse(conn.br, req) if err != nil { + if d.TLSClientConfig != nil { + for _, proto := range d.TLSClientConfig.NextProtos { + if proto != "http/1.1" { + return nil, nil, fmt.Errorf( + "websocket: protocol %q was given but is not supported;"+ + "sharing tls.Config with net/http Transport can cause this error: %w", + proto, err, + ) + } + } + } return nil, nil, err } @@ -348,8 +392,8 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } if resp.StatusCode != 101 || - !strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") || - !strings.EqualFold(resp.Header.Get("Connection"), "upgrade") || + !tokenListContainsValue(resp.Header, "Upgrade", "websocket") || + !tokenListContainsValue(resp.Header, "Connection", "upgrade") || resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) { // Before closing the network connection on return from this // function, slurp up some of the response to aid application @@ -382,14 +426,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h return conn, resp, nil } -func doHandshake(tlsConn *tls.Conn, cfg *tls.Config) error { - if err := tlsConn.Handshake(); err != nil { - return err - } - if !cfg.InsecureSkipVerify { - if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { - return err - } +func cloneTLSConfig(cfg *tls.Config) *tls.Config { + if cfg == nil { + return &tls.Config{} } - return nil + return cfg.Clone() } diff --git a/vendor/github.com/gorilla/websocket/client_clone.go b/vendor/github.com/gorilla/websocket/client_clone.go deleted file mode 100644 index 4f0d94372..000000000 --- a/vendor/github.com/gorilla/websocket/client_clone.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.8 - -package websocket - -import "crypto/tls" - -func cloneTLSConfig(cfg *tls.Config) *tls.Config { - if cfg == nil { - return &tls.Config{} - } - return cfg.Clone() -} diff --git a/vendor/github.com/gorilla/websocket/client_clone_legacy.go b/vendor/github.com/gorilla/websocket/client_clone_legacy.go deleted file mode 100644 index babb007fb..000000000 --- a/vendor/github.com/gorilla/websocket/client_clone_legacy.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.8 - -package websocket - -import "crypto/tls" - -// cloneTLSConfig clones all public fields except the fields -// SessionTicketsDisabled and SessionTicketKey. This avoids copying the -// sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a -// config in active use. -func cloneTLSConfig(cfg *tls.Config) *tls.Config { - if cfg == nil { - return &tls.Config{} - } - return &tls.Config{ - Rand: cfg.Rand, - Time: cfg.Time, - Certificates: cfg.Certificates, - NameToCertificate: cfg.NameToCertificate, - GetCertificate: cfg.GetCertificate, - RootCAs: cfg.RootCAs, - NextProtos: cfg.NextProtos, - ServerName: cfg.ServerName, - ClientAuth: cfg.ClientAuth, - ClientCAs: cfg.ClientCAs, - InsecureSkipVerify: cfg.InsecureSkipVerify, - CipherSuites: cfg.CipherSuites, - PreferServerCipherSuites: cfg.PreferServerCipherSuites, - ClientSessionCache: cfg.ClientSessionCache, - MinVersion: cfg.MinVersion, - MaxVersion: cfg.MaxVersion, - CurvePreferences: cfg.CurvePreferences, - } -} diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go index ca46d2f79..5161ef81f 100644 --- a/vendor/github.com/gorilla/websocket/conn.go +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -13,6 +13,7 @@ import ( "math/rand" "net" "strconv" + "strings" "sync" "time" "unicode/utf8" @@ -401,6 +402,12 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error return nil } +func (c *Conn) writeBufs(bufs ...[]byte) error { + b := net.Buffers(bufs) + _, err := b.WriteTo(c.conn) + return err +} + // WriteControl writes a control message with the given deadline. The allowed // message types are CloseMessage, PingMessage and PongMessage. func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) error { @@ -794,47 +801,69 @@ func (c *Conn) advanceFrame() (int, error) { } // 2. Read and parse first two bytes of frame header. + // To aid debugging, collect and report all errors in the first two bytes + // of the header. + + var errors []string p, err := c.read(2) if err != nil { return noFrame, err } - final := p[0]&finalBit != 0 frameType := int(p[0] & 0xf) + final := p[0]&finalBit != 0 + rsv1 := p[0]&rsv1Bit != 0 + rsv2 := p[0]&rsv2Bit != 0 + rsv3 := p[0]&rsv3Bit != 0 mask := p[1]&maskBit != 0 c.setReadRemaining(int64(p[1] & 0x7f)) c.readDecompress = false - if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 { - c.readDecompress = true - p[0] &^= rsv1Bit + if rsv1 { + if c.newDecompressionReader != nil { + c.readDecompress = true + } else { + errors = append(errors, "RSV1 set") + } + } + + if rsv2 { + errors = append(errors, "RSV2 set") } - if rsv := p[0] & (rsv1Bit | rsv2Bit | rsv3Bit); rsv != 0 { - return noFrame, c.handleProtocolError("unexpected reserved bits 0x" + strconv.FormatInt(int64(rsv), 16)) + if rsv3 { + errors = append(errors, "RSV3 set") } switch frameType { case CloseMessage, PingMessage, PongMessage: if c.readRemaining > maxControlFramePayloadSize { - return noFrame, c.handleProtocolError("control frame length > 125") + errors = append(errors, "len > 125 for control") } if !final { - return noFrame, c.handleProtocolError("control frame not final") + errors = append(errors, "FIN not set on control") } case TextMessage, BinaryMessage: if !c.readFinal { - return noFrame, c.handleProtocolError("message start before final message frame") + errors = append(errors, "data before FIN") } c.readFinal = final case continuationFrame: if c.readFinal { - return noFrame, c.handleProtocolError("continuation after final message frame") + errors = append(errors, "continuation after FIN") } c.readFinal = final default: - return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType)) + errors = append(errors, "bad opcode "+strconv.Itoa(frameType)) + } + + if mask != c.isServer { + errors = append(errors, "bad MASK") + } + + if len(errors) > 0 { + return noFrame, c.handleProtocolError(strings.Join(errors, ", ")) } // 3. Read and parse frame length as per @@ -872,10 +901,6 @@ func (c *Conn) advanceFrame() (int, error) { // 4. Handle frame masking. - if mask != c.isServer { - return noFrame, c.handleProtocolError("incorrect mask flag") - } - if mask { c.readMaskPos = 0 p, err := c.read(len(c.readMaskKey)) @@ -935,7 +960,7 @@ func (c *Conn) advanceFrame() (int, error) { if len(payload) >= 2 { closeCode = int(binary.BigEndian.Uint16(payload)) if !isValidReceivedCloseCode(closeCode) { - return noFrame, c.handleProtocolError("invalid close code") + return noFrame, c.handleProtocolError("bad close code " + strconv.Itoa(closeCode)) } closeText = string(payload[2:]) if !utf8.ValidString(closeText) { @@ -952,7 +977,11 @@ func (c *Conn) advanceFrame() (int, error) { } func (c *Conn) handleProtocolError(message string) error { - c.WriteControl(CloseMessage, FormatCloseMessage(CloseProtocolError, message), time.Now().Add(writeWait)) + data := FormatCloseMessage(CloseProtocolError, message) + if len(data) > maxControlFramePayloadSize { + data = data[:maxControlFramePayloadSize] + } + c.WriteControl(CloseMessage, data, time.Now().Add(writeWait)) return errors.New("websocket: " + message) } @@ -1160,8 +1189,16 @@ func (c *Conn) SetPongHandler(h func(appData string) error) { c.handlePong = h } +// NetConn returns the underlying connection that is wrapped by c. +// Note that writing to or reading from this connection directly will corrupt the +// WebSocket connection. +func (c *Conn) NetConn() net.Conn { + return c.conn +} + // UnderlyingConn returns the internal net.Conn. This can be used to further // modifications to connection specific flags. +// Deprecated: Use the NetConn method. func (c *Conn) UnderlyingConn() net.Conn { return c.conn } diff --git a/vendor/github.com/gorilla/websocket/conn_write.go b/vendor/github.com/gorilla/websocket/conn_write.go deleted file mode 100644 index a509a21f8..000000000 --- a/vendor/github.com/gorilla/websocket/conn_write.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.8 - -package websocket - -import "net" - -func (c *Conn) writeBufs(bufs ...[]byte) error { - b := net.Buffers(bufs) - _, err := b.WriteTo(c.conn) - return err -} diff --git a/vendor/github.com/gorilla/websocket/conn_write_legacy.go b/vendor/github.com/gorilla/websocket/conn_write_legacy.go deleted file mode 100644 index 37edaff5a..000000000 --- a/vendor/github.com/gorilla/websocket/conn_write_legacy.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.8 - -package websocket - -func (c *Conn) writeBufs(bufs ...[]byte) error { - for _, buf := range bufs { - if len(buf) > 0 { - if _, err := c.conn.Write(buf); err != nil { - return err - } - } - } - return nil -} diff --git a/vendor/github.com/gorilla/websocket/mask.go b/vendor/github.com/gorilla/websocket/mask.go index 577fce9ef..d0742bf2a 100644 --- a/vendor/github.com/gorilla/websocket/mask.go +++ b/vendor/github.com/gorilla/websocket/mask.go @@ -2,6 +2,7 @@ // this source code is governed by a BSD-style license that can be found in the // LICENSE file. +//go:build !appengine // +build !appengine package websocket diff --git a/vendor/github.com/gorilla/websocket/mask_safe.go b/vendor/github.com/gorilla/websocket/mask_safe.go index 2aac060e5..36250ca7c 100644 --- a/vendor/github.com/gorilla/websocket/mask_safe.go +++ b/vendor/github.com/gorilla/websocket/mask_safe.go @@ -2,6 +2,7 @@ // this source code is governed by a BSD-style license that can be found in the // LICENSE file. +//go:build appengine // +build appengine package websocket diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go index e87a8c9f0..e0f466b72 100644 --- a/vendor/github.com/gorilla/websocket/proxy.go +++ b/vendor/github.com/gorilla/websocket/proxy.go @@ -48,7 +48,7 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) } connectReq := &http.Request{ - Method: "CONNECT", + Method: http.MethodConnect, URL: &url.URL{Opaque: addr}, Host: addr, Header: connectHeader, diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go index 887d55891..bb3359743 100644 --- a/vendor/github.com/gorilla/websocket/server.go +++ b/vendor/github.com/gorilla/websocket/server.go @@ -23,6 +23,8 @@ func (e HandshakeError) Error() string { return e.message } // Upgrader specifies parameters for upgrading an HTTP connection to a // WebSocket connection. +// +// It is safe to call Upgrader's methods concurrently. type Upgrader struct { // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration @@ -115,8 +117,8 @@ func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header // Upgrade upgrades the HTTP server connection to the WebSocket protocol. // // The responseHeader is included in the response to the client's upgrade -// request. Use the responseHeader to specify cookies (Set-Cookie) and the -// application negotiated subprotocol (Sec-WebSocket-Protocol). +// request. Use the responseHeader to specify cookies (Set-Cookie). To specify +// subprotocols supported by the server, set Upgrader.Subprotocols directly. // // If the upgrade fails, then Upgrade replies to the client with an HTTP error // response. @@ -131,7 +133,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header") } - if r.Method != "GET" { + if r.Method != http.MethodGet { return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET") } @@ -152,8 +154,8 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade } challengeKey := r.Header.Get("Sec-Websocket-Key") - if challengeKey == "" { - return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank") + if !isValidChallengeKey(challengeKey) { + return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header must be Base64 encoded value of 16-byte in length") } subprotocol := u.selectSubprotocol(r, responseHeader) diff --git a/vendor/github.com/gorilla/websocket/trace.go b/vendor/github.com/gorilla/websocket/trace.go deleted file mode 100644 index 834f122a0..000000000 --- a/vendor/github.com/gorilla/websocket/trace.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build go1.8 - -package websocket - -import ( - "crypto/tls" - "net/http/httptrace" -) - -func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { - if trace.TLSHandshakeStart != nil { - trace.TLSHandshakeStart() - } - err := doHandshake(tlsConn, cfg) - if trace.TLSHandshakeDone != nil { - trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) - } - return err -} diff --git a/vendor/github.com/gorilla/websocket/trace_17.go b/vendor/github.com/gorilla/websocket/trace_17.go deleted file mode 100644 index 77d05a0b5..000000000 --- a/vendor/github.com/gorilla/websocket/trace_17.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !go1.8 - -package websocket - -import ( - "crypto/tls" - "net/http/httptrace" -) - -func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { - return doHandshake(tlsConn, cfg) -} diff --git a/vendor/github.com/gorilla/websocket/util.go b/vendor/github.com/gorilla/websocket/util.go index 7bf2f66c6..31a5dee64 100644 --- a/vendor/github.com/gorilla/websocket/util.go +++ b/vendor/github.com/gorilla/websocket/util.go @@ -281,3 +281,18 @@ headers: } return result } + +// isValidChallengeKey checks if the argument meets RFC6455 specification. +func isValidChallengeKey(s string) bool { + // From RFC6455: + // + // A |Sec-WebSocket-Key| header field with a base64-encoded (see + // Section 4 of [RFC4648]) value that, when decoded, is 16 bytes in + // length. + + if s == "" { + return false + } + decoded, err := base64.StdEncoding.DecodeString(s) + return err == nil && len(decoded) == 16 +} diff --git a/vendor/github.com/hashicorp/golang-lru/2q.go b/vendor/github.com/hashicorp/golang-lru/2q.go index e474cd075..15fcad030 100644 --- a/vendor/github.com/hashicorp/golang-lru/2q.go +++ b/vendor/github.com/hashicorp/golang-lru/2q.go @@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) { // New2QParams creates a new TwoQueueCache using the provided // parameter values. -func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) { +func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) { if size <= 0 { return nil, fmt.Errorf("invalid size") } @@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) { // Add to the recently seen list c.ensureSpace(false) c.recent.Add(key, value) - return } // ensureSpace is used to ensure we have space in the cache diff --git a/vendor/github.com/hashicorp/golang-lru/LICENSE b/vendor/github.com/hashicorp/golang-lru/LICENSE index be2cc4dfb..0e5d580e0 100644 --- a/vendor/github.com/hashicorp/golang-lru/LICENSE +++ b/vendor/github.com/hashicorp/golang-lru/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2014 HashiCorp, Inc. + Mozilla Public License, version 2.0 1. Definitions diff --git a/vendor/github.com/hashicorp/golang-lru/README.md b/vendor/github.com/hashicorp/golang-lru/README.md index 33e58cfaf..03bcfb5b7 100644 --- a/vendor/github.com/hashicorp/golang-lru/README.md +++ b/vendor/github.com/hashicorp/golang-lru/README.md @@ -1,25 +1,7 @@ golang-lru ========== -This provides the `lru` package which implements a fixed-size -thread safe LRU cache. It is based on the cache in Groupcache. - -Documentation -============= - -Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru) - -Example -======= - -Using the LRU is very simple: - -```go -l, _ := New(128) -for i := 0; i < 256; i++ { - l.Add(i, nil) -} -if l.Len() != 128 { - panic(fmt.Sprintf("bad len: %v", l.Len())) -} -``` +Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will +not be updated anymore. The v2 version supports generics and is faster; old code +can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for +backwards compatibility. diff --git a/vendor/github.com/hashicorp/golang-lru/arc.go b/vendor/github.com/hashicorp/golang-lru/arc.go index 555225a21..e396f8428 100644 --- a/vendor/github.com/hashicorp/golang-lru/arc.go +++ b/vendor/github.com/hashicorp/golang-lru/arc.go @@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) { // Add to the recently seen list c.t1.Add(key, value) - return } // replace is used to adaptively evict from either T1 or T2 diff --git a/vendor/github.com/hashicorp/golang-lru/lru.go b/vendor/github.com/hashicorp/golang-lru/lru.go index 1cbe04b7d..895d8e3ea 100644 --- a/vendor/github.com/hashicorp/golang-lru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/lru.go @@ -6,10 +6,17 @@ import ( "github.com/hashicorp/golang-lru/simplelru" ) +const ( + // DefaultEvictedBufferSize defines the default buffer size to store evicted key/val + DefaultEvictedBufferSize = 16 +) + // Cache is a thread-safe fixed size LRU cache. type Cache struct { - lru simplelru.LRUCache - lock sync.RWMutex + lru *simplelru.LRU + evictedKeys, evictedVals []interface{} + onEvictedCB func(k, v interface{}) + lock sync.RWMutex } // New creates an LRU of the given size. @@ -19,30 +26,63 @@ func New(size int) (*Cache, error) { // NewWithEvict constructs a fixed size cache with the given eviction // callback. -func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) { - lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted)) - if err != nil { - return nil, err +func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) { + // create a cache with default settings + c = &Cache{ + onEvictedCB: onEvicted, } - c := &Cache{ - lru: lru, + if onEvicted != nil { + c.initEvictBuffers() + onEvicted = c.onEvicted } - return c, nil + c.lru, err = simplelru.NewLRU(size, onEvicted) + return +} + +func (c *Cache) initEvictBuffers() { + c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize) + c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize) +} + +// onEvicted save evicted key/val and sent in externally registered callback +// outside of critical section +func (c *Cache) onEvicted(k, v interface{}) { + c.evictedKeys = append(c.evictedKeys, k) + c.evictedVals = append(c.evictedVals, v) } // Purge is used to completely clear the cache. func (c *Cache) Purge() { + var ks, vs []interface{} c.lock.Lock() c.lru.Purge() + if c.onEvictedCB != nil && len(c.evictedKeys) > 0 { + ks, vs = c.evictedKeys, c.evictedVals + c.initEvictBuffers() + } c.lock.Unlock() + // invoke callback outside of critical section + if c.onEvictedCB != nil { + for i := 0; i < len(ks); i++ { + c.onEvictedCB(ks[i], vs[i]) + } + } } -// Add adds a value to the cache. Returns true if an eviction occurred. +// Add adds a value to the cache. Returns true if an eviction occurred. func (c *Cache) Add(key, value interface{}) (evicted bool) { + var k, v interface{} c.lock.Lock() evicted = c.lru.Add(key, value) + if c.onEvictedCB != nil && evicted { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } c.lock.Unlock() - return evicted + if c.onEvictedCB != nil && evicted { + c.onEvictedCB(k, v) + } + return } // Get looks up a key's value from the cache. @@ -71,32 +111,107 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) { return value, ok } -// ContainsOrAdd checks if a key is in the cache without updating the -// recent-ness or deleting it for being stale, and if not, adds the value. +// ContainsOrAdd checks if a key is in the cache without updating the +// recent-ness or deleting it for being stale, and if not, adds the value. // Returns whether found and whether an eviction occurred. func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) { + var k, v interface{} c.lock.Lock() - defer c.lock.Unlock() - if c.lru.Contains(key) { + c.lock.Unlock() return true, false } evicted = c.lru.Add(key, value) + if c.onEvictedCB != nil && evicted { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } + c.lock.Unlock() + if c.onEvictedCB != nil && evicted { + c.onEvictedCB(k, v) + } return false, evicted } +// PeekOrAdd checks if a key is in the cache without updating the +// recent-ness or deleting it for being stale, and if not, adds the value. +// Returns whether found and whether an eviction occurred. +func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) { + var k, v interface{} + c.lock.Lock() + previous, ok = c.lru.Peek(key) + if ok { + c.lock.Unlock() + return previous, true, false + } + evicted = c.lru.Add(key, value) + if c.onEvictedCB != nil && evicted { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } + c.lock.Unlock() + if c.onEvictedCB != nil && evicted { + c.onEvictedCB(k, v) + } + return nil, false, evicted +} + // Remove removes the provided key from the cache. -func (c *Cache) Remove(key interface{}) { +func (c *Cache) Remove(key interface{}) (present bool) { + var k, v interface{} c.lock.Lock() - c.lru.Remove(key) + present = c.lru.Remove(key) + if c.onEvictedCB != nil && present { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } c.lock.Unlock() + if c.onEvictedCB != nil && present { + c.onEvictedCB(k, v) + } + return +} + +// Resize changes the cache size. +func (c *Cache) Resize(size int) (evicted int) { + var ks, vs []interface{} + c.lock.Lock() + evicted = c.lru.Resize(size) + if c.onEvictedCB != nil && evicted > 0 { + ks, vs = c.evictedKeys, c.evictedVals + c.initEvictBuffers() + } + c.lock.Unlock() + if c.onEvictedCB != nil && evicted > 0 { + for i := 0; i < len(ks); i++ { + c.onEvictedCB(ks[i], vs[i]) + } + } + return evicted } // RemoveOldest removes the oldest item from the cache. -func (c *Cache) RemoveOldest() { +func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) { + var k, v interface{} c.lock.Lock() - c.lru.RemoveOldest() + key, value, ok = c.lru.RemoveOldest() + if c.onEvictedCB != nil && ok { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } c.lock.Unlock() + if c.onEvictedCB != nil && ok { + c.onEvictedCB(k, v) + } + return +} + +// GetOldest returns the oldest entry +func (c *Cache) GetOldest() (key, value interface{}, ok bool) { + c.lock.RLock() + key, value, ok = c.lru.GetOldest() + c.lock.RUnlock() + return } // Keys returns a slice of the keys in the cache, from oldest to newest. diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go index 5673773b2..9233583c9 100644 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go @@ -25,7 +25,7 @@ type entry struct { // NewLRU constructs an LRU of the given size func NewLRU(size int, onEvict EvictCallback) (*LRU, error) { if size <= 0 { - return nil, errors.New("Must provide a positive size") + return nil, errors.New("must provide a positive size") } c := &LRU{ size: size, @@ -73,6 +73,9 @@ func (c *LRU) Add(key, value interface{}) (evicted bool) { func (c *LRU) Get(key interface{}) (value interface{}, ok bool) { if ent, ok := c.items[key]; ok { c.evictList.MoveToFront(ent) + if ent.Value.(*entry) == nil { + return nil, false + } return ent.Value.(*entry).value, true } return @@ -106,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) { } // RemoveOldest removes the oldest item from the cache. -func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) { +func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) { ent := c.evictList.Back() if ent != nil { c.removeElement(ent) @@ -117,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) { } // GetOldest returns the oldest entry -func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) { +func (c *LRU) GetOldest() (key, value interface{}, ok bool) { ent := c.evictList.Back() if ent != nil { kv := ent.Value.(*entry) @@ -142,6 +145,19 @@ func (c *LRU) Len() int { return c.evictList.Len() } +// Resize changes the cache size. +func (c *LRU) Resize(size int) (evicted int) { + diff := c.Len() - size + if diff < 0 { + diff = 0 + } + for i := 0; i < diff; i++ { + c.removeOldest() + } + c.size = size + return diff +} + // removeOldest removes the oldest item from the cache. func (c *LRU) removeOldest() { ent := c.evictList.Back() diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go index 74c707744..cb7f8caf0 100644 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go @@ -1,3 +1,4 @@ +// Package simplelru provides simple LRU implementation based on build-in container/list. package simplelru // LRUCache is the interface for simple LRU cache. @@ -10,7 +11,7 @@ type LRUCache interface { // updates the "recently used"-ness of the key. #value, isFound Get(key interface{}) (value interface{}, ok bool) - // Check if a key exsists in cache without updating the recent-ness. + // Checks if a key exists in cache without updating the recent-ness. Contains(key interface{}) (ok bool) // Returns key's value without updating the "recently used"-ness of the key. @@ -31,6 +32,9 @@ type LRUCache interface { // Returns the number of items in the cache. Len() int - // Clear all cache entries + // Clears all cache entries. Purge() + + // Resizes cache, returning number evicted + Resize(int) int } diff --git a/vendor/github.com/hashicorp/hcl/.travis.yml b/vendor/github.com/hashicorp/hcl/.travis.yml index 83dc540ef..cb63a3216 100644 --- a/vendor/github.com/hashicorp/hcl/.travis.yml +++ b/vendor/github.com/hashicorp/hcl/.travis.yml @@ -1,3 +1,13 @@ sudo: false + language: go -go: 1.5 + +go: + - 1.x + - tip + +branches: + only: + - master + +script: make test diff --git a/vendor/github.com/hashicorp/hcl/Makefile b/vendor/github.com/hashicorp/hcl/Makefile index ad404a811..84fd743f5 100644 --- a/vendor/github.com/hashicorp/hcl/Makefile +++ b/vendor/github.com/hashicorp/hcl/Makefile @@ -6,6 +6,7 @@ fmt: generate go fmt ./... test: generate + go get -t ./... go test $(TEST) $(TESTARGS) generate: diff --git a/vendor/github.com/hashicorp/hcl/README.md b/vendor/github.com/hashicorp/hcl/README.md index 3d5b8bd92..c8223326d 100644 --- a/vendor/github.com/hashicorp/hcl/README.md +++ b/vendor/github.com/hashicorp/hcl/README.md @@ -81,9 +81,20 @@ FOO * Boolean values: `true`, `false` * Arrays can be made by wrapping it in `[]`. Example: - `["foo", "bar", 42]`. Arrays can contain primitives - and other arrays, but cannot contain objects. Objects must - use the block syntax shown below. + `["foo", "bar", 42]`. Arrays can contain primitives, + other arrays, and objects. As an alternative, lists + of objects can be created with repeated blocks, using + this structure: + + ```hcl + service { + key = "value" + } + + service { + key = "value" + } + ``` Objects and nested objects are created using the structure shown below: @@ -92,6 +103,16 @@ variable "ami" { description = "the AMI to use" } ``` +This would be equivalent to the following json: +``` json +{ + "variable": { + "ami": { + "description": "the AMI to use" + } + } +} +``` ## Thanks diff --git a/vendor/github.com/hashicorp/hcl/appveyor.yml b/vendor/github.com/hashicorp/hcl/appveyor.yml index e70f03b96..4db0b7112 100644 --- a/vendor/github.com/hashicorp/hcl/appveyor.yml +++ b/vendor/github.com/hashicorp/hcl/appveyor.yml @@ -4,7 +4,7 @@ clone_folder: c:\gopath\src\github.com\hashicorp\hcl environment: GOPATH: c:\gopath init: - - git config --global core.autocrlf true + - git config --global core.autocrlf false install: - cmd: >- echo %Path% @@ -12,5 +12,8 @@ install: go version go env + + go get -t ./... + build_script: - cmd: go test -v ./... diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go index 02888d2ab..bed9ebbe1 100644 --- a/vendor/github.com/hashicorp/hcl/decoder.go +++ b/vendor/github.com/hashicorp/hcl/decoder.go @@ -89,9 +89,9 @@ func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error switch k.Kind() { case reflect.Bool: return d.decodeBool(name, node, result) - case reflect.Float64: + case reflect.Float32, reflect.Float64: return d.decodeFloat(name, node, result) - case reflect.Int: + case reflect.Int, reflect.Int32, reflect.Int64: return d.decodeInt(name, node, result) case reflect.Interface: // When we see an interface, we make our own thing @@ -137,13 +137,13 @@ func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) e func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { switch n := node.(type) { case *ast.LiteralType: - if n.Token.Type == token.FLOAT { + if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER { v, err := strconv.ParseFloat(n.Token.Text, 64) if err != nil { return err } - result.Set(reflect.ValueOf(v)) + result.Set(reflect.ValueOf(v).Convert(result.Type())) return nil } } @@ -164,7 +164,11 @@ func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) er return err } - result.Set(reflect.ValueOf(int(v))) + if result.Kind() == reflect.Interface { + result.Set(reflect.ValueOf(int(v))) + } else { + result.SetInt(v) + } return nil case token.STRING: v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0) @@ -172,7 +176,11 @@ func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) er return err } - result.Set(reflect.ValueOf(int(v))) + if result.Kind() == reflect.Interface { + result.Set(reflect.ValueOf(int(v))) + } else { + result.SetInt(v) + } return nil } } @@ -409,7 +417,6 @@ func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) if result.Kind() == reflect.Interface { result = result.Elem() } - // Create the slice if it isn't nil resultType := result.Type() resultElemType := resultType.Elem() @@ -443,6 +450,12 @@ func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) // Decode val := reflect.Indirect(reflect.New(resultElemType)) + + // if item is an object that was decoded from ambiguous JSON and + // flattened, make sure it's expanded if it needs to decode into a + // defined structure. + item := expandObject(item, val) + if err := d.decode(fieldName, item, val); err != nil { return err } @@ -455,6 +468,57 @@ func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) return nil } +// expandObject detects if an ambiguous JSON object was flattened to a List which +// should be decoded into a struct, and expands the ast to properly deocode. +func expandObject(node ast.Node, result reflect.Value) ast.Node { + item, ok := node.(*ast.ObjectItem) + if !ok { + return node + } + + elemType := result.Type() + + // our target type must be a struct + switch elemType.Kind() { + case reflect.Ptr: + switch elemType.Elem().Kind() { + case reflect.Struct: + //OK + default: + return node + } + case reflect.Struct: + //OK + default: + return node + } + + // A list value will have a key and field name. If it had more fields, + // it wouldn't have been flattened. + if len(item.Keys) != 2 { + return node + } + + keyToken := item.Keys[0].Token + item.Keys = item.Keys[1:] + + // we need to un-flatten the ast enough to decode + newNode := &ast.ObjectItem{ + Keys: []*ast.ObjectKey{ + &ast.ObjectKey{ + Token: keyToken, + }, + }, + Val: &ast.ObjectType{ + List: &ast.ObjectList{ + Items: []*ast.ObjectItem{item}, + }, + }, + } + + return newNode +} + func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error { switch n := node.(type) { case *ast.LiteralType: @@ -489,7 +553,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // the yacc parser would always ensure top-level elements were arrays. The new // parser does not make the same guarantees, thus we need to convert any // top-level literal elements into a list. - if _, ok := node.(*ast.LiteralType); ok { + if _, ok := node.(*ast.LiteralType); ok && item != nil { node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} } @@ -509,7 +573,11 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // Compile the list of all the fields that we're going to be decoding // from all the structs. - fields := make(map[*reflect.StructField]reflect.Value) + type field struct { + field reflect.StructField + val reflect.Value + } + fields := []field{} for len(structs) > 0 { structVal := structs[0] structs = structs[1:] @@ -517,6 +585,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) structType := structVal.Type() for i := 0; i < structType.NumField(); i++ { fieldType := structType.Field(i) + tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") + + // Ignore fields with tag name "-" + if tagParts[0] == "-" { + continue + } if fieldType.Anonymous { fieldKind := fieldType.Type.Kind() @@ -531,7 +605,6 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // We have an embedded field. We "squash" the fields down // if specified in the tag. squash := false - tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") for _, tag := range tagParts[1:] { if tag == "squash" { squash = true @@ -547,7 +620,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) } // Normal struct field, store it away - fields[&fieldType] = structVal.Field(i) + fields = append(fields, field{fieldType, structVal.Field(i)}) } } @@ -555,26 +628,27 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) decodedFields := make([]string, 0, len(fields)) decodedFieldsVal := make([]reflect.Value, 0) unusedKeysVal := make([]reflect.Value, 0) - for fieldType, field := range fields { - if !field.IsValid() { + for _, f := range fields { + field, fieldValue := f.field, f.val + if !fieldValue.IsValid() { // This should never happen panic("field is not valid") } // If we can't set the field, then it is unexported or something, // and we just continue onwards. - if !field.CanSet() { + if !fieldValue.CanSet() { continue } - fieldName := fieldType.Name + fieldName := field.Name - tagValue := fieldType.Tag.Get(tagName) + tagValue := field.Tag.Get(tagName) tagParts := strings.SplitN(tagValue, ",", 2) if len(tagParts) >= 2 { switch tagParts[1] { case "decodedFields": - decodedFieldsVal = append(decodedFieldsVal, field) + decodedFieldsVal = append(decodedFieldsVal, fieldValue) continue case "key": if item == nil { @@ -585,10 +659,10 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) } } - field.SetString(item.Keys[0].Token.Value().(string)) + fieldValue.SetString(item.Keys[0].Token.Value().(string)) continue case "unusedKeys": - unusedKeysVal = append(unusedKeysVal, field) + unusedKeysVal = append(unusedKeysVal, fieldValue) continue } } @@ -601,6 +675,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // match (only object with the field), then we decode it exactly. // If it is a prefix match, then we decode the matches. filter := list.Filter(fieldName) + prefixMatches := filter.Children() matches := filter.Elem() if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 { @@ -614,7 +689,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // because we actually want the value. fieldName = fmt.Sprintf("%s.%s", name, fieldName) if len(prefixMatches.Items) > 0 { - if err := d.decode(fieldName, prefixMatches, field); err != nil { + if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil { return err } } @@ -624,12 +699,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) decodeNode = &ast.ObjectList{Items: ot.List.Items} } - if err := d.decode(fieldName, decodeNode, field); err != nil { + if err := d.decode(fieldName, decodeNode, fieldValue); err != nil { return err } } - decodedFields = append(decodedFields, fieldType.Name) + decodedFields = append(decodedFields, field.Name) } if len(decodedFieldsVal) > 0 { diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go index f8bb71a04..6e5ef654b 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go +++ b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go @@ -133,6 +133,12 @@ type ObjectItem struct { } func (o *ObjectItem) Pos() token.Pos { + // I'm not entirely sure what causes this, but removing this causes + // a test failure. We should investigate at some point. + if len(o.Keys) == 0 { + return token.Pos{} + } + return o.Keys[0].Pos() } @@ -150,7 +156,8 @@ func (o *ObjectKey) Pos() token.Pos { type LiteralType struct { Token token.Token - // associated line comment, only when used in a list + // comment types, only used when in a list + LeadComment *CommentGroup LineComment *CommentGroup } @@ -208,4 +215,5 @@ func (c *CommentGroup) Pos() token.Pos { // GoStringer //------------------------------------------------------------------- -func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } +func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } +func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) } diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go index cc129b6c7..64c83bcfb 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go +++ b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go @@ -3,6 +3,7 @@ package parser import ( + "bytes" "errors" "fmt" "strings" @@ -36,6 +37,11 @@ func newParser(src []byte) *Parser { // Parse returns the fully parsed source and returns the abstract syntax tree. func Parse(src []byte) (*ast.File, error) { + // normalize all line endings + // since the scanner and output only work with "\n" line endings, we may + // end up with dangling "\r" characters in the parsed data. + src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) + p := newParser(src) return p.Parse() } @@ -50,7 +56,7 @@ func (p *Parser) Parse() (*ast.File, error) { scerr = &PosError{Pos: pos, Err: errors.New(msg)} } - f.Node, err = p.objectList() + f.Node, err = p.objectList(false) if scerr != nil { return nil, scerr } @@ -62,11 +68,23 @@ func (p *Parser) Parse() (*ast.File, error) { return f, nil } -func (p *Parser) objectList() (*ast.ObjectList, error) { +// objectList parses a list of items within an object (generally k/v pairs). +// The parameter" obj" tells this whether to we are within an object (braces: +// '{', '}') or just at the top level. If we're within an object, we end +// at an RBRACE. +func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) { defer un(trace(p, "ParseObjectList")) node := &ast.ObjectList{} for { + if obj { + tok := p.scan() + p.unscan() + if tok.Type == token.RBRACE { + break + } + } + n, err := p.objectItem() if err == errEofToken { break // we are finished @@ -79,6 +97,13 @@ func (p *Parser) objectList() (*ast.ObjectList, error) { } node.Add(n) + + // object lists can be optionally comma-delimited e.g. when a list of maps + // is being expressed, so a comma is allowed here - it's simply consumed + tok := p.scan() + if tok.Type != token.COMMA { + p.unscan() + } } return node, nil } @@ -172,9 +197,18 @@ func (p *Parser) objectItem() (*ast.ObjectItem, error) { keyStr = append(keyStr, k.Token.Text) } - return nil, fmt.Errorf( - "key '%s' expected start of object ('{') or assignment ('=')", - strings.Join(keyStr, " ")) + return nil, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf( + "key '%s' expected start of object ('{') or assignment ('=')", + strings.Join(keyStr, " ")), + } + } + + // key=#comment + // val + if p.lineComment != nil { + o.LineComment, p.lineComment = p.lineComment, nil } // do a look-ahead for line comment @@ -220,13 +254,27 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { return keys, nil case token.LBRACE: + var err error + + // If we have no keys, then it is a syntax error. i.e. {{}} is not + // allowed. + if len(keys) == 0 { + err = &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type), + } + } + // object - return keys, nil + return keys, err case token.IDENT, token.STRING: keyCount++ keys = append(keys, &ast.ObjectKey{Token: p.tok}) case token.ILLEGAL: - fmt.Println("illegal") + return keys, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("illegal character"), + } default: return keys, &PosError{ Pos: p.tok.Pos, @@ -270,7 +318,7 @@ func (p *Parser) objectType() (*ast.ObjectType, error) { Lbrace: p.tok.Pos, } - l, err := p.objectList() + l, err := p.objectList(true) // if we hit RBRACE, we are good to go (means we parsed all Items), if it's // not a RBRACE, it's an syntax error and we just return it. @@ -278,9 +326,12 @@ func (p *Parser) objectType() (*ast.ObjectType, error) { return nil, err } - // If there is no error, we should be at a RBRACE to end the object - if p.tok.Type != token.RBRACE { - return nil, fmt.Errorf("object expected closing RBRACE got: %s", p.tok.Type) + // No error, scan and expect the ending to be a brace + if tok := p.scan(); tok.Type != token.RBRACE { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type), + } } o.List = l @@ -300,27 +351,38 @@ func (p *Parser) listType() (*ast.ListType, error) { needComma := false for { tok := p.scan() - switch tok.Type { - case token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: - if needComma { + if needComma { + switch tok.Type { + case token.COMMA, token.RBRACK: + default: return nil, &PosError{ Pos: tok.Pos, - Err: fmt.Errorf("unexpected token: %s. Expecting %s", tok.Type, token.COMMA), + Err: fmt.Errorf( + "error parsing list, expected comma or list end, got: %s", + tok.Type), } } - + } + switch tok.Type { + case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: node, err := p.literalType() if err != nil { return nil, err } + // If there is a lead comment, apply it + if p.leadComment != nil { + node.LeadComment = p.leadComment + p.leadComment = nil + } + l.Add(node) needComma = true case token.COMMA: // get next list item or we are at the end // do a look-ahead for line comment p.scan() - if p.lineComment != nil { + if p.lineComment != nil && len(l.List) > 0 { lit, ok := l.List[len(l.List)-1].(*ast.LiteralType) if ok { lit.LineComment = p.lineComment @@ -332,12 +394,28 @@ func (p *Parser) listType() (*ast.ListType, error) { needComma = false continue - case token.BOOL: - // TODO(arslan) should we support? not supported by HCL yet + case token.LBRACE: + // Looks like a nested object, so parse it out + node, err := p.objectType() + if err != nil { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error while trying to parse object within list: %s", err), + } + } + l.Add(node) + needComma = true case token.LBRACK: - // TODO(arslan) should we support nested lists? Even though it's - // written in README of HCL, it's not a part of the grammar - // (not defined in parse.y) + node, err := p.listType() + if err != nil { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error while trying to parse list within list: %s", err), + } + } + l.Add(node) case token.RBRACK: // finished l.Rbrack = p.tok.Pos diff --git a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go index a3f34a7b5..624a18fe3 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go +++ b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go @@ -74,14 +74,6 @@ func (s *Scanner) next() rune { return eof } - if ch == utf8.RuneError && size == 1 { - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - s.err("illegal UTF-8 encoding") - return ch - } - // remember last position s.prevPos = s.srcPos @@ -89,12 +81,27 @@ func (s *Scanner) next() rune { s.lastCharLen = size s.srcPos.Offset += size + if ch == utf8.RuneError && size == 1 { + s.err("illegal UTF-8 encoding") + return ch + } + if ch == '\n' { s.srcPos.Line++ s.lastLineLen = s.srcPos.Column s.srcPos.Column = 0 } + if ch == '\x00' { + s.err("unexpected null character (0x00)") + return eof + } + + if ch == '\uE123' { + s.err("unicode code point U+E123 reserved for internal use") + return utf8.RuneError + } + // debug // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) return ch @@ -224,6 +231,11 @@ func (s *Scanner) Scan() token.Token { func (s *Scanner) scanComment(ch rune) { // single line comments if ch == '#' || (ch == '/' && s.peek() != '*') { + if ch == '/' && s.peek() != '/' { + s.err("expected '/' for comment") + return + } + ch = s.next() for ch != '\n' && ch >= 0 && ch != eof { ch = s.next() @@ -340,7 +352,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type { return token.NUMBER } -// scanMantissa scans the mantissa begining from the rune. It returns the next +// scanMantissa scans the mantissa beginning from the rune. It returns the next // non decimal rune. It's used to determine wheter it's a fraction or exponent. func (s *Scanner) scanMantissa(ch rune) rune { scanned := false @@ -421,16 +433,16 @@ func (s *Scanner) scanHeredoc() { // Read the identifier identBytes := s.src[offs : s.srcPos.Offset-s.lastCharLen] - if len(identBytes) == 0 { + if len(identBytes) == 0 || (len(identBytes) == 1 && identBytes[0] == '-') { s.err("zero-length heredoc anchor") return } var identRegexp *regexp.Regexp if identBytes[0] == '-' { - identRegexp = regexp.MustCompile(fmt.Sprintf(`[[:space:]]*%s\z`, identBytes[1:])) + identRegexp = regexp.MustCompile(fmt.Sprintf(`^[[:space:]]*%s\r*\z`, identBytes[1:])) } else { - identRegexp = regexp.MustCompile(fmt.Sprintf(`[[:space:]]*%s\z`, identBytes)) + identRegexp = regexp.MustCompile(fmt.Sprintf(`^[[:space:]]*%s\r*\z`, identBytes)) } // Read the actual string value @@ -469,7 +481,7 @@ func (s *Scanner) scanString() { // read character after quote ch := s.next() - if ch == '\n' || ch < 0 || ch == eof { + if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { s.err("literal not terminated") return } @@ -525,16 +537,27 @@ func (s *Scanner) scanEscape() rune { // scanDigits scans a rune with the given base for n times. For example an // octal notation \184 would yield in scanDigits(ch, 8, 3) func (s *Scanner) scanDigits(ch rune, base, n int) rune { + start := n for n > 0 && digitVal(ch) < base { ch = s.next() + if ch == eof { + // If we see an EOF, we halt any more scanning of digits + // immediately. + break + } + n-- } if n > 0 { s.err("illegal char escape") } - // we scanned all digits, put the last non digit char back - s.unread() + if n != start && ch != eof { + // we scanned all digits, put the last non digit char back, + // only if we read anything at all + s.unread() + } + return ch } diff --git a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go index e87ac6356..5f981eaa2 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go +++ b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go @@ -27,7 +27,7 @@ func Unquote(s string) (t string, err error) { if quote != '"' { return "", ErrSyntax } - if contains(s, '\n') { + if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { return "", ErrSyntax } @@ -49,7 +49,7 @@ func Unquote(s string) (t string, err error) { for len(s) > 0 { // If we're starting a '${}' then let it through un-unquoted. // Specifically: we don't unquote any characters within the `${}` - // section, except for escaped quotes, which we handle specifically. + // section. if s[0] == '$' && len(s) > 1 && s[1] == '{' { buf = append(buf, '$', '{') s = s[2:] @@ -64,14 +64,6 @@ func Unquote(s string) (t string, err error) { s = s[size:] - // We special case escaped double quotes in interpolations, converting - // them to straight double quotes. - if r == '\\' { - if q, _ := utf8.DecodeRuneInString(s); q == '"' { - continue - } - } - n := utf8.EncodeRune(runeTmp[:], r) buf = append(buf, runeTmp[:n]...) @@ -95,6 +87,10 @@ func Unquote(s string) (t string, err error) { } } + if s[0] == '\n' { + return "", ErrSyntax + } + c, multibyte, ss, err := unquoteChar(s, quote) if err != nil { return "", err diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/vendor/github.com/hashicorp/hcl/hcl/token/token.go index 6e9949804..e37c0664e 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/token/token.go +++ b/vendor/github.com/hashicorp/hcl/hcl/token/token.go @@ -152,6 +152,11 @@ func (t Token) Value() interface{} { f = strconv.Unquote } + // This case occurs if json null is used + if t.Text == "" { + return "" + } + v, err := f(t.Text) if err != nil { panic(fmt.Sprintf("unquote %s err: %s", t.Text, err)) diff --git a/vendor/github.com/hashicorp/hcl/json/parser/flatten.go b/vendor/github.com/hashicorp/hcl/json/parser/flatten.go index 6eb14a253..f652d6fe7 100644 --- a/vendor/github.com/hashicorp/hcl/json/parser/flatten.go +++ b/vendor/github.com/hashicorp/hcl/json/parser/flatten.go @@ -48,6 +48,12 @@ func flattenListType( item *ast.ObjectItem, items []*ast.ObjectItem, frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { + // If the list is empty, keep the original list + if len(ot.List) == 0 { + items = append(items, item) + return items, frontier + } + // All the elements of this object must also be objects! for _, subitem := range ot.List { if _, ok := subitem.(*ast.ObjectType); !ok { diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/vendor/github.com/hashicorp/hcl/json/parser/parser.go index 65d56c9b8..125a5f072 100644 --- a/vendor/github.com/hashicorp/hcl/json/parser/parser.go +++ b/vendor/github.com/hashicorp/hcl/json/parser/parser.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/hashicorp/hcl/hcl/ast" + hcltoken "github.com/hashicorp/hcl/hcl/token" "github.com/hashicorp/hcl/json/scanner" "github.com/hashicorp/hcl/json/token" ) @@ -85,6 +86,7 @@ func (p *Parser) objectList() (*ast.ObjectList, error) { break } } + return node, nil } @@ -103,6 +105,14 @@ func (p *Parser) objectItem() (*ast.ObjectItem, error) { switch p.tok.Type { case token.COLON: + pos := p.tok.Pos + o.Assign = hcltoken.Pos{ + Filename: pos.Filename, + Offset: pos.Offset, + Line: pos.Line, + Column: pos.Column, + } + o.Val, err = p.objectValue() if err != nil { return nil, err @@ -128,10 +138,16 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { Token: p.tok.HCLToken(), }) case token.COLON: + // If we have a zero keycount it means that we never got + // an object key, i.e. `{ :`. This is a syntax error. + if keyCount == 0 { + return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) + } + // Done return keys, nil case token.ILLEGAL: - fmt.Println("illegal") + return nil, errors.New("illegal") default: return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) } diff --git a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go index 477f71ff3..fe3f0f095 100644 --- a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go +++ b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go @@ -246,7 +246,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type { return token.NUMBER } -// scanMantissa scans the mantissa begining from the rune. It returns the next +// scanMantissa scans the mantissa beginning from the rune. It returns the next // non decimal rune. It's used to determine wheter it's a fraction or exponent. func (s *Scanner) scanMantissa(ch rune) rune { scanned := false @@ -296,7 +296,7 @@ func (s *Scanner) scanString() { return } - if ch == '"' && braces == 0 { + if ch == '"' { break } diff --git a/vendor/github.com/icrowley/fake/.go-makefile.json b/vendor/github.com/icrowley/fake/.go-makefile.json deleted file mode 100644 index 7f688de04..000000000 --- a/vendor/github.com/icrowley/fake/.go-makefile.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "build_id_generator": "0x$(shell echo $(version) | sha1sum | awk '{print $$1}')", - "host": "github.com", - "include": [], - "kind": "package", - "name": "fake", - "tool": [], - "user": "icrowley", - "version_generator": "$(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD)", - "version_variable": "cli.version" -} diff --git a/vendor/github.com/icrowley/fake/.travis.yml b/vendor/github.com/icrowley/fake/.travis.yml deleted file mode 100644 index b809e455f..000000000 --- a/vendor/github.com/icrowley/fake/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -sudo: false -language: go - -go: - - 1.6 - - 1.7 - - 1.8 - - master - - tip - -script: make test diff --git a/vendor/github.com/icrowley/fake/Makefile b/vendor/github.com/icrowley/fake/Makefile index ab4233b3a..2d3016908 100644 --- a/vendor/github.com/icrowley/fake/Makefile +++ b/vendor/github.com/icrowley/fake/Makefile @@ -1,34 +1,14 @@ .DEFAULT_GOAL = all -numcpus := $(shell cat /proc/cpuinfo | grep '^processor\s*:' | wc -l) -version := $(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD) - name := fake package := github.com/icrowley/$(name) .PHONY: all -all:: dependencies - -.PHONY: tools -tools:: - @if [ ! -e "$(GOPATH)"/bin/glide ]; then go get github.com/Masterminds/glide; fi - @if [ ! -e "$(GOPATH)"/bin/godef ]; then go get github.com/rogpeppe/godef; fi - @if [ ! -e "$(GOPATH)"/bin/gocode ]; then go get github.com/nsf/gocode; fi - @if [ ! -e "$(GOPATH)"/bin/gometalinter ]; then go get github.com/alecthomas/gometalinter && gometalinter --install; fi - @if [ ! -e "$(GOPATH)"/src/github.com/stretchr/testify/assert ]; then go get github.com/stretchr/testify/assert; fi - -.PHONY: dependencies -dependencies:: tools - glide install - -.PHONY: clean -clean:: tools - glide cache-clear +all: .PHONY: test -test:: dependencies - go test -v \ - $(shell glide novendor) +test: + go test -v ./... .PHONY: bench bench:: dependencies @@ -37,12 +17,8 @@ bench:: dependencies $(shell glide novendor) .PHONY: lint -lint:: dependencies - go vet $(shell glide novendor) - gometalinter \ - --deadline=5m \ - --concurrency=$(numcpus) \ - $(shell glide novendor) +lint: + golangci-lint --color=always --timeout=120s run ./... .PHONY: check -check:: lint test +check: lint test diff --git a/vendor/github.com/icrowley/fake/credit_cards.go b/vendor/github.com/icrowley/fake/credit_cards.go index 47d6ca726..8d6d277b2 100644 --- a/vendor/github.com/icrowley/fake/credit_cards.go +++ b/vendor/github.com/icrowley/fake/credit_cards.go @@ -1,9 +1,10 @@ package fake import ( - "strings" - + "fmt" + "sort" "strconv" + "strings" ) type creditCard struct { @@ -12,11 +13,27 @@ type creditCard struct { prefixes []int } -var creditCards = map[string]creditCard{ - "visa": {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}}, - "mastercard": {"MasterCard", 16, []int{51, 52, 53, 54, 55}}, - "amex": {"American Express", 15, []int{34, 37}}, - "discover": {"Discover", 16, []int{6011}}, +func (c creditCard) RandomPrefix() int { + return c.prefixes[r.Intn(len(c.prefixes))] +} + +var ( + creditCards = map[string]creditCard{ + "visa": {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}}, + "mastercard": {"MasterCard", 16, []int{51, 52, 53, 54, 55}}, + "amex": {"American Express", 15, []int{34, 37}}, + "discover": {"Discover", 16, []int{6011}}, + } + creditCardsKeys = make([]string, len(creditCards)) +) + +func init() { + n := 0 + for key := range creditCards { + creditCardsKeys[n] = key + n++ + } + sort.Strings(creditCardsKeys) } // CreditCardType returns one of the following credit values: @@ -36,34 +53,40 @@ func CreditCardNum(vendor string) string { if vendor != "" { vendor = strings.ToLower(vendor) } else { - var vendors []string - for v := range creditCards { - vendors = append(vendors, v) - } - vendor = vendors[r.Intn(len(vendors))] + vendor = creditCardsKeys[r.Intn(len(creditCardsKeys))] + } + card, ok := creditCards[vendor] + if !ok { + panic(fmt.Sprintf("unsupported vendor %q", vendor)) } - card := creditCards[vendor] - prefix := strconv.Itoa(card.prefixes[r.Intn(len(card.prefixes))]) + + prefix := strconv.Itoa(card.RandomPrefix()) num := []rune(prefix) - for i := 0; i < card.length-len(prefix); i++ { - num = append(num, genCCDigit(num)) + for i := 0; i < card.length-len(prefix)-1; i++ { + num = append(num, rune(strconv.Itoa(r.Intn(10))[0])) } + num = append(num, creditCardNumChecksum(num)) + return string(num) } -func genCCDigit(num []rune) rune { +func creditCardNumChecksum(num []rune) rune { + // See: https://en.wikipedia.org/wiki/Luhn_algorithm sum := 0 + pos := 0 for i := len(num) - 1; i >= 0; i-- { - n := int(num[i]) - if i%2 != 0 { - sum += n - } else { - if n*2 > 9 { - sum += n*2 - 9 - } else { - sum += n * 2 + n := int(num[i] - '0') + if pos%2 == 0 { + n *= 2 + if n > 9 { + n -= 9 } } + sum += n + pos++ } - return rune(((sum/10+1)*10 - sum) % 10) + + // https://en.wikipedia.org/wiki/Talk:Luhn_algorithm#Formula_error + checksum := 10 - (sum%10)%10 + return rune(strconv.Itoa(checksum)[0]) } diff --git a/vendor/github.com/icrowley/fake/data.go b/vendor/github.com/icrowley/fake/data.go index 7249a9d38..f100510a5 100644 --- a/vendor/github.com/icrowley/fake/data.go +++ b/vendor/github.com/icrowley/fake/data.go @@ -3,6 +3,7 @@ package fake import ( "bytes" "compress/gzip" + "encoding/base64" "io/ioutil" "net/http" "os" @@ -11,35 +12,41 @@ import ( "time" ) -type localFS struct{} +type _escLocalFS struct{} -var local localFS +var _escLocal _escLocalFS -type staticFS struct{} +type _escStaticFS struct{} -var static staticFS +var _escStatic _escStaticFS -type file struct { +type _escDirectory struct { + fs http.FileSystem + name string +} + +type _escFile struct { compressed string size int64 + modtime int64 local string isDir bool - data []byte once sync.Once + data []byte name string } -func (fs localFS) Open(name string) (http.File, error) { - f, present := data[name] +func (_escLocalFS) Open(name string) (http.File, error) { + f, present := _escData[path.Clean(name)] if !present { return nil, os.ErrNotExist } return os.Open(f.local) } -func (fs staticFS) Open(name string) (http.File, error) { - f, present := data[path.Clean(name)] +func (_escStaticFS) prepare(name string) (*_escFile, error) { + f, present := _escData[path.Clean(name)] if !present { return nil, os.ErrNotExist } @@ -50,7 +57,8 @@ func (fs staticFS) Open(name string) (http.File, error) { return } var gr *gzip.Reader - gr, err = gzip.NewReader(bytes.NewBufferString(f.compressed)) + b64 := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(f.compressed)) + gr, err = gzip.NewReader(b64) if err != nil { return } @@ -59,54 +67,65 @@ func (fs staticFS) Open(name string) (http.File, error) { if err != nil { return nil, err } + return f, nil +} + +func (fs _escStaticFS) Open(name string) (http.File, error) { + f, err := fs.prepare(name) + if err != nil { + return nil, err + } return f.File() } -func (f *file) File() (http.File, error) { - return &httpFile{ - Reader: bytes.NewReader(f.data), - file: f, - }, nil +func (dir _escDirectory) Open(name string) (http.File, error) { + return dir.fs.Open(dir.name + name) } -type httpFile struct { - *bytes.Reader - *file +func (f *_escFile) File() (http.File, error) { + type httpFile struct { + *bytes.Reader + *_escFile + } + return &httpFile{ + Reader: bytes.NewReader(f.data), + _escFile: f, + }, nil } -func (f *file) Close() error { +func (f *_escFile) Close() error { return nil } -func (f *file) Readdir(count int) ([]os.FileInfo, error) { +func (f *_escFile) Readdir(count int) ([]os.FileInfo, error) { return nil, nil } -func (f *file) Stat() (os.FileInfo, error) { +func (f *_escFile) Stat() (os.FileInfo, error) { return f, nil } -func (f *file) Name() string { +func (f *_escFile) Name() string { return f.name } -func (f *file) Size() int64 { +func (f *_escFile) Size() int64 { return f.size } -func (f *file) Mode() os.FileMode { +func (f *_escFile) Mode() os.FileMode { return 0 } -func (f *file) ModTime() time.Time { - return time.Time{} +func (f *_escFile) ModTime() time.Time { + return time.Unix(f.modtime, 0) } -func (f *file) IsDir() bool { +func (f *_escFile) IsDir() bool { return f.isDir } -func (f *file) Sys() interface{} { +func (f *_escFile) Sys() interface{} { return f } @@ -114,119 +133,414 @@ func (f *file) Sys() interface{} { // the filesystem's contents are instead used. func FS(useLocal bool) http.FileSystem { if useLocal { - return local + return _escLocal } - return static + return _escStatic +} + +// Dir returns a http.Filesystem for the embedded assets on a given prefix dir. +// If useLocal is true, the filesystem's contents are instead used. +func Dir(useLocal bool, name string) http.FileSystem { + if useLocal { + return _escDirectory{fs: _escLocal, name: name} + } + return _escDirectory{fs: _escStatic, name: name} +} + +// FSByte returns the named file from the embedded assets. If useLocal is +// true, the filesystem's contents are instead used. +func FSByte(useLocal bool, name string) ([]byte, error) { + if useLocal { + f, err := _escLocal.Open(name) + if err != nil { + return nil, err + } + return ioutil.ReadAll(f) + } + f, err := _escStatic.prepare(name) + if err != nil { + return nil, err + } + return f.data, nil +} + +// FSMustByte is the same as FSByte, but panics if name is not present. +func FSMustByte(useLocal bool, name string) []byte { + b, err := FSByte(useLocal, name) + if err != nil { + panic(err) + } + return b +} + +// FSString is the string version of FSByte. +func FSString(useLocal bool, name string) (string, error) { + b, err := FSByte(useLocal, name) + return string(b), err +} + +// FSMustString is the string version of FSMustByte. +func FSMustString(useLocal bool, name string) string { + return string(FSMustByte(useLocal, name)) } -var data = map[string]*file{ +var _escData = map[string]*_escFile{ "/data/en/adjectives": { - local: "data/en/adjectives", - size: 119, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x14\x8b\xc1\n\xc20\x10D\xef\xf3W\x85H\xf5d\xb0\xe2=\xa6cYH\xbb\xb2n\xf0\xf7\xbb\xb9\xcc\xf0\x98y\x93\x18f6L\xdd\x15Y\xff4<\xcb\x16\xb8ʻ\x11ׄ9/1\x98\x97\xc1I~\x15\x97\xc6\xea&\x15\x99\xf6Q\xdb\xcbQ\x89EV\xe2\x15\xa1\xb8\x1d\xdf\xee\xb8w\x1f\x95\xc4\xe2\x8d\aw\xf5\xe1o\xe2\xa5\xe1\f\x00\x00\xff\xff\xd8\x18m\xadw\x00\x00\x00", + local: "data/en/adjectives", + size: 119, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/xSLwQrCMBBE7/NXhUj1ZLDiPaZjWUi7sm7w97u5zPCYeZMYZjZM3RVZ/zQ8yxa4yrsR +14Q5LzGYl8FJfhWXxuomFZn2UdvLUYlFVuIVobgd3+64dx+VxOKNB3f14W/ipeEMAAD//9gYba13AAAA +`, }, "/data/en/characters": { - local: "data/en/characters", - size: 72, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x04\xc0\xc3\x01\xc4\x00\x00\x00\xb0\u007f\xa69c\x9c\xdav\xa7o\x02\xa1H,\x91\xca\xe4\n\xa5J\xad\xd1\xea\xf4\x06\xa3\xc9l\xb1\xda\xec\x0e\xa7\x9b\xbb\x87\xa7\x97\xb7\x8f\xaf\x9f\xbf+\x00\x00\xff\xffq\xa7L\x96H\x00\x00\x00", + local: "data/en/characters", + size: 72, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wTAwwHEAAAAsH+mOWOc2nanbwKhSCyRyuQKpUqt0er0BqPJbLHa7A6nm7uHp5e3j6+f +vysAAP//cadMlkgAAAA= +`, }, "/data/en/cities": { - local: "data/en/cities", - size: 4837, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\\X[\x9a\xe3(\xd2}\xd7*\xb4\x81\xfe\xf7\x90wgwf\xa5\u007f\u06dd\xf9\xd5cX\xc2\x16m\x04\x1a@v\xb9v5k\x98\x8d\xcd9\x01rWϋ\xe3\x04B\b\xe2r\"\xf0]o\x9c\xf8\x1c\x9a\xbbc\x98\xa3\xb4+\xeb\\j\ue70c\xa6\x17Ƚ\xf8+\xc4 \xe3>R\xb7)\xb4\x9f\xd6\xfc\x85\x17\\\xc6\v\x98;J\x1fb\xfb`3&\x8e&\xdaN|\xfb\x80ׂo\xee\xbc\fƎ\x90\xbd\x89I\a\x8e\xc6%<\x1e'\xe0lC74w\xd3\xe4L\xfb)\xce\x19\xac\x10;魨\xcc\x141\\C\xfb\x12\x05+@\xcb&\xe9ó\xc5ZY\x12&\x9b\x88\xbd\xe4\xc1\xc4\xcc\xf5\xf3E\xb2\x89\xcdݼ\x9f#Գ8\x8e\x9e\x8d\x17\xd7\xdc\xfd\x9c\x934\xf7r\xc2^\x0eָ\x1e\xd8\xf5\x17\xeb۵\xc4\x13\x14\xef\xad?BƔå\xb972\x8f\xc1g\x00\xe7\xf4\xa7}\x91\xd8\x1b\x9fT9\xb8p\xc1\x97\x00\x97Ig\x83\xcd\x18 o;\xec\xf2\xdeē\xe1\x99\xee\xcd\xd9Dw\xad\xb6\xbd\xb7\xc7\x16K\xc7\xf6\r\x1b\xa1v\xe4X\x1a\xc2\xd4ܻ\xd9\xd4awő\x9a\xfb(=\x0er%\xb8\xe8R\xd1\b\u007f|\xbe\x84\x80\xfdG\x9b\xe0!L\x9c\xb1#\x1a\x00\xc0K=\xcf\x1c\xf1L\xa5ù\xe0\xd1\xe6A\x9c\xec%\xc1k@\xe6\x87\xed\x02\x81=\x84\xe8\xad\x14\x17R\x1f\r\xecD0I\x8e\xb6@\x98\xe4H4J\xc41\xf8\x1e=\\v\xfb \x93\xcd\xc1\xf1qt\xd8PO0\x1a\xf7\xdb\xfe\xfa\x1b\x8e\xf1\xdb\xd6\xe8\xa3\xc9z\xf8F\xd7\xd3`x\x10<죸\xfae\x18/\xf17b1\x80A\xb77X_\u007f\xab\xfd\x1e\x86p\xe9\x06@\xac3\xccN\x10\x8e\t\x91\x82%\xe2\x9cڕ\xb1\xc7!c\x96\x93h\xd41@WZ\xe6\xc1\xc1\xe8N\xb7\xeb\x02\x1c\xd2\xc3\x02\n-f\a\xe9\x06\xa3K\x06Qc\x01\xb8\x83\xfc\xa0\x18U\xd1%\x82c\x04q\xb7m8\xb4\x0faD\xbcwX%\x8cSy\xee\xbb\x10q\xfa\x10!\x85\x03QC\n2x\xa9\xa2\x0f\x04ٴ\xef\f^\x8eb\xff\xed\xbb\xda\x8d\xb3\x8d͓\xa4\xac\x13[0Gh\x9e\xe0u\xf9\v\xcb\x10\xe0\x90\xb1\f\x15\xef\x13\xbe\xc3y\x86`k\x8e\xb3\xef9v\x02\x11\xc0u\xcd\x13\xcc~-Gz\xf2\x9d\xf5\x16L\xd0<\x81\f\x98\xec\x90خ\xe5\v\x19F|\x9a\xa39A\xfc0\xe4\x85g\xb1\x91nU\xa9\x14\xf0\xccH\x8d\xa9\xac\xf6l\xa2\u05f8x\x86:\x86H\x10\xcd^\xe6\xe3\xd0<\a\x97\xc2\b\xe13L\v\t;!-\x8f\xc7\x02\u007f\x0f\x1e\xd1K8\xebӔ\x17/=\x87\x19\xaf\x80e*\xc5=\a\xa42\xb6R\xe3\x132\xc1\xf2\xcf3\x1e*\x87\xbd\x88\xcbMa\x9azޢH\xf3b\x1d\xe8\xb0yq\xa6\xecR\x01\x02\xady\t\xced\n\xff\x13\xe3\xa9Q\xbelw0\xa6 <\xa1\xa5\xb4|\xfd%\x1a\xe3\xcb\xd1_\xa2\xed\xcb\x10\xf3\x81\xa4\x046~\x99\x05k#\xb0\x80\x12b\xcb4+q\ax\x03\xc9~/Wh\xfe\xc0\x18_\xc9E\xac\x05\xd5/\x9c\x88\x81< \xde\xf9\xc2\xf5\"\x9cb@\xaf\t\xfcu\x04\x1cM\xc6o\xecf\xee\x0f`\fI\xea'W&M\xca\v+\xdb\xf3\xd0%\xcfWHd\xc4$\x96\xa1\xbaG\xea\xd0\v\xab\xe0\xc8E\xb0\x1fP.^[\xe1\x01\xf9d\x05;#d3wZ\x16\xfe{@\x19q5#\xff\x9a\xd7Q\xbf\xe6n\xa0\xce~E\xd4\xe0<_\x86_\xa7\x12n\x99\x0e\r\xc6\x00\x0f\xbf\xfa\xa33J\xbd\xaf\xf0w\xf3\xcaBD\x81\"\xa2\x1eyMp\x04\xbe\xf1\xbbt'n\xe9\x0f\x1c\x14<\xf0\avQ\x82\x81\xa8\x98\xe4\r\x84+\xff\xf97\xac\xdd>#Q@\xb4\xfd\xd1pt%,\xb5\v\xb81\xda[\xe5\bJ\x8b\xba\xa0\b\xf94\x16\x00\xde\xcf\xfa\xfa\xff\xcfXL\xc7>\r\xbd\xf1&\a\xb9\x9a\xac\x0f\x91H\x8bѫRl]\x95o\xf6\x88:\xb2h_8&\x1f\x9dL\xfb\xe4\x12X&\x9a\xa2!\xc8Mʊ'Ļ\x02\xb5ɛ\xf8N\xd49o0w\x9af\x825\x94\x01\xed\xc1`2\v\x10f\xe0\xcd%É\x118\x86`Rj|\xb7)YX\xbd4n\uf847\xfb(=\xbc\x80\xb4#\xd3\xc2\xe5FA\xe7@\x8d\x8a\f\x98\x17\x9dF(\xcaް\xea+\x8c\xfcH\x05u7p\xe3T\x00\x18\x91+\xf2\xc5ۆB\xd1/]\xc27cz\xba\xe8\x9b93u\xea\u0605\x1f\x87`\xb2ALJ\xcej\xf9o\xac\xc5\xfc\xbd\x88Ôp\x863\x1bĖ\x06#\xa4\x1a\x98\x12\x1b\xfd\xe8\x8c\xf8d\xd1i~\xfc%\xb6\xf9\xc0\x96\"X\xe0\x03l\x8a\xd4,\x02U\xffL\xac\xa1\xf7Q\xfc\xf3A;\xd2u\x1f?<\x89o-\x9d=خFyդa\xb2\xb6\xa5\xc2\x16\xbc\x94X*\xba\x9f\xbfˣVTf0|\xd5>\xc1D\xe8|1\x88\xbc\xb7\xc9(\x18i2\"g\x91pktuZ#\x00B\xbb\t{\xa7\xf3\x91\xf6\xdaj\xad\x8d\xd6\xea5\x8c\xeaf0\xc6\x1aQ\xd8n\x98]Ħ\xd7J\xb4F\x8es\x136\x8d\xa1Zoms.t\xb5v\xc2^\x04\xe1\xa2(\x96\x03\xaf\xd1T%\xc4vq\xee\xa2\xf1\x83\xee\x8a\rf\xac\xc0\x16\xa4\xbd\x8b\xba\xb70\x06\x15l1@X(\n\xaa\xdcV\x03f\x1bY\xe5\x12?\xebpA\xbcl@.C\x80\xf9c\x0f'\xdeԹc{r\xbc\r\x90\x1bᬪ\xfdj\xc6el\x8b\x1d\n;\xa0#\xbc\x8b \xdb\x1847n>\x1c\x88z\xb6k\x90\xf4k\"@/\xb1\x18\x03\x1a\x13\xb3\xc4\xdcF\xe3\x10Ғ\x15 \xba\x81m\x12\x00h\xbcS\x82\xdc\xd8\x00w\xc3.\x04\xa5K\xdd\xd8\t\xc6Q\xc3ko\xaeH#n\x13\xba\x13\xfb\xa5M\x18<[0ͫ\r\xab\x1d\xf8\xac0\xd4?\xb4[PlB\x82\x1d\xd1s\x13\x14;\x02\xa5f+\x1d\x82\xc4\xf0n\xb7eO+\x1c\xf2\xa0\xb8\xc4\x1b\x8bb\xdcP\x18\xafl U\x8dsE\xec\xe3C\x99\x8f\xb6y\xd4\xd2B\xe5њc\xa8h\xac\v\xb2g\x12\xf6g\xaa G:\x8b\x0eL\xb5\x17\x140t\x1a\x8aQ\x11m\xd9\vp\x90\u007f\xa1JU\x9c\xcaڿ\xcf܂\xccY\ru\x1b\xe1\xdd\x02\xa5W\xea\xceސ\xa1}\xacx\xb6\xa9\xfd\xd8\xdb4\x15\x1d.\xed\uab95^\x97\xd1l\nZ\xcb\xde\x15\xb4AM\xac\xfb\xda0|\x88\xaa_\xb7L\xf2ؔ \xc1\xfd\xb5\"t\xbf{$]\xd5x\xbb\xf8\x15\xdb|\xd3\xe2\xfc\xb3\xc2gsK\xf0[\xc8\xd9e\x1e\xf8\x93\x94P\x94\xb5\xe0\x1eS1|W\xa0\xa1Y\xa2\xe8\xb5k+\xb8w86\xc6\xdb. #\x97\xcc\xc0\xc5j\xe9^\x005\x8e\xb6hW\xc1\xeeS\xc0\xf1\f\x9b\x030\xec\x81%\xb90m\xb9\xb0m-[C^@\"\x95#\xd9U3xkG{[\x1c)xk\x17\xa0\x98\x1eA\x06y\x86\x85 }\xe0\xe2\x10\xb4\x04S\xbd\xbd5\xedEE\xd9\\\xa0\xb6\r;\x19\xc22p\xa3\xab\xa2\xfeO\xe8\xe4\xffC\xd7\xe3\xf4q.t\xb2\xcdH\x8f\x02f4f\xd5U\xf0\xff\xec\x17\xec\xfd\xf5L\x0e\xdd\xc2T\xf5\xbe\xb3\x9d\xb3v\xe1hyO\xcd\x0efhvf\xc0i\x10R\x8ap\x80\x1d\xa2\xbb\xa3\xf5\x01\xf87\x84.\xb6\x1b\x02\x17\xe9\xcb\xd5h\x87\xf2ξq\x87҅-\x9af\x87\xae\x1a\x93\xe0ZK\x93\xec\xe2ܝ\xe0\xad\xdd\xcc;'\x85\xd1k\xe6\x0e\xf7n\xec\x1a\x92}t\xb3\xbb \x8d\xae\xb8\x0e\x1a\xed\xdaR\xf3\xe7\xc9\xca\xd0\xfc\xe9Y\x99\xf5\xb3\u007fNZM>\xa5\x93\xb2\u007fu\x04*\xf6'ޜaf6t\xd8ȧ\xedr\xa8\x94\xf9ɋp!\v0\fbD\x9a\xc24_\xe2\xfc\x9c\xab\xa8&\xf8\x12\x9a\xf7\x8b\xff\x90h\x0f\x0f\x84\xe2P\x16\xfa\x02\x9f\xe1\aw\xb4z\xfbT\xfc\v\x89P\xe7\xb9Z\xfd\xe4\xd1\xe8\xc0h\xbd\xf6{\x8aC\xa9\x86_\x83\x91\\\x11\xca\a\xab\xd3\x17^\xc152\x15\x90\x8b\f\x17J\xd0l\xe0\x04\xb6\x13\xd0\xc1\xafj\xbc\x02\xb8\x06\xbbP\x06\xf6\xf7\x80\f\xac-\xdfw־\xb2\xef\xefz\xbd\xfb\x8eki1\xe2w\x14\x04;q\xa4\xeb\x96\n\xf2\xdf\x00\x00\x00\xff\xffPpU\a\xe5\x12\x00\x00", + local: "data/en/cities", + size: 4837, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1xYW5rjKNJ91yq0gf73kHdnd2alf9ud+dVjWMIWbQQaQHa5djVrmI3NOQFyV8+L4wRC +COJyIvBdb5z4HJq7Y5ijtCvrXGrunIymF8i9+CvEIOM+UrcptJ/W/IUXXMYLmDtKH2L7YDMmjibaTnz7 +gNeCb+68DMaOkL2JSQeOxiU8HifgbEM3NHfT5Ez7Kc4ZrBA76a2ozBQxXEP7EgUrQMsm6cOzxVpZEiab +iL3kwcTM9fNFsonN3byfI9SzOI6ejRfX3P2ckzT3csJeDta4Htj1F+vbtcQTFO+tP0LGlMOluTcyj8Fn +AOf0p32R2BufVDm4cMGXAJdJZ4PNGCBvO+zy3sST4ZnuzdlEd622vbfHFkvH9g0boXbkWBrC1Ny72dRh +d8WRmvsoPQ5yJbjoUtEIf3y+hID9R5vgIUycsSMaAMBLPc8c8Uylw7ng0eZBnOwlwWtA5oftAoE9hOit +FBdSHw3sRDBJjrZAmORINErEMfgePVx2+yCTzcHxcXTYUE8wGvfb/vobjvHb1uijyXr4RtfTYHgQPOyj +uPplGC/xN2IxgEG3N1hff6v9HoZw6QZArDPMThCOCZGCJeKc2pWxxyFjlpNo1DFAV1rmwcHoTrfrAhzS +wwIKLWYH6QajSwZRYwG4g/ygGFXRJYJjBHG3bTi0D2FEvHdYJYxTee67EHH6ECGFA1FDCjJ4qaIPBNm0 +7wxejmL/7bvaPGTJFgLxDQ326ODqap65l4ECcRaXoQlhrwa6TpicmkdBnOmzR2EcBJic8Ax7GQAe9tE4 +fDqq3Jhr+yEnHRSs82gSVmxXIbfbKWLreGIFduzbe75i/bwXiB847WOAp/A8JMSbC0QXjxh9nAWng9jD +khA+jbONzZOkrBNbMEdonuB1+QvLEOCQsQwV7xO+w3mGYGuOs+85dgIRwHXNE8x+LUd68p31FkzQPIEM +mOyQ2K7lCxlGfJqjOUH8MOSFZ7GRblWpFPDMSI2prPZsote4eIY6hkgQzV7m49A8B5fCCOEzTAsJOyEt +j8cCfw8e0Us469OUFy89hxmvgGUqxT0HpDK2UuMTMsHyzzMeKoe9iMtNYZp63qJI82Id6LB5cabsUgEC +rXkJzmQK/xPjqVG+bHcwpiA8oaW0fP0lGuPL0V+i7csQ84GkBDZ+mQVrI7CAEmLLNCtxB3gDyX4vV2j+ +wBhfyUWsBdUvnIiBPCDe+cL1IpxiQK8J/HUEHE3Gb+xm7g9gDEnqJ1cmTcoLK9vz0CXPV0hkxCSWobpH +6tALq+DIRbAfUC5eW+EB+WQFOyNkM3daFv57QBlxNSP/mtdRv+ZuoM5+RdTgPF+GX6cSbpkODcYAD7/6 +ozNKva/wd/PKQkSBIqIeeU1wBL7xu3QnbukPHBQ88Ad2UYKBqJjkDYQr//k3rN0+I1FAtP3RcHQlLLUL +uDHaW+UISou6oAj5NBYA3s/6+v/PWEzHPg298SYHuZqsD5FIi9GrUmxdlW/2iDqyaF84Jh+dTPvkElgm +mqIhyE3KiifEuwK1yZv4TtQ5bzB3mmaCPESUtje5FAu9MeprXBPrqha86TxlnxBjb/ZsSEsK4limnGk5 +2vYt9BY/o7ScL4Q2q5hCB+GPyxEDnuAEICg2NFpVivIPtNiAOtsTUzDagTrrRcr8q2gVeLt6PW2l73cU +jP0MMY4hD1oQEzQ/SAZR1K1Az6bjZPRHYSrAq2CO/SS4VhJ6R/ro+t0zCxYy4J1pjiNCgj41lAHtwWAy +CxBm4M0lw4kROIZgUmp8tylZWL00bu+hh/soPbyAtCPTwuVGQedAjYoMmBedRijK3rDqK4z8SAV1N3Dj +VAAYkSvyxduGQjxKSWviGJRI3kmL7XYQVu/3G0dac2neZ1QBEto3mfiDPtEvXcI3Y3q66Js5M3Xq2IUf +h2CyQUxKzmr5b6zF/L2Iw5RwhjMbxJYGI6QamBIb/eiM+GTRaX78Jbb5wJYiWOADbIrULAJV/0ysofdR +/PNBO9J1Hz88iW8tnT3YrkZ51aRhsralwha8lFgqup+/y6NWVGYwfNU+wUTofDGIvLfJKBhpMiJnkXBr +dHVaIwBCuwl7p/OR9tpqrY3W6jWM6mYwxhpR2G6YXcSm10q0Ro5zEzaNoVpvbXMudLV2wl4E4aIolgOv +0VQlxHZx7qLxg+6KDWaswBakvYu6tzAGFWwxQFgoCqrcVgNmG1nlEj/rcEG8bEAuQ4D5Yw8n3tS5Y3ty +vA2QG+Gsqv1qxmVsix0KO6AjvIsg2xg0N24+HIh6tmuQ9GsiQC+xGAMaE7PE3EbjENKSFSC6gW0SAGi8 +U4Lc2AB3wy4EpUvd2AnGUcNrb65II24TuhP7pU0YPFswzasNqx34rDDUP7RbUGxCgh3RcxMUOwKlZisd +gsTwbrdlTysc8qC4xBuLYtxQGK9sIFWNc0Xs40OZj7Z51NJC5dGaY6horAuyZxL2Z6ogRzqLDky1FxQw +dBqKURFt2QtwkH+hSlWcytq/z9yCzFkNdRvh3QKlV+rO3pChfax4tqn92Ns0FR0u7equlV6X0WwKWsve +FbRBTaz72jB8iKpft0zy2JQgwf21InS/eyRd1Xi7+BXbfNPi/LPCZ3NL8FvI2WUe+JOUUJS14B5TMXxX +oKFZoui1ayu4dzg2xtsuICOXzMDFauleADWOtmhXwe5TwPEMmwMw7IEluTBtubBtLVtDXkAilSPZVTN4 +a0d7WxwpeGsXoJgeQQZ5hoUgfeDiELQEU729Ne1FRdlcoLYNOxnCMnCjq6L+T+jk/0PX4/RxLnSyzUiP +AmY0ZtVV8P/sF+z99UwO3cJU9b6znbN24Wh5T80OZmh2ZsBpEFKKcIAdoruj9QH4N4QuthsCF+nL1WiH +8s6+cYfShS2aZoeuGpPgWkuT7OLcneCt3cw7J4XRa+YO927sGpJ9dLO7II2uuA4a7dpS8+fJytD86VmZ +9bN/TlpNPqWTsn91BCr2J96cYWY2dNjIp+1yqJT5yYtwIQswDGJEmsI0X+L8nKuoJvgSmveL/5BoDw+E +4lAW+gKf4Qd3tHr7VPwLiVDnuVr95NHowGi99nuKQ6mGX4ORXBHKB6vTF17BNTIVkIsMF0rQbOAEthPQ +wa9qvAK4BrtQBvb3gAysLd931r6y7+96vfuOa2kx4ncUBDtxpOuWCvLfAAAA//9QcFUH5RIAAA== +`, }, "/data/en/colors": { - local: "data/en/colors", - size: 128, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\f\xcaA\xaa\xc2P\f\x05\xd0\xf9\xdd\xd5\xff\x82ED,R\x04\x87\xa1\xefRC\xd3ĦF\xb7oGgrnl\xf8\xb7\"\xba$\x1d\x0f\x9a\xc5\x17\xd7\x14\x9f\x88\xbe\xf2e\xc4]\xc3\xf8\xc6ɛN\x81\x81b\xe8\xd5g\x1ck\x1bUЅ5zF\xc3Eꃿ\xb5d\x91T'\x86ʵB7\u243al\xe1\xfb\xc8\xd8\xe9k$\xceO\x99\xf5\x17\x00\x00\xff\xff\xfe\x16\b\xa6\x80\x00\x00\x00", + local: "data/en/colors", + size: 128, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wzKQarCUAwF0Pnd1f+CRUQsUgSHoe9SQ9PEpka3b0dncm5s+LciuiQdD5rFF9cUn4i+ +8mXEXcP4xsmbToGBYujVZxxrG1XQhTV6RsNF6oO/tWSRVCeGyrVCN+KQumzh+8jY6Wskzk+Z9RcAAP// +/hYIpoAAAAA= +`, }, "/data/en/companies": { - local: "data/en/companies", - size: 3157, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffTV\xdbR\xe3<\x13\xbc\xd7[q\b\xd4G\b\xb0@\xb1\u007fr'\xc7J\xa2\x8dm\xb9|\b\xb1\x9f\xfe\xef\xee\x91\xd9ڋ-6\xb6<\x9a\xe9\xe9\xee\x99\xf5w\xac\xe2pr+?%\xf7\x95R\xfeQ\xa4\xab{\x8cG\xfd݄p\t\xc9mS]\x8cn\x15\xbb\xe0^\xa7Ԕ\xa1s\xf7S\xe3\xe7yr\xf7\xa1\x8e|\xf9;\x9e\xe3<\xbb\xff\x9a&\xed\xdc[\xbc\xa6f\xba\xba\x8fƷ\x83?\xf6n\xeb\xeb\xe8\xdd\xcd\xc5\u05f5\xbb\v\xcd\x10\xf5\xb3\xf0\x83w\x0f!\x94u\xbc\xba\a_\xe2\xa6\xcfS\x1a\x8f\xa7\xa1\xe8by\f\xcb/\xbe\xbe9\xc6\xcb\xe8\x9e<\xc3ގEQ\x05>\xbd\x8f\x17\xdf\x06\xf7\x1c\x18\x13\xcf\xe7\xb9\b\xbe\xe1\xe1\xba\xf08}\xed[\xfc\xfc8O\xf8\xf6\xa1\x8am?\xa4\xaev\xb7]\xfa\xeeCQ\xf9\u00adpM;V}pw\xe9\x18Y\xf2\xb3\xff\x93\xdc{\xf0Ւ\xc3wD\xd2\xc0\xaa\x19\x97|,\n\xe3\xa5\x16u\xdc\xfb\xa2?\xa5\xa1w/\xad\a\x82\xa8\xf2\x12\x82\xbb\xad\xd2\xf1\u007f\x1f\b\ap\x91\x80\xd2)\x8a\xd0\xf5\xed)t?\xa5)\x89\x8fslP\xcc\x1b\x82\xa0\t\xfd \x14\xff\xf8Z/\b6@G\x95\x19\xe2[\xcf\xea\xf5\xe1\xfbi\x9ac\"\xba\x05n$\x18MJe\x15\xf2\x99>\f\xee\x13)\xee\xbf=nܦ2%\xf4\xebҦ\xd8\f\xaa\\A\xf0\xa4?\xf1\xc0g7\xf2\x04\x81\xe0_\x16\xd0\xfa\x92\xccP\x12\x9b\xa9\x19\x02\xda4\xcc\xee\xd1\x17\xc3\xd8\x04<*\x00\xb9[\xfb\x89,Y\xfbyt_\x91\xa7T\n+\x00\x81p~\x97\x12\x0f\xe8i1\x1eY\x0f\xf0 \xc8\xfb\xb1@\xfb\xe2%\x1cb\u007fB\x04\xa4\xf1D\xc4n\xbbHt\xd8L\xbe\x15\xb0@1\x97\x87\x94\xe3a\"\xf0\xbcc\xed\xed\x8azN\r?\xaf\x98\xbc\xb5\x18w}\x9c\xc6á\ne\x870L\x87\xa4}\xc0\xffs{QJߦ\xc1\xbd\xe3\xfbZ/\xf6'?\xa8x0\x97a\xf3\x9d\xeb\x05\xdb;p\xb9$\xe8e\xa8\x04\xaaal\xa4\xb0\x1e\x0fS\xcbD\x86.\x928\xe4\xf5\u007f\xecӗ\xee\x00+U\x17\x9a\x9b\xf9\xb8\x89\xd0\x01%\xb7\xafF\xb1\x81\xea\xc8\x19\xf4@\x14\xe5Qn\x17P(\f\xdfT\xe1\x06TM\xee\xd7(\x9a\xaf\"\xc9\xffJ\x86\x8du\vαc\xe0S曮\xf8\x87\xb9\x9b\xe9;u\xe7\x9e0\x12\xa1\xe7\u061c3\x1a@\xf4\x00=\x12'Q\n\xb9 \xecV\xdd[I\xef?=$\u007f\x94\xaf\x1c\xc1\xe4\xc5\xe7\xd4>\x93\xdb1\xdfO\u007f\x14Q\xd8\x1d\x8ak\x15\t\x1a\x10h\xfc\x10SCq\rC\xe8,\x9dߩ+\xdbPF\xf3\x84|\x02\x19\xed\xdcf$ʾ\xf2MX>Y\xd4ٙ\x871\xe1Zw\xb7?G$\xa5W2\x8d\xcc\x0e$\x85\x8f\xcd\x05\x90\x04\xa1m\xa2\x85\x86rc\xc9\xc7\x03\xd1\xddҗd\x01\xd4\a07\x87\xd8\xfa\xb3\x84\x81\xa2\xa8\v\x02\xf0m\xc7\xf7\xa13\xbd\xe4\xa4e\x01ɽ\x92\x89π\r\xe0\xe0\xb6\xecE\xb1\xd5% \xdc5\x1b\r5\xb4\x19\xf1K\xd4\a\x9b\x8c\xac/$\xa0\xb8\xa5$n\x00\x11ɕ\xb47\xa2\xa1\x91u\xceHS\x8a\xa3\x85\xbc@[\xcc\xfd䙨\x8fL\xfb\xa4\x96\xde\xe3\xe1`6aSN\f\x90\xc1\x10!\xf3'\xfa+\x1e\xb1\x19\xc0\x9b\xa2\xea\xc6\xd6:*L\x91&\xf4\xf9\xa2\x1bОC\x85s\xe4\x1bc\xab3\x1c\x82\xcaT\x84\x90\xd0\xe0Z\xe6S,\x8f3B\xde\xe39\xfd\xd8\xfa\xad \\\xa9\x06\x98\x8b>\xb9\xcf\xc5\xdc\xe18zn\x15\xbfU\xdc0\x10Ĩ\x1bI\x12f)\xd0wr\x05bn\x02:k\x1ba\xc5y\xb5\x90\xe1C\x97\xa4\xfb&\xda\b\xe2l\xd9L\x80)\x8f}\x99<\x00\x94/\xf0\x02b\xc7]b\b恙j\x1c\xcbc\xf6&\xac\n7Q\x06\xbb\xf3\x8c\xa7s\xb9\xa9\xb6o1\x88\x99\x80\xfd\x1e\xfe\x8a=\x17;ϸ\xdcB\x9bv:3\xcd?\x1a}\xd2\u007f6\x93\x0fˉ\x9a\x97\x1c\x81\x89\xc8\xfa\xb3\x12,\x0e\xf6\xcf\xceD룾1q\xd8\xd2e ?i\xb9\\\xc6&\xf3\x16WLUֲmb\xda0h3ASƍ\x82mu\x0f/\xe6B\xa9\x8c\xb4\r\xbd\x12\xe9ܸl\x85\\@\xcaŔ\xc8\xf0\xac\xe5\xec\xfa\x0fKBˈ\"\x1f?\xad0\xab\xe3g\x9f\x19\x96\xb5';\tF\xe5\x97\f\xe4-\x95\x92\x8e/d\x19Xl\xafZ\xac\xa2Qd`\xd6<\aAp\xb8\xa8w\xf4\x9f\xec\xc1\xcbVɛ\x1f\xf5\xe4\xcbx\xb5\x12FZo4\xb3\x93\r2\nD\xeb\x13ljm\x9c^\xb4\aČ\u007f\xa3\xdd^\x9a\x12\x99\xd8Mn5\xb6\xf1\xd8\xfc\x04r\xe6\xa4+nD\xff\x0f\x00\x00\xff\xff\x16.\x1a\x04\xa5\xad\xb7\x99$\xb1\x99\x89\x14ꈓ\xcaJ\x9b\xa8\xc0młB\x95\x1a\xc8B\xcb\x10;\xe5z\xce\xf7\x87Ta\x1djv\x83xW<\x0e\xd3\xf3i\x88\x81\xac\x1ePN\xe9\x99CE\xf2\x13&.\xa8\xa3\x9e\x06\xa5\x81D\xf7\xae\xb5\xd4\xf0\xd0\x19}\x88\x1a\x0f\x1d[\n)\xd3VR\xafT\xce\f\xe2\xf4\x03\x0e\xbd\x9a\xb3蒺\xbc\xf0V\x8exb\xe1\a\x98\x94\r~\xe0p\xe6\xd6\x1f\xd5ԅ\x8fÉ2\x93\x8e\x1c/&.\x02\x9dłH\x94\xa1+\xde$\xb4r\xb1\u007f\xb8\x8a\x1f]#\x88ڷ\x9a\xb1\xee8@\xec\xc3\bur,ō\xda8\x90%\x18\x98lK\xea\xe8\"\x85=\x9e-\xeeh\xf0\xbaI\xb8\xc1,\xa9\xafE17\xbe\x17\xa7W]\x98\x0f\x0e\xdf\xd6\t\x98\b\xe6\xb6\x1d\x0f\xd1\xdcZ`\xd8\x1e'ɯDȇ L\xf7I\x1c\x93\xb9E\x82\x82\xd2!z\xc5\xe7m\xec\xc4\x1f\xc0ܑݫ\xdd\x17\xf3\x8bO\x1b܂\xf0\r\x9f\xa1\v\x9e\xaf~\xdd\xc9O\xc1\xe2r\xcc\xee\x02\xb9\x9aA\xd8\xc1~<\xa2@\x9aw[oGǃ\\\x05%\\\xe98\xbc\x03Ex0\xf7T!\xdd\xf7\x94#\u007f\xcf\x1e0S\x1a\x90\xeb\xd1\xdcwz\u07fdT\xc84*\xcf\xdc\af<\xa7dz\x1f\\\xc6\xc9=B\xc0֧\x03+\xdb\xeb\x12\xb9\a\xf2\xc0\xe1Łq\xd7\x14\x81\x89\xfc\xb5\x10\x003a7\xea\v\x0f\x048\x9b\a\xa6\xd0\xe4\xfa\xd8\xd47ޑ\xbdF\xc3\xd1\x01\xaa'\x0ej\xef\x93\x0f\rv+:Ӿ˽k\xc5n$\xb3\x92 \x15\x00dV\x1e\x99\xfcR<\xfb\x10\xbb\xcb&\x87ج\xd2\t\x0e\x99\xd5\x18\xda\xf1\x9c?]\x13\U0003c9a8}`\xcd\xe8}\x88\xf9\x9a\a\x1f;o\xd6R\xe5\x1e\b:\xea\n$F\xb4\xab\xc8h%k\x89]ʝr\x9d~3\x8a4\x85\xd6l\xa8F\xe8\xb0r\x93A\xb4A\x06Z\x1aj$\b\xa0\xa1\x93d2\x0eYe\x1b9\"\xcd`\xb28\xaa,\f\x1dY{\r.\x04h\x9a\xf2+1\xd8\x04d\xd0t\xab\xb2\x92T?\xfa\x18\xa1\xe4\xdfR{\xb3\x91:\xcc1\xdex\xdb\xf8\xa3RG\xaa\xd1\xea\xb4Y\xee\xe0\x02\xb7!\xcb\xe2\x00\xbcQ\x04\x1b|\x9d\x8f\x9d\x15n\xf9=\xa4\x1f\x95f\x9e\xa9\x17\x05\xe03\x1eM\xe6\x99\x0fd\xb1*Z'\x13?\xf0\x85v~kY\x85\xa7bIv\x8e\x82\xee\xbe3\xe5L?#\x9b\x810\x1e\xc0\xe1\x95g\xc1\x94\x99V=\xe8\xc3\x0fo/\x8d\xc2\xe4\xfciUl\xb4?\xa23^\xc2\x02ʼnF\xf3\r\x95`\xb6\xb4\x9f\xe6\xd7\x16\x0f$]yИ}\xec\xba_І\xebt\x10n\xa0w\x80\x14\xc8\x01\x13J\r\x9b\xc1\xbf\x9d\xac\x1a͖\xe1\xe6\x16MR\x0e\ah\x06\xb3\x95X\x93\x84\xeb\x84B\xf1N$\xc4\xd4\"\x18[\x94Q\xf4\xdaμ\xf9/i-\xbepr\x18i\xe6\xc5\xf79_/h\xf5J0KP\x90%&W\xd4\xc1\b\xdf,\xf7\xe3,x\xc0\xc6]\xb4+\x89q\xc8\xf5\xf6\xccG\x19f\xe9:\xd5r91!c\xdel\x05\x9e\xf2T\x9f\x9a<\xeb/\x9a7A\x13\x02U\x15\xde+\xa6\xae\x90\xfd\x9a\xe6yISx\x9d\a닝\xef\xa7{\xb6\x10Ղ\xa6QRB\xf5\x16_\x03)\nJ\xc5\x0e\x9c.1\x93\xf3v\xacᅦ\xbcT\x1b\xa8X3\x00\x88\r:\xc0\x01\x85gJ\v\x14\xee\xf5(\x98<\xf8K\x1d&\xfe}\\\x95\x88\x92\xcdr\x14\xe8<\xb4\xe6\xcd\xdc\xf4\xae\xd6OR\x98ܜ\x04]\xf3z\xc3A\u007f\x06\xca Ś\xdc\x1e\x1f'm\x0f%\x8a\x04\xb9\x86\tG\xc2?\xcdܿ\x9e\xb2\xbf#\u007fx\xff\xa4\xe3\\SZ\x9e\xb8a|x\x92x\x9e m\xcaQq\xb9#A\xee@~\xca\f\xb6\x1d\xb9s\xce\xed\xae\xa3\xe9\xe3\x9d`4\xfe\x85\u0381r\xdc\xf9\xd6cٳ\"r\x87\xd2\xc39\x18#\rMF\xec|Ez\x020Q`\xec0\xf8\xd1֔\xe8\xbf\xd1\xf4\x006\x13\x02\x96h\x80~\xb8\x9a\xbbKp'\x99\xd76\x83\xe9u\xaf?Bl^\x9dDnr\x96\x8a\xdb^P\xd3H\xc9,\\!\x19\x8d\xef/\xdb2\xaaR\xbb\xed\xfck\xf7\x87\xe2\x8f\xff\x99אr]\xbc\x96\xc0\x96\xf3\xa1\xf8\x96\xa2\x1dq\xe5\xfb\x89\xb2|1\xaf\xe7\x8a\xe7ؼ\x91ÌI\xa01\x8f\xe3\xa5\xc4q\xba\xbc\xf8\xf4\x80\xc9W\x94̟\xcd\x1b\x90t\x06Tɼ\tG$\xca\xfc\x8d\xce'\x93\xcfw)\xa6\x0f\xf5\xfe\xb7F5\xe8/h\x8725\xff0\xc2d\xfeI\xad\x87^\xfb\xf6\xf7iF~\x97\xbe\xa2\xea\xc4\xff\x06\x00\x00\xff\xff\xf40\xec\xfc\xd6\n\x00\x00", + local: "data/en/countries", + size: 2774, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1xWTZbbOA7e8xTaTfJe+hCx6992xVNyVb/ODpIQCTFFOhRpR97PyeZi/YGSXfWyIUCA +IvHzAdDXH21HToZIzvz/f5ZcY77aChICbTko7UFqckVJvcfWNT4Epa23mSSxmYkU6oiTykqbqMBtxYJC +lRrIQssQO+V6zveHVGEdanaDeFc8DtPzaYiBrB5QTumZQ0XyEyYuqKOeBqWBRPeutdTw0Bl9iBoPHVsK +KdNWUq9Uzgzi9AMOvZqz6JK6vPBWjnhi4QeYlA1+4HDm1h/V1IWPw4kyk44cLyYuAp3FgkiUoSveJLRy +sX+4ih9dI4jat5qx7jhA7MMIdXIsxY3aOJAlGJhsS+roIoU9ni3uaPC6SbjBLKmvPG5ShoP3DoyjRvcH +Lt44NAx27OndgiUijRAWX39MiXvhQ6qs1GbZUYNFLOsKv5ZdQO4R0YtrS1/7ofi0YgTNtZ/fxdb3lRrh +ex8Q5KVH+r9cby78j4vohntfBwIQ/tD6/buBHoArXhQrSx+5aP7zePQSYFXw+BJShcZyPGgel2euu3cf +btj1FPbm5qdUPkUxN74Xp1ddmA8O39YJmAjmth0P0dxaYNgeJ8mvRMiHIEz3SRyTuUWCgtIhesXnbezE +H8Dckd2r3Rfzi08b3ILwDZ+hC56vft3JT8HicszuArmaQdjBfjyiQJp3W29Hx4NcBSVc6Ti8A0V4MPdU +Id33lCN/zx4wUxqQ69Hcd3rfvVTINCrP3AdmPKdkeh9cxsk9QsDWpwMr2+sSuQfywOHFgXHXFIGJ/LUQ +ADNhN+oLDwQ4mwem0OT62NQ33pG9RsM8eNekQJlpixUW85AcED2ax5qzKbkUdPWT048IjS6/sMwnBsuA +SbFRxRCIrXmMZEfzhHrX5D7RAaonDmrvkw8Ndis6077LvWvFbiSzkiAVAGRWHpn8Ujz7ELvLJofYrNIJ +DpnVGNrxnD9dE/C8pqh9YM3ofYj5mgcfO2/WUuUeCDrqCiRGtKvIaCVriV3KnXKdfjOKNIXWbKhG6LBy +k0G0QQZaGmokCKChk2QyDlllGzkizWCyOKosDB1Zew0uBGia8isx2ARk0HSrspJUP/oYoeTfUnuzkTrM +Md542/ijUkeq0eq0We7gArchy+IAvFEEG3ydj50Vbvk9pB+VZp6pFwXgMx5N5pkPZLEqWicTP/CFdn5r +WYWnYkl2joLuvjPlTD8jm4EwHsDhlWfBlJlWPejDD28vjcLk/GlVbLQ/ojNewgLFiUbzDZVgtrSf5tcW +DyRdedCYfey6X9CG63QQbqB3gBTIARNKDZvBv52sGs2W4eYWTVIOB2gGs5VYk4TrhELxTiTE1CIYW5RR +9NrOvPkvaS2+cHIYaebF9zlfL2j1SjBLUJAlJlfUwQjfLPfjLHjAxl20K4lxyPX2zEcZZuk61XI5MSFj +3mwFnvJUn5o86y+aN0ETAlUV3iumrpD9muZ5SVN4nQfri53vp3u2ENWCplFSQvUWXwMpCkrFDpwuMZPz +dqzhhaa8VBuoWDMAiA06wAGFZ0oLFO71KJg8+EsdJv59XJWIks1yFOg8tObN3PSu1k9SmNycBF3zesNB +fwbKIMWa3B4fJ20PJYoEuYYJR8I/zdy/nrK/I394/6TjXFNanrhhfHiSeJ4gbcpRcbkjQe5AfsoMth25 +c87trqPp451gNP6FzoFy3PnWY9mzInKH0sM5GCMNTUbsfEV6AjBRYOww+NHWlOi/0fQANhMClmiAfria +u0twJ5nXNoPpda8/QmxenURucpaK215Q00jJLFwhGY3vL9syqlK77fxr94fij/+Z15ByXbyWwJbzofiW +oh1x5fuJsnwxr+eK59i8kcOMSaAxj+OlxHG6vPj0gMlXlMyfzRuQdAZUybwJRyTK/I3OJ5PPdymmD/X+ +t0Y16C9ohzI1/zDCZP5JrYde+/b3aUZ+l76i6sT/BgAA///0MOz81goAAA== +`, }, "/data/en/currencies": { - local: "data/en/currencies", - size: 1800, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xfftUKv\xeb6\f\x9ds\x15\x1c\xc6\xcb\xf0\xf7%\xb1\x9d\xb8\x96۞\x97\x19,\xa1\x12k\x8at!2~\xca\xea{)\x8bJzN:\xb1\t\x10\x04..>\x9a\xffU7\xe4L\x17\xc8\xe9|Vs{\xc6?\xe9\x1d_\x18B\xcd\x02ae\x1c\t\xeeZH%\xe9\x87ߝ\t\\\xe9\"P\xe0n\xa6W\xde\xda\xe1^jv\x01\xb6\xfa\xc0\x9d\x87\x1c\xbb d\x93\x83l\x914\x90\x8b\xb21\xd6\x1aWwjA\r\xb5\xd4M&\x90\x85\x8c\xcb1\x17\xe4jK\x15w\x8d>х ˙*\xffŞmmb\xab7B\xaeL\xa2\xb4\xb1\xfa\x8c\xb8\x10\xfa0V\x1f\x99\x90\xdc\"ښd\xc8\xee\x9dԒ\x1c}\xb1\\n\xe6z\xb1\\\xcf_\xb3\xabA\xb1\x9e/'\x19\x98yL\rg\xa4\xf93\x82\xba#\xbbָ\xb3Q\xc7\xfdB?|s1SKo}{6\x99\x97\xe5\xe60\xf9\xf4\xa0_\x1f\x13\xab\xc9\xc81T\xe2)\xc0v\x1b\x1d0\xf6W\x89\x9d>\xf8\xe8*\\}p\xd9\xc0\xef5\x9e\xad)\xf5\xd6Kt\xbdZ!\x0e\xc9Eo\x05\xef\x05b\f]ٰ~\xf8\x01.\xc8\xf53\xbd\xc7u\xa7V\x1ep\x10\xc9}z\xb8\xe3Y\xc5\x00\xb7\x0f/\x1c\x1a\x16K\x884\xd3?\xa2\xb1\x15\x83\x965u\x81\xc5\xe9%\x88;\x9f\x19\xaf3a뺿\x86\fm\xdd\x05\x9f\xfa\x06 \xf0\xaf\xd6Q\xe0xc\xfe6\x93\xf9Ƹ\xe4{\x00s!R\x03\x03\x9c\x89\x18\xb1\xea\t\xfd\x1d\xf3\x0fo+\xfd\x1aa\x88\xb30\xe3\xc1J\xa8lZb\xf5\x98\x1c\xc3\xe1\xff\x00\u007f\xf4\xae\x06E\xf8\xc9\b\x1e\xa3C\xf9{\xbd\xf1b\\PO%\x0f\xef\x13oQ\xd4\xd3~\xa3\x8b+\x97\x86l\x8aqCw\xa20u\x03CW!\xb3c\xbc2P@He\xba+\f5\xd0H\xa2\x14φ\xe3?\xb9s\x9f\xe4\xee~$\xe8\xa9\x13b\xab_\xf8\xa6\x8b\x06Õ\xac\x03\xd9^\uf330z\xc6\f\xa4&\xc8P\x9f\xe9\n\xa7?٩g/\x15M\xe3\xb0e\xd7c|\xa6\xe9A\v0\x06\xb2\xf0143\xfd\xa7wj\x1bodB\xb6\xdf1\xc6ٻ\fb\x17\u007fq{\xf6Q\xea\xcc\xfb\x9e,\xf5C6\xf0W\x9b0hВ@ep\x8cb\x82A\x03\x8e\xc9\xef\xf9\x97)\xfd\xd86{/\xbe\x84\xb42\x82\x11\xeeԗ2|V!\xe5\xfb\xc640\x91\x93{\xf1r\xa3>\xf7\xebk;\xd1w\xa0\xcb}\x1d\x8d\xe1\x0e\x84\aU\x9a\xee\xb1\x05\x0e,Q\xbfD~\xc7\x02(\xbcM\x1aPa\xaeW\x83\x92\x8c\xb0\x0e\x16\xe3㾼\xf1\xd6`{\xbcY\x1fz\b\x12b\x8d\n\xaf\xbb2b\x8d\xa8\xdf(\x90 |\x9f\xe2\x1f};,\xbf\x04z\xc7f\x92\x87s\xec\xeeE?\xa7\xb0\x05\xc5\xca\xe8\xb9\xd0y\xa0nx]\x18\xfbΒ\xc3\x16\xe0\x93\xae(ϔva\xfd;\x12\xa4<\xb7I\xe6\xe4\xfe\xe4\xef\xf7\xa9\x88\xd8\xc4Î=\x82\xb0Qs\xafq\xaamqM\x9b\x11ir \xd8\u007f\u05ec\x9d~@#\xcfT!F\xef\xc8]\xa6\xbe-bj\xa3\xb1\x0f\x8a\x1bW\xec\x86\nx\x81d\xc2ǽr\xb9-Ndn0ODd\xf8\xa7\x86\xcc`\x82\r\x1d\xd4\t#d*\xaatҜ\xfc\x99j\xffi\x19\xf1%\xf9\xfcl\x9c\xa2\\x\xe8sR\xe3\x97#\x11\xa7\xd7-4\xf8\x80L\r4^n\x91L\xe5ی\xf5?\x1f\x9b)\xc6\x1f\xec\xf8#b\xc2\xf4\x02\xf5}'\xe1ouz\x13YB\xba3\x1c\x1c\xb5x\xefj\xf5F\xc36\xdeްIH\xfd\x1b\x00\x00\xff\xff\xbc\xbdΙ\b\a\x00\x00", + local: "data/en/currencies", + size: 1800, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/3RVS3brNgydcxUcxsvw9yWxnbiW256XGSyhEmuKdCEyfsrqeymLSnpOOrEJEAQuLj6a +/1U35EwXyOl8VnN7xj/pHV8YQs0CYWUcCe5aSCXph9+dCVzpIlDgbqZX3trhXmp2Abb6wJ2HHLsgZJOD +bJE0kIuyMdYaV3dqQQ211E0mkIWMyzEX5GpLFXeNPtGFIMuZKv/Fnm1tYqs3Qq5MorSx+oy4EPowVh+Z +kNwi2ppkyO6d1JIcfbFcbuZ6sVzPX7OrQbGeLycZmHlMDWek+TOCuiO71rizUcf9Qj98czFTS299ezaZ +l+XmMPn0oF8fE6vJyDFU4inAdhsdMPZXiZ0++OgqXH1w2cDvNZ6tKfXWS3S9WiEOyUVvBe8FYgxd2bB+ ++AEuyPUzvcd1p1YecBDJfXq441nFALcPLxwaFkuINNM/orEVg5Y1dYHF6SWIO58ZrzNh67q/hgxt3QWf ++gYg8K/WUeB4Y/42k/nGuOR7AHMhUgMDnIkYseoJ/R3zD28r/RphiLMw48FKqGxaYvWYHMPh/wB/9K4G +RfjJCB6jQ/l7vfFiXFBPJQ/vE29R1NN+o4srl4ZsinFDd6IwdQNDVyGzY7wyUEBIZborDDXQSKIUz4bj +P7lzn+TufiToqRNiq1/4posGw5WsA9le74ywesYMpCbIUJ/pCqc/2alnLxVN47Bl12N8pulBCzAGsvAx +NDP9p3dqG29kQrbfMcbZuwxiF39xe/ZR6sz7niz1QzbwV5swaNCSQGVwjGKCQQOOye/5lyn92DZ7L76E +tDKCEe7UlzJ8ViHl+8Y0MJGTe/Fyoz7362s70Xegy30djeEOhAdVmu6xBQ4sUb9EfscCKLxNGlBhrleD +koywDhbj47688dZge7xZH3oIEmKNCq+7MmKNqN8okCB8n+IffTssvwR6x2aSh3Ps7kU/p7AFxcroudB5 +oG54XRj7zpLDFuCTrijPlHZh/TsSpDy3Sebk/uTv96mI2MTDjj2CsFFzr3GqbXFNmxFpciDYf9esnX5A +I89UIUbvyF2mvi1iaqOxD4obV+yGCniBZMLHvXK5LU5kbjBPRGT4p4bMYIINHdQJI2QqqnTSnPyZav9p +GfEl+fxsnKJceOhzUuOXIxGn1y00+IBMDTRebpFM5duM9T8fmynGH+z4I2LC9AL1fSfhb3V6E1lCujMc +HLV472r1RsM23t6wSUj9GwAA//+8vc6ZCAcAAA== +`, }, "/data/en/currency_codes": { - local: "data/en/currency_codes", - size: 519, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff$\x91Kz\x80 \f\x84\xf7s+0\xa0\xc8C\x1a\xb0E\xef\u007f\x90\x0e\xb8\x98/Bb\x92\xf9q\xb7\xe2n\x82\xddVlF`n\xc1Y\x1f\x84\xa2(\xaf`;<^\xa3\x98u\xc6\x17\x98\x94 \xbc\x9f\xff\x18m\xab\xde\xf4\x06˳=(鰖\xd1y\xd8̨\tv/\xab\xf7\xb8<\x86\xf1\xd8\x12g\x95\xe7\xd3U1*\xeftá\x11\xdb\xc3\xdc\x1b!\x91r\x19\xc2|I;\xc6&p{\x85sq\xed\xe2O\x81\x0f\x19^\xfd\xaa\x1b\xe6Ʈ\xb2j\x8f(8n\x8f\xd0\"\x86\xe8\xf2\x12fT\xeaG\x10\\EH\r\xa1'\x9c\xf9\xf3{^\x82\xe8\x1a\xa2\xfe!\xfe\t\x12y$\xf6ȏ\"\xb3.sf\x1e\x05\xd9|3&\x9brE\\YQ\xa3҃\xa0\xba\x82zL?\x1d5\xf1\xbb;\xfc\x90\x9d^\x85J\xd0ۢ\xf1<̎\xb6\v\x1a=\xb6\xd0\x17\xdf9\u05f5\xba\xf6M\xecׄ5\xf4:\xf9w\xee\xd3\x0f\x8b\xde\x19\v\xa5\x0f\x8c\xfb\xdel\xbeï\xb3\x94\xc7/so\xfe\xf8L\u038b7\xd9.v\xf3Ntq\x9a\xf3W\xe4\x9eso\xe6\xfe\x03\x00\x00\xff\xff\xf7O\x92\xa7\a\x02\x00\x00", + local: "data/en/currency_codes", + size: 519, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/ySRS3qAIAyE93MrMKDIQxqwRe9/kA64mC9CYpL5cbfiboLdVmxGYG7BWR+EoiivYDs8 +XqOYdcYXmJQgvJ//GG2r3vQGy7M9KOmwltF52MyoCXYvq/e4PIbx2BJnlefTVTEq73TDoRHbw9wbIZFy +GcJ8STvGJnB7hXNx7eJPgQ8ZXv2qG+bGrrJqjyg4bo/QIobo8hJmVOpHEFxFSA2hJ5z583tegugaov4h +/gkSeST2yI8isy5zZh4F2XwzJptyRVxZUaPSg6C6gnpMPx018bs7/JCdXoVK0Nui8TzMjrYLGj220Bff +Ode1uvZN7NeENfQ6+Xfu0w+L3hkLpQ+M+95svsOvs5THL3Nv/vhMzos32S528050cZrzV+Sec2/m/gMA +AP//90+SpwcCAAA= +`, }, "/data/en/domain_zones": { - local: "data/en/domain_zones", - size: 753, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\f\xcbA\xb6\xa5 \f\x00\xd1y\xed2 F\x84 \x8f\x80\xb6\xae\xbe\xff\xf4\x9e*\x89Ȇ$dG\x14\xc9HE\fiȅ\xfc\x90\x8182\x91\x85<\xc8?\xe4#\b!\x106B\"\xec\x04%\x1c\x84L8\t\x95`\x84F\xb8\b\x83\xe0\x84I\xb8\t\x0f\xe1%|D!F\xe2F܉J<\x88\x99X\x88\x95h\xc4F\xbc\x88\x83\xb8\x887\xf1\x1f\xf1%~l\x89\xedd+l\xc6v\xb1}\xa4HJ$%\x1d\xa4Ar\xd2$-\xf6\xcc~\xb2\x17vc\xbf\xd8\a*h@74\xa1;\xaa\xe8\x81f\xb4\xa2\x866\xb4\xa3?\xf4\xaftt\xa2\v}З\xa3p\x18G\xe3\x18\x1c\x93c\x917r\"W\xb2\x91\x1b\xf9\"\xffȃ\xec\xe4ə8\x8d\xf3\xe2\xec\x94DQ\xcaA\xc9\x14\xa34\xca\x1f\x0e\xcaCy)\x1fU\xa8\x81\x1a\xa9\x99Z\xa8\x83\xea\xd4I]ԛ\xfab\x82El\xc3\x12\xa6\u0601\x15\xacb\x865\xec\xc2:\xf6\xc3\x06\xe6\xd8\xc4\x16vc\x0f\xf6\x0f\xfb\xdb?\x9a\xd0\"-\xd1v\x9a\xd22\xad\xd2.Z\xa7\rڢ}\\F\x17z\xa2\xeft\xa5\x1f\xf4B\xaf\xf4?o\xf4Aw\xfa\xa4?\xf4\x97\x9f0\x12\xe3b8c1\x1e\\\xf0\x80G|\xc3\x13\xae\xf8\x81g\xfc\xc4\v^q\xc3\x1b~\xe1\x03\x9f\xf8\xc2o\xfc\xc5?fdn̝\xa9̃y2\v\xb32\x8d٘\x17\xb33\as2o\xe6\xc3\xfcX\xc2RVa\x19\xcbY/\xeb\xe3\x16\xeeȝ\xb8\x95;s7\xeeų\xf38o❼\x8bO\xf8\x8c\xef\xe1\u007f\x00\x00\x00\xff\xff\x88\xcdet\xf1\x02\x00\x00", + local: "data/en/domain_zones", + size: 753, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wzLQbalIAwA0XntMiBGhCCPgLauvv/0niqJyIYkZEcUyUhFDGnIhfyQgTgykYU8yD/k +IwghEDZCIuwEJRyETDgJlWCERrgIg+CESbgJD+ElfEQhRuJG3IlKPIiZWIiVaMRGvIiDuIg38R/xJX5s +ie1kK2zGdrF9pEhKJCUdpEFy0iQt9sx+shd2Y7/YBypoQDc0oTuq6IFmtKKGNrSjP/SvdHSiC33Ql6Nw +GEfjGByTY5E3ciJXspEb+SL/yIPs5MmZOI3z4uyURFHKQckUozTKHw7KQ3kpH1WogRqpmVqog+rUSV3U +m/pigkVswxKm2IEVrGKGNezCOvbDBubYxBZ2Yw/2D/vbP5rQIi3RdprSMq3SLlqnDdqifVxGF3qi73Sl +H/RCr/Q/b/RBd/qkP/SXnzAS42I4YzEeXPCAR3zDE674gWf8xAteccMbfuEDn/jCb/zFP2ZkbsydqcyD +eTILszKN2ZgXszMHczJv5sP8WMJSVmEZy1kv6+MW7siduJU7czfuxbPzOG/inbyLT/iM7+F/AAAA//+I +zWV08QIAAA== +`, }, "/data/en/female_first_names": { - local: "data/en/female_first_names", - size: 686, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xb7Y\xe8\xa2\x18\xa1ST\xd4\xfd\x16\x81y\x97}\x9c\x9ebR<\x0e\xac\xa4\xaf1{\xaco\x9f\xe24\xbd\xb0s\x89\xb5\x88X\xe2b\xb2\xec\x82\x0f\x92>\xa3{*\xc1\xed\xf7ۢ\x88\xf0\x91\xcb.\xc6Y\xae\b\xb1\xd1M\xe7\x1c\x9dri\xffU\x1f\xae\x1b=\xc3A\xdd\xc9\xe7\xbfl\x93\x02\xff\xe4\x15q}Cr\x871\x1a\xa0\x89\x1e\xecg\xd9\xfd\xba\xb4\x13n(\xc7\"\xc3\xe7\x907\x87\xfa\xb1ܴ\x03\xe7\xdf\x1b\x8e\x80\xf2\xc7\x1eb\x87s\xeb\xe1\x1dg\xd8&\xfc$\x19\x86\x9f.\xe7\x1eZĽ\xe8\x96m\xc5\x17o8\x84\a\xb6\xef\x02hP\xb4a\xf6m\x057LN\x9a\xfe\x06\x00\x00\xff\xff\xff\u0091\b\xae\x02\x00\x00", + local: "data/en/female_first_names", + size: 686, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zxSXa+bMAx9978q7d3uKLeqSrU9G/AaSyHZnHCl7NfvGKa9mdjH58N8sDW6czWdlWnQ +tDB1bBMb01vUPzxJDdRLSvpTjDCOsXErnLx+sUmlS7ZcQwO6MN04zY2uaCTqpNZG7xJRj5wW7LzklJjO +bDnSY8PqMaDGMp2DxCg08IaxEfyBrrpOYrHRRabsD72UojPaQS1Ko3NLNUDQKb0kMn1I1AINHcjh47Q2 +dED3kElmwL6rvTRh/so1RIGqO687kK0GdhpzGDt6rPIrcFI51LZE52BaqibZYxDqOcH9GbvE/PWLwbsU +56Q+t1noohihU1TU/RaBeZd9nJ5iUjwOrKSvMXusb5/iNL2wc4m1iFjiYrLsgg+SPqN7KsHt99uiiPCR +yy7GWa4IsdFN5xydcmn/VR+uGz3DQd3J579skwL/5BVxfUNyhzEaoIke7GfZ/bq0E24oxyLD55A3h/qx +3LQD598bjoDyxx5ih3Pr4R1n2Cb8JBmGny7nHlrEveiWbcUXbziEB7bvAmhQtGH2bQU3TE6a/gYAAP// +/8KRCK4CAAA= +`, }, "/data/en/female_last_names": { - local: "data/en/female_last_names", - size: 1764, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffDU\xddr\xe2:\x13\xbc\xd7[\x05\xb2@%\x90P\x86\xfa\xa8\xefr\xb0'X\x85-qF\x12\x8ey\xfa\xd3-\xb297\x9b\xb5\xfe\xa6\xa7\xbb\xa79\x8c>\xf7\xee-\xf6!\xc5\xe0N~\x18\xbc\x8c\t\vA\x93[X\x9c\x82{\x95\xbbOn\x87-5\x9e\xe0\xc1]\x8c\xa6\xee(\xf3\x10ͽ\x84N\x8d\xab\xc7>\x8e\x82\xcb\xd2^\xebk\xbd\xcf\xea6b\xc6\xfbb\xd9?\x8fܸ\xb9\x16k\xbd\xfc,\xeb\xc35\xf1\xec+\x86\xe5 v\xc5gg\xfeR\xb0\xb1\xd5\t\u05f7\xaa\xee$\xc3\x15\x1062\f\xee\x05h\x82\xfb\u007f,\xe1\xe26jA\x80\xe1\xe1\xde=>O\xb8\xd8g\xb7\x8d7\xacl\x00\xdb\x1dژ\xb3[\x9b\xe2\xcaK\xc7\xfe\x16\u0097\xd61d\xc5Bv\a\tx\xf4\x01\xe6*\x1dM\xbc\x803רv8\x1a\xaf\\\xbfHp\v>\xb8+v\xebg\x80\xf4\x83ή\xf1w5\xe1\xa9\x1b\xaa4\xbe\xedY\x80p\xe3\xb7\xdbD\x96\x035\xf8爧\xa1\xda^\xf3S\x8e\xb5\tn\xcb\xe8\xd9ś\x8c\xd8;I\xe6\x0e\x84\x8d\xd7\xe4\xdeQl&2\xea\xe7\xf6\xe6[\x05\x80\x10\x14l\x9db\xec\x80\xc0\xe8\x83&\xa6\x04\x96\xffʌ\xd6t\x04\xd67\rW\xb6\b\x9alv\xfb8\x11\xfb6B\x82\xbd\xe4\x1f\f\x9br\xe9\xf1\xc2\n>\xa9\xe5S\x0f\x892!\x94L?\x1d\xfc8F\xbc\xb1\x8a)\xff\xa7\b\xad7KȐY\xbf+<ה\x94\xf8\xfe\xda\xfc\xd7\x17\x8c\xf4\xea\x05\xeaʌ\xb3\xbb\x99\xf0W\x11\x14l\xd0퐟\xbd\xf72\xbaC\x81\nЅ\xde\x19\x04\xed\xb1\xad*\x0e\xfe\xab)\xc3\xe8\xd6a\xfbs\xd2@5\xe6\x10\a\xec\xaf|\xea\xa9(.\xa7\x1f\x03\xf3M\u007f\xae\xdeo\xbb\x18d\x80nV\x1e4p\xea\xe9\xc8O\x18\xf9\x81\x06F\x8a\\\x8cܯ\xe08\x12u\x02p4\xaf\xe73\xfb\xad\xf6\x87-\xee,y,-\xbd\xb3\x8f\xd5y\x9b\x12\xea\x1f\x8f\x01\xc2\xf32}զ4\x80\xdfE\x9c;T{N\x9fU\x92ީU7S}SR\xf2\x8dM\b\x1ek+d\x11\x96M\xc0d\x1dK\xf62\xc1/\x03}\xd0P\xea\x1fcW\x95\xc0\xf5\x02\x04]1\xed\xc1c\x1a !\x0eZ\x1d\xfb\xe4>`\xba\x88\xbf`\x15\a\xdfC\x1d\xb0\x95ڥ\xf06\xec\xa1h\b\x91\x01\xae\xa6j\x89\xd7\x12\x02}Q?6\xa5\xda\xf5p\xd3\xd0Rcx\x95\x83\x04\nn=9\xd8ˌ\xab{\xafV\xfdG3\xed`\xa0^\xa7\xe4^\x8c\x8a\xa0\xc3Kx\xa6\x0f\x15i\x84=\xe7\xfa\xf8\xe7\xdf\xc95\f\x1c\xeb\xb6 \xfc\x10\xe6\xae&\x05\x06o\t(\xf0\x1cݰ0\xe98Q[A=\xa4\x96\xb1BS<\x8dd\x1c\xae\x15&\xaa\xa9C\xf7bc\xcaF//\xb9Ue9\xa9܉\x9f9\xa2xd26T]\xc2|Y\xf6\xd8~Pa\xc0.\x89i\xf7\x1c\xc5:gJ;H\xb8\"\x14x\x95\xa0W \x1af[\x97\x8c\xd6k\xd2\xcc\xc4\xde\xf6\xa3\xefrm\xc9\xfdO\xd2?\f\xc1\xa5\xe0\xbda\x88\xc8TU\xce\r\x8a\xddh\xadρ\xe9\x00G\x84|\x81\xf5l\xfe\r\x88\xdf0G\xa5\x9a\xefu\xea\x80\x00\x03\x03s\x98[\xc0\xe4\xf1\x06;\xb7qf\x8eh\x8dջ\xd8oJ\xd1\x19\xc84Xk\xf5\x1b\xb1P\xef!\xe4\xebN\"}\xc6\x14\xd3f\xb9zZ\x02\xfb\xfc\xb8\x94\x19w֊HS\xfe\x1a\xc43\r\xe9;\xe4\xf3\xe8V\xa5\xfe\x90lg\xe4\xa1{U\xe1\\\r4\"\x9f6FO\xc3F\"\xa7\x06'\xb6Rs\x04\xdc=\xf2\xdbE\xefB\xffa\x03֮>[\xa5\xb5\xe8\x1f\x9e\xe1\xb2\xf6\x82okP\x8fhi5ba\x87^ȇ\xcb\b\x92\xaa\xf8\n\xbf\xfa[8\x1d\xad\x80\x10\xb82WZ\x81\t\x99\xa1\xadt\xb0\xbe\x88]\x99\x04\x92\x06f\xb8\xaa,\x8b\xa4Dk\xbb\xdd*\xfd\x1f\xefټ-\xb5\xe5߹ʒ\xe9\x14Z\xda']m\x1c\xe1\x8by\xda8\xc7\t\xd8`\xbd\x04~+m\x12\xff2\\\x04gM\x01A\u007f3\xfd\xe5aջV\xe4\x10\xe7\x16J\xb3i4\xfa\x1b\x00\x00\xff\xffa\x8c\xf8f\x9a\x02\x00\x00", + local: "data/en/female_patronymics", + size: 666, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zSSzY4qOwyE934r/gbUw1whQHfWhvZ0ckjbyJ2A8vanktHZIJF2VeorZ+BZFhosKJ3t +Jp7pK94DS6LvmFLkmbb8iiOd26mPtMFv6opFnoGuwWZecOpxyfYM4pjXCPmJS6Iv9gdtTTmNtBfzSehT +VCUHumR5idJufDfbtUduCfrkSnMwrRh9RaWBF1M45RzkTXv2Stc4Ww61h6AjO44G+flxqfThrA+63C1n +2nm8t3sQS2E6OvRnrrMp0rhM5t0iFIa8mWyRLS70zSkD5MQZBg86Sft3YDdk21qZEogPohBsUAatPIfi +dK6dYMLsYEJD4ZYd+lXqvQ6Ay6EdliWD69qv3Is35E+JrROey7/mBVETGj7y20XvQv9hA9auPlultegf +nuGy9oJva1CPaGk1YmGHXsiHywiSqvgKv/pbOB2tgBC4MldagQmZoa10sL6IXZkEkgZmuKosi6REa7vd +Kv0f79m8LbXl37nKkukUWtonXW0c4Yt52jjHCdhgvQR+K20S/zJcBGdNAUF/M/3lYdW7VuQQ5xZKs2k0 ++hsAAP//YYz4ZpoCAAA= +`, }, "/data/en/genders": { - local: "data/en/genders", - size: 11, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xf2M\xccI\xe5rK\xcd\x05R\x80\x00\x00\x00\xff\xff\x92'H2\v\x00\x00\x00", + local: "data/en/genders", + size: 11, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA//JNzEnlckvNBVKAAAAA//+SJ0gyCwAAAA== +`, }, "/data/en/industries": { - local: "data/en/industries", - size: 4922, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xfftX\xcdV\xe3<\x12\xdd\xfb)\xbcb՜\xef\x19 \x01\x9a9\t\xe4\xc4\x19X+v\xc5\xd1`[\x1eY\x0e\x9dy\xfa\xb9%Y?\x0e\xeeM7\xae\x92JUW\xf5s\x95G1\xc82\xdf\nCZ\x8af\xc8\x1ej-˱1\xa3\x16M\xbe:S+K+n\xc6Vvc\x9b\x05Q~\x8f]\xffQ:_\xcb\v\xe9A\x9e$U\xd9J\xf5=\xe9\xecE5U\xf6\xdaU\xd4\x13\xfe\xe9L\xfe.\x9b\xfc.\u007f\x11\x03K\xc7\xc1\xf0Y\xf9\x96\f۹˷\xb2#ͧ8\x83\xaf\x9d\xa1Zã*\xd9\xf7\xa6\xba\x96\xd77\xec\xad[\xcf\xffˮ\xce¢|\xad%\x16t5>\x9f\xfe\xf4\x8d\x82\x11\xa9\xbad\xc1\xd3\u007fGٷ\xec\xd1]^\x90\xbeȒ\x86D\xbd\x93=a\xffL\xb6\xa7\x93=\x86\xfd\x14\xfa\x8b\f\x1fY\xc8\x06AgEO%\"1\xd7\x04\xa9\xc2\x10\xf1\xdeW\x8d\x93\x8bkg\xce\xd8R\x0e\x80\xa6\xab\x1b\xd5\x12\a\xb6\xf05\x8c\xf8\xc8_\x94\xaa\x00v\xdf7Rt\xec\xdb\xc3h\x14\xce\xedƓ(q'\x00\xda\xe3\xeeT;\xa1͐=\x12\xbc\x115\xb1\xf2Q\xd37\x96\xcdd\x85:\x19\x06\xa7\xfb\x9a\xcb?\x19HI|\ak9\x18\x80gw\x8e\x03c\x90\xa0\x95\xadd-4\x19\xebkC\xc2\xe2\xb1Ӫ\x1aKc\xbd?Q\xc9H\xf3\ued50\xfa\x1a\x95O\rT\x80\x02\xd7\x16\xcd=\v\xdd\xc6%\xcf\bz1\x9b~\x03\xa0\xfcyԝ\x1c\xce8\x91\xdd|\x96\u007f\x18\x86\x01\xbaq\xa0o8\xc5҇\x12X\r\x8aCɶ$L\xb4\xfd~:\xe1\x8e\xf3bdH\xa1݉\xf2K\xd4\xee:\xe1\xb7\x11\xd2:\xbd\x13H[\x88\xdc\xffa\xf7\x0e:\xd5!Ӣ䬌Br\xf6\xe74 Φp\x82V\xec\f\x92\x97\xcd\xf1i\xf8\xd3\xdd\xeb\x9eJM6%aҊ~\xe5\xef\xc8\x0f=\xd7|\x10\x8c70\xb5\x1f\x8fG\xe7V#\x06\x9bDE\xaf4'\xe0d\xf0@\u007fpi\x04\xf0\x902\xc0\x02\x15\xdb(\xc3X-\xa8\x00\xb3\xf9&\xa1o\xf0:\xa8\xa3(K\x15B\xf4.\x1d\xd4u\xb0%\xd0\xf2\"=\x96_\xfciu\xd1\xc3g\xd9!OQ\x02\x19L\xca\xcaA\xf1\x9bP\x12g\x94\xf1\x80&\x82,\xce\x1e\x00\x87\xe1,\x06\x16.\x9d\x1a\x05\x80\ue7fa\n\xd7\xdb\xf1\xe5\xaf\xe9\xb8$f\x84\xcduA\xf1\xac4ɺ\xcbV\x9a*ib-'\xe9\x03\a.4\x18>\x90s̮ϷHRT+d\b\xe3QpAx՞j\x87\xbf\x13\a\xf7QQꋓ$ڛD\b\a\xae\xbcM\xf7\xf67\xbd\xb7\x9bm\xe4\x89\x12T\x16\\\xd9\xe2vk\xde\x15Mq>!'\xd1b\x90\xb0b\x18m\xb7\x89F\x826Aw\xff\xf4z`H\x93J\x9aD\xeefJ\xa4C\xfe,J\xd9H\xc3\x19\xe0\x95\xcaP\xf3ϖ\xff\xf5\xa2ج\xbd\xc4Փ\xff\xda\xd3`/=Y\xb0G\x93\x96\xf8\xc2I\xf9\xd3`\xd0\xdep\xb7\x17j\x94\xab\xfc\x002\xea]V\xf7\x0f\xa6\x11\xd8^N\xf1ϵ߀\xe0\xa7\xe2\r\x18\x9dI,\xa9Pn\bw\xc1X\xa1ƿ\xed\xb1\xaa\xe4\xa4B\\\xa6V\xb3Q\xa2\xc37\xba\x8d\x05\xff M\x93^_\xc42{\x94\x00\xad\x9a\x88!\x18z\xc9\xc37\xdb`\x0e\xdd\x1f\b\xedxu\x93\x15[\x14\x16\x06Z\x1e\x87\x11O\xd5\xd0½\x1a\x80\x18=\xda\"K\xbb\xa0Wođ\xa7\xb0\x9a\xa6\f\x12\x06\x1d\xa8<\a\xfdN#J\xe9g\xc74O\xe5\xff\x10\xdf\xe4o\xa8\xec\x848LS\x924\xc2\x10%\xfd\xb3\xa6\x13u\x03-ΐ\x9f\xab\xa8,\x17\x8cK\xc1>l\n \xa7.\xae-\xf9\x9a\x9a\x19\xc9^\x98t\xe9\x10\xc4\rq\x9c\x89_\xdb^\xab\v\xa5`,\x16Xt\xe2_ \xd4M4\xbeQUmk\xc5\xf6\x1a$\x9d{1\xc4썐\x84\aC\"\x9a\x1a\xdf\xd2A[u\x91\x94\xd4\xef\xaf\xfc\x80\xa9ŷ\x9bmGN\xc0\xbb\xfc\x03զ\xbc'\x81\x9e\x06\xeb\xbb\xf1\xd8L1\xe3%\xa0\xd4\u05cd荾\xd1\f{KyS9,IU\xb9\a\xcc\x1eI\xc6\xf9\x9b\x8c\xc9\x10\xe4\x1e\x0e\v~\xddl0Mgq\xf9\xce>\x93(m\xdb\xec\x8a\xd7*+1\x82\xc7'ZVA娥\x9d\xac\bظ\xf7C\xdc\\\xa0:{\xfb\xd2\nO\xac'[94$\"G6|\xad\ar\x9c\xa4˜0{\xe0\n#\xc0c\xec#\xe0}4\x83\x1au9\v\xe6\xc0\xd3\xdc^S\x14)v\xf5\xb7:\x1eC\"XR\xcc>\x86\x1b\f\xdc9\xb2\x01;>\xa7\xaa\xe1gط%\f\xa1\xe0'\xc9l\x16\xa9\xb6\x1d;\xbf'y\x83M\xa5\x0e\xa2¯\x8b\xd0\x1d\xbc\x98\xef\xb0?\xbb\x87\xf4\x1a-ú\xc9d\x12\xfc\xeb\a7\x9e\x1f\xb2H\x9f\x83a\u007fR\xaaL*;aB\xe8\xe9'\xa5\xdb\x1b\xa3\xa9\xf0.v\xf0E}D.\xd5Ë\x0e/\x88t!\x92\xe6\x82ZЉzڰ\xa8Z\xc0\x99\xa9\x8f}\xf6Z\x92\x0f\xfa\x83䲕\xd6\x18٢J\x05\xbf~\xdcK/^T\xf6F\xe6[\xe9/\xff\x82LQ\xf48\x87\xb2\f\xcd\x194]vL\xdaVR\x97xѠ4\x85\xae\xc2[\xd1\xe6\x9e\x03ٕ\x83#v\x05\xa6\x1e&\xeb\xc9\x16~LɄq\xc5*Z\n\xb0\xe0\x9f$T\xc7\xc6Ш\xf8\x97\x01Tu\xbeA\xe6\xfdP%?\xb9L.\xfeܞ\x90\xb3\x1b]\xcaJ\"\xfb\x99\xad\x015\xa3Vi\xfe\xa1\x84\xc7n\x8c\xe6n\x8a<\"| \xe4\x96jC\x1c\x80OBh\xaf\x1c;hmZ\xa9\xb8ӦJ\xd8\xf1\v\x84w\xf2\x06+\xf2\x06\xb3\x01\v\xcaq\x82\xd9\x1f\xff\xbd\xfe\x9fl\x1c\xcd\xe5Y\xaa\x9e=Y+miq\x9e\x9b{\xf5\xd4NR\xa1\xc1\x84\xaf콶\xd6K\xd7I\x01\x98\x94\xe2\xa3\xee\xd9A\x1a\xe1\xa5c\xcf`e\xaf\xd8\xc4\x15\xef\xa3\xf5n\x1d\xab\x8d\xee\r\x9f&\x82\xd6Ͼ$\xa7\x8c@+9\xabG\xae\xd4\x06\xc7\xf0\x0e\xac\xd5\v\xa6\x85\xe4\x0eJ\xcc;=aVZ\xb1f\x06\xb4\x8e\x18\x16\x92\xfeKjK\xa4X'\x11W\x11\xf4m\x0f\xeeϒ\x90\x98f4[\xa9\xf0ˬA\b&\x8b5\xdd`\xd4\xf3\x84\xfc&\xcf\xea0\xc0$\x05\x1f\xd9Q\xf5\xe8\x8d\xd9\x1e\x06\t]\xaa?\xa3\xf2&K\xa7\x119\xa4\xb0\x9chu\xd0\xd3\xe4\x95twv\xf1\xce\x00\x17\xc3\xce:\x83\xb2\xa1\xbc\xf5v\x04\xbd\x03\xb3\xa6\xb8)\xe0\x805\xb3\xdc\xfe\xea\x99;\xbe\x11\x12\x01\x1f\xdcb\x8bsO\xb5\t\xc1Ϥ\xa2\x91\x9d\xef\xbd\x042U\xfb\x8a\xf0\xfc\xe9\xf4\xcc\x1a?\xcf\xda8v\x051\xa8\x85\xdd*\x12\x05\xe9SҀ\xa0\x0f\xeb\x8e5|\x04[\x1d[I\xf7\x1fG\xc4͖\xbe\xf4'\x84\x1e\xd5M\x1a\xad\xa6\x90LA\xc7\xd6@wW\xeb8\xb0\x06\x84\x01GR\xfe\x86\x95*\x8a\xc1\x12o\x92DR \x91\xc4oZ\xb7l\xe9#\x1eNߛT\t\xb9\x181H\x87IV'@%\"\x92\xb4z\x02\x8drߦ\x1e\xb1D\xff\xc9\xf0y\x90\"J\x01\xedg\xe0\xa3\x1b\xb0\x03\xd4\xda\xc5\xe5\f\xe3L\xf6OvA\xb6\x96\x9ed\xa8 \xf4\xecq\x90p\xba\xad\xf6F\x80ݏ\xe4ޜ\x92\xfc\xae:m\xd2DD\x85d\x1b\xeaFQ\x8d>4\xe3o\xd4\x1e\xf6(/\x95\x1fГ9]U\xfd\x90\x1f\x86\x1bJ煛O\xd8n\x90\x02K7\xbc`\xfe<\xaa<^\xbeR\x15\x06\xda3\xb4\xd2[s\xec\"\x15\x86\xff\xeea\x92۟\u07ba\xe5o9\x1b\xf5\xc0\x91:A\x9f\xac\x87\xbb]\xca\b\xb7܋\xaaq\xf9\xb4^\xb8\x9cn\xdeFyՅ\x14\x8a\xf3fJ\x11\xff\x89\n[i\xfbǣ\xc2q\t\x1c\xb4rFoD\x9fL\xebmo(tܶ\xf9_\xc9\xff\x1b\x90\x16\xc1@\xcb\x02\x89(\x10$\x18\xb5\xb7#\xa7\xc4\xc3R\xcdP\x88lx\axoVd\b\\\x86\xb9\x88\n\xe7\xed#T5\xb0\xe8j\xbf\x8c\"\xbc\xae\x8a\x04\xc4\xd5\x10O\x8f\xd3\x1a\r\x0fTD\xfc!%\xbdD\xbfkT':\xe9\xce\xfd\xe2\x06\x88\\\xebǐH¶\x9bg\x85\xaf`\xdd\xde6\x032\xc1j\xee\x868\xf1U\xe3xױ\xfd[\x1b\xd0F\xe0\nu\xd1k\xf7\x065Π~\xbcY+\x94Ŕ\x14ƌ\xa5M\xff\xb8\xb2\xaf\xfc\xabd\xf8JO\bF\xe4u\xf6n\x16\xad\xfc[\xb3\xfc\xe6\xd1i\x9d]:$I\a\x19\xd1\\\x10\xbaS%Aa\x95\xbf\xc3Ǻ\xe1B\x1a\x01ټ\x00\xbf\x03\x00\x00\xff\xff\xb11\x04X\xc6\b\x00\x00", + local: "data/en/jobs", + size: 2246, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2RVXXLjNgx+1yk40wP0DKnjtbezidXI0zwzFCRxI5Ea/njj6fTuC4ikSMkvHvMDIAIf +PoBPQmivHDtobVqpuNOmStjxC4R38gYr8gazAQvKcYLZH/+9/p9sHM3lWaqePVkrbWlxnpt79dROUqHB +hK/svbbWS9dJAZiU4qPu2UEa4aVjz2Blr9jEFe+j9W4dq43uDZ8mgtbPviSnjEArOatHrtQGx/AOrNUL +poXkDkrMOz1hVlqxZga0jhgWkv5LakukWCcRVxH0bQ/uz5KQmGY0W6nwy6xBCCaLNd1g1POE/CbP6jDA +JAUf2VH16I3ZHgYJXao/o/ImS6cROaSwnGh10NPklXR3dvHOABfDzjqDsqG89XYEvQOzprgp4IA1s9z+ +6pk7vhESAR/cYotzT7UJwc+kopGd770EMlX7ivD86fTMGj/P2jh2BTGohd0qEgXpU9KAoA/rjjV8BFsd +W0n3H0fEzZa+9CeEHtVNGq2mkExBx9ZAd1frOLAGhAFHUv6GlSqKwRJvkkRSIJHEb1q3bOkjHk7fm1QJ +uRgxSIdJVidAJSKStHoCjXLfph6xRP/J8HmQIkoB7WfgoxuwA9TaxeUM40z2T3ZBtpaeZKgg9OxxkHC6 +rfZGgN2P5N6ckvyuOm3SRESFZBvqRlGNPjTjb9Qe9igvlR/QkzldVf2QH4YbSueFm0/YbpACSze8YP48 +qjxevlIVBjx6hiJevRiBG1brXwitnq/eWAi/OOpc0ABrYvMihJ+X2kgAA9I3UwPDPtoztNJbc+wiFYb/ +7mGS25/euuVvORv1wJE6QZ+sh7tdygi33Iuqcfm0Xricbt5GedWFFIrzZkoR/4kKW2n7x6PCcQkctHJG +b0SfTOttbyh03Lb5X8n/G5AWwUDLAokoECQYtbcjp8TDUs1QiGx4B3hvVmQIXIa5iArn7SNUNbDoar+M +IryuigTE1RBPj9MaDQ9URPwhJb1Ev2tUJzrpzv3iBohc68eQSMK2m2eFr2Dd3jYDMsFq7oY48VXjeNex +/Vsb0EbgCnXRa/cGNc6gfrxZK5TFlBTGjKVN/7iyr/yrZPhKTwhG5HX2bhat/Fuz/ObRaZ1dOiRJBxnR +XBC6UyVBYZW/w8e64UIaAdm8AL8DAAD//7ExBFjGCAAA +`, }, "/data/en/jobs_suffixes": { @@ -236,258 +550,603 @@ var data = map[string]*file{ }, "/data/en/languages": { - local: "data/en/languages", - size: 821, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff,RQv\x1a;\f\xfd\xd7*f+@\x12\xc8\x03\xf2h\u171e\xe6O0\xaa-\xb0e\x8el\x87\xc2_\x17\xd4U\xb4\v\xab\xec\xc9nj\xaeeIֽ\xd2\xec\x87\xf2\x05Q2\xcc\xc2\x11\x85Q`\x16=*\x9f`\xa6x\xec&\xd2\xe4\xcf\x19#e\x82\xd9=\xa2\"\xcc\x1e\xa4\fs\n\xa85\xb7\x809\x89\xc3`.\xce\x01#\xc2<\xe5\x9e8\xaf\xc1YŎ\xb4WX`\xc1`\xe7\x85g\xe9gMXZ\xc0\xe2A'\x0fO\xd6Hn\xc6\xea?y\xfe o\xb6\x96v\xf3H\xe2.\x1e\xe1Y\\h1Ϲ\xa4\xfe\xc8\v\x9f'\x13\xf8ʒ\fH/\xf2\xa2$\x96\xf8\x8dr\x19^\x94{\xa3KtX\x1f\xb0\xa4\xa4\xae\x9fIc3Jt\x81e5r\xf2緁\xb3\xa1°Bn\xcd\r\v\xa5\x14\bVtT\xba\xc1\x8ae\xb4;V\x1e\xb6\xa9TXU\xf9d\xf9z2M\xec\xf2\x04\xaf2&#\u061d\xf6\xb6\x1f\x96H\xa1\xf9\x8d~s\xfe\x87W\xec\x02\xacQ\x04G4\x9b}\xb4\x92\x06\x1ex\xf1\xb0\xf6\x91\x14\xd6Iɢ\xd7U\xc7Fi}Ww\u007f\xc0\x06\x93}\xe5\xa3\x15\xdap\xf1u\x1aߦ\xfe\xa4xLըY\xec\x16O4N\nmMr\x87\xf9\xde\xc1\xe7\u07fe\xd8PiMl\xff\xfeJ\xf6\xf4\xb6\xb16ŷ)\x8c\xe9\xa3%\x9a\xe6\xa9\xf7k\xa8\x90\x90S\x16x\x1b\xe9H&\xc7\x1b]\xdb\xd0\xdf\xe86\xbcS\x9b\xea8\xec\xd9ɰAq\x15\x9d\x05$-\x9eT\x86}*>\xb5㍺\xec\xff+\xdf\x11vxe\xdb+)\xc9`\xf6͐v\xc9v\xa9\x8fxg\xf9\xd5\xd5\xd6\xe1\xae\xcaٖ\x12\xbeT[\x93\x8a\xf05ʼn\xf4ހ51\xbd\xb0\xbfN\xfb\xb3\xbf\xa1\xe7潵)\xeeo\xd4\xd5;\xe0\x99/\xf6\x8f\x1c\xe0@\xc1*\x9b)5\xc2\xc1#\xc3!]\x86\x9dm\x89\xc0!\x1bm4sCA\xf8\xcec\xcf~\xaf\xa1¿\x00\x00\x00\xff\xffq\xe9\xea75\x03\x00\x00", + local: "data/en/languages", + size: 821, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/yxSUXYaOwz91ypmK0ASyAPyaOGcnuZPMKotsGWObIfCXxfUVbQLq+zJx4yuZUnWvdLs +h/IFUTLMwhGFUWAWPSqfYKZ47CbS5M8ZI2WC2T2iIswepAxzCqg1t4A5icNgLs4BI8I85Z44r8FZxY60 +V1hgwWDnhWfpZ01YWsDiQScPT9ZIbsbqP3n+IG+2lnbzSOIuHuFZXGgxz7mk/sgLnycT+MqSDEgv8qIk +lviNchlelHujS3RYH7CkpK6fSWMzSnSBZTVy8ue3gbOhwrBCbs0NC6UUCFZ0VLrBimW0O1YetqlUWFX5 +ZPl6Mk3s8gSvMiYj2J32th+WSKH5jX5z/odX7AKsUQRHNJt9tJIGHnjxsPaRFNZJyaLXVcdGaX1Xd3/A +BpN95aMV2nDxdRrfpv6keEzVqFnsFk80TgptTXKH+d7B59++2FBpTWz//kr29LaxNsW3KYzpoyWa5qn3 +a6iQkFMWeBvpSCbHG13b0N/oNrxTm+o47NnJsEFxFZ0FJC2eVIZ9Kj6144267P8r3xF2eGXbKynJYPbN +kHbJdqmPeGf51dXW4a7K2ZYSvlRbk4rwNcWJ9N6ANTG9sL9O+7O/oefmvbUp7m/U1TvgmS/2jxzgQMEq +myk1wsEjwyFdhp1ticAhG200c0NB+M5jz36vocK/AAAA//9x6eo3NQMAAA== +`, }, "/data/en/male_first_names": { - local: "data/en/male_first_names", - size: 665, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff4\x92͎*;\f\x84\xf7~+\xfe\x06\xd4\xc3\\!@wֆ\xf6trH\xdbȝ\x80\xf2\xf6\xa7\x92\xd1\xd9 \x91vU\xea+g\xe0Y\x16\x1a,(\x9d\xed&\x9e\xe9+\xde\x03K\xa2\xef\x98R䙶\xfc\x8a#\x9d۩\x8f\xb4\xc1o\xea\x8aE\x9e\x81\xae\xc1f^p\xeaq\xc9\xf6\f\xe2\x98\xd7\b\xf9\x89K\xa2/\xf6\amM9\x8d\xb4\x17\xf3I\xe8ST%\a\xbady\x89\xd2n|7۵Gn\t\xfa\xe4Js0\xad\x18}E\xa5\x81\x17S8\xe5\x1c\xe4M{\xf6J\xd78[\x0e\xb5\x87\xa0#;\x8e\x06\xf9\xf9q\xa9\xf4\xe1\xac\x0f\xba\xdc-g\xday\xbc\xb7{\x10Ka::\xf4g\xae\xb3)ҸL\xe6\xdd\"\x14\x86\xbc\x99l\x91-.\xf4\xcd)\x03\xe4\xc4\x19\x06\x0f:I\xfbw`7d\xdbZ\x99\x12\x88\x0f\xa2\x10lP\x06\xad<\x87\xe2t\xae\x9d`\xc2\xec`BC\xe1\x96\x1d\xfaU\xea\xbd\x0e\x80ˡ\x1d\x96%\x83\xebگ܋7\xe4O\x89\xad\x13\x9e˿\xe6\x05Q\x13\x1a>\xf2\xdbE\xefB\xffa\x03֮>[\xa5\xb5\xe8\x1f\x9e\xe1\xb2\xf6\x82okP\x8fhi5ba\x87^ȇ\xcb\b\x92\xaa\xf8\n\xbf\xfa[8\x1d\xad\x80\x10\xb82WZ\x81\t\x99\xa1\xadt\xb0\xbe\x88]\x99\x04\x92\x06f\xb8\xaa,\x8b\xa4Dk\xbb\xdd*\xfd\x1f\xefټ-\xb5\xe5߹ʒ\xe9\x14Z\xda']m\x1c\xe1\x8by\xda8\xc7\t\xd8`\xbd\x04~+m\x12\xff2\\\x04gM\x01A\u007f3\xfd\xe5aջV\xe4\x10\xe7\x16J\xb3i\xb4\xbf\x01\x00\x00\xff\xff\xf6\xdb\xdd\xf1\x99\x02\x00\x00", + local: "data/en/male_first_names", + size: 665, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zSSzY4qOwyE934r/gbUw1whQHfWhvZ0ckjbyJ2A8vanktHZIJF2VeorZ+BZFhosKJ3t +Jp7pK94DS6LvmFLkmbb8iiOd26mPtMFv6opFnoGuwWZecOpxyfYM4pjXCPmJS6Iv9gdtTTmNtBfzSehT +VCUHumR5idJufDfbtUduCfrkSnMwrRh9RaWBF1M45RzkTXv2Stc4Ww61h6AjO44G+flxqfThrA+63C1n +2nm8t3sQS2E6OvRnrrMp0rhM5t0iFIa8mWyRLS70zSkD5MQZBg86Sft3YDdk21qZEogPohBsUAatPIfi +dK6dYMLsYEJD4ZYd+lXqvQ6Ay6EdliWD69qv3Is35E+JrROey7/mBVETGj7y20XvQv9hA9auPlultegf +nuGy9oJva1CPaGk1YmGHXsiHywiSqvgKv/pbOB2tgBC4MldagQmZoa10sL6IXZkEkgZmuKosi6REa7vd +Kv0f79m8LbXl37nKkukUWtonXW0c4Yt52jjHCdhgvQR+K20S/zJcBGdNAUF/M/3lYdW7VuQQ5xZKs2m0 +vwEAAP//9tvd8ZkCAAA= +`, }, "/data/en/male_last_names": { - local: "data/en/male_last_names", - size: 1764, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffDU\xddr\xe2:\x13\xbc\xd7[\x05\xb2@%\x90P\x86\xfa\xa8\xefr\xb0'X\x85-qF\x12\x8ey\xfa\xd3-\xb297\x9b\xb5\xfe\xa6\xa7\xbb\xa79\x8c>\xf7\xee-\xf6!\xc5\xe0N~\x18\xbc\x8c\t\vA\x93[X\x9c\x82{\x95\xbbOn\x87-5\x9e\xe0\xc1]\x8c\xa6\xee(\xf3\x10ͽ\x84N\x8d\xab\xc7>\x8e\x82\xcb\xd2^\xebk\xbd\xcf\xea6b\xc6\xfbb\xd9?\x8fܸ\xb9\x16k\xbd\xfc,\xeb\xc35\xf1\xec+\x86\xe5 v\xc5gg\xfeR\xb0\xb1\xd5\t\u05f7\xaa\xee$\xc3\x15\x1062\f\xee\x05h\x82\xfb\u007f,\xe1\xe26jA\x80\xe1\xe1\xde=>O\xb8\xd8g\xb7\x8d7\xacl\x00\xdb\x1dژ\xb3[\x9b\xe2\xcaK\xc7\xfe\x16\u0097\xd61d\xc5Bv\a\tx\xf4\x01\xe6*\x1dM\xbc\x803רv8\x1a\xaf\\\xbfHp\v>\xb8+v\xebg\x80\xf4\x83ή\xf1w5\xe1\xa9\x1b\xaa4\xbe\xedY\x80p\xe3\xb7\xdbD\x96\x035\xf8爧\xa1\xda^\xf3S\x8e\xb5\tn\xcb\xe8\xd9ś\x8c\xd8;I\xe6\x0e\x84\x8d\xd7\xe4\xdeQl&2\xea\xe7\xf6\xe6[\x05\x80\x10\x14l\x9db\xec\x80\xc0\xe8\x83&\xa6\x04\x96\xffʌ\xd6t\x04\xd67\rW\xb6\b\x9alv\xfb8\x11\xfb6B\x82\xbd\xe4\x1f\f\x9br\xe9\xf1\xc2\n>\xa9\xe5S\x0f\x892!\x94L?\x1d\xfc8F\xbc\xb1\x8a)\xff\xa7\b\xad7KȐY\xbf+<ה\x94\xf8\xfe\xda\xfc\xd7\x17\x8c\xf4\xea\x05\xeaʌ\xb3\xbb\x99\xf0W\x11\x14l\xd0퐟\xbd\xf72\xbaC\x81\nЅ\xde\x19\x04\xed\xb1\xad*\x0e\xfe\xab)\xc3\xe8\xd6a\xfbs\xd2@5\xe6\x10\a\xec\xaf|\xea\xa9(.\xa7\x1f\x03\xf3M\u007f\xae\xdeo\xbb\x18d\x80nV\x1e4p\xea\xe9\xc8O\x18\xf9\x81\x06F\x8a\\\x8cܯ\xe08\x12u\x02p4\xaf\xe73\xfb\xad\xf6\x87-\xee,y,-\xbd\xb3\x8f\xd5y\x9b\x12\xea\x1f\x8f\x01\xc2\xf32}զ4\x80\xdfE\x9c;T{N\x9fU\x92ީU7S}SR\xf2\x8dM\b\x1ek+d\x11\x96M\xc0d\x1dK\xf62\xc1/\x03}\xd0P\xea\x1fcW\x95\xc0\xf5\x02\x04]1\xed\xc1c\x1a !\x0eZ\x1d\xfb\xe4>`\xba\x88\xbf`\x15\a\xdfC\x1d\xb0\x95ڥ\xf06\xec\xa1h\b\x91\x01\xae\xa6j\x89\xd7\x12\x02}Q?6\xa5\xda\xf5p\xd3\xd0Rcx\x95\x83\x04\nn=9\xd8ˌ\xab{\xafV\xfdG3\xed`\xa0^\xa7\xe4^\x8c\x8a\xa0\xc3Kx\xa6\x0f\x15i\x84=\xe7\xfa\xf8\xe7\xdf\xc95\f\x1c\xeb\xb6 \xfc\x10\xe6\xae&\x05\x06o\t(\xf0\x1cݰ0\xe98Q[A=\xa4\x96\xb1BS<\x8dd\x1c\xae\x15&\xaa\xa9C\xf7bc\xcaF//\xb9Ue9\xa9܉\x9f9\xa2xd26T]\xc2|Y\xf6\xd8~Pa\xc0.\x89i\xf7\x1c\xc5:gJ;H\xb8\"\x14x\x95\xa0W \x1af[\x97\x8c\xd6k\xd2\xcc\xc4\xde\xf6\xa3\xefrm\xc9\xfdO\xd2?\f\xc1\xa5\xe0\xbda\x88\xc8TU\xce\r\x8a\xddh\xadρ\xe9\x00G\x84|\x81\xf5l\xfe\r\x88\xdf0G\xa5\x9a\xefu\xea\x80\x00\x03\x03s\x98[\xc0\xe4\xf1\x06;\xb7qf\x8eh\x8dջ\xd8oJ\xd1\x19\xc84Xk\xf5\x1b\xb1P\xef!\xe4\xebN\"}\xc6\x14\xd3f\xb9zZ\x02\xfb\xfc\xb8\x94\x19w֊HS\xfe\x1a\xc43\r\xe9;\xe4\xf3\xe8V\xa5\xfe\x90lg\xe4\xa1{U\xe1\\\r4\"\x9f6FO\xc3F\"\xa7\x06'\xb6Rs\x04\xdc=\xf2\xdbE\xefB\xffa\x03֮>[\xa5\xb5\xe8\x1f\x9e\xe1\xb2\xf6\x82okP\x8fhi5ba\x87^ȇ\xcb\b\x92\xaa\xf8\n\xbf\xfa[8\x1d\xad\x80\x10\xb82WZ\x81\t\x99\xa1\xadt\xb0\xbe\x88]\x99\x04\x92\x06f\xb8\xaa,\x8b\xa4Dk\xbb\xdd*\xfd\x1f\xefټ-\xb5\xe5߹ʒ\xe9\x14Z\xda']m\x1c\xe1\x8by\xda8\xc7\t\xd8`\xbd\x04~+m\x12\xff2\\\x04gM\x01A\u007f3\xfd\xe5aջV\xe4\x10\xe7\x16J\xb3i4\xfa\x1b\x00\x00\xff\xffa\x8c\xf8f\x9a\x02\x00\x00", + local: "data/en/male_patronymics", + size: 666, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zSSzY4qOwyE934r/gbUw1whQHfWhvZ0ckjbyJ2A8vanktHZIJF2VeorZ+BZFhosKJ3t +Jp7pK94DS6LvmFLkmbb8iiOd26mPtMFv6opFnoGuwWZecOpxyfYM4pjXCPmJS6Iv9gdtTTmNtBfzSehT +VCUHumR5idJufDfbtUduCfrkSnMwrRh9RaWBF1M45RzkTXv2Stc4Ww61h6AjO44G+flxqfThrA+63C1n +2nm8t3sQS2E6OvRnrrMp0rhM5t0iFIa8mWyRLS70zSkD5MQZBg86Sft3YDdk21qZEogPohBsUAatPIfi +dK6dYMLsYEJD4ZYd+lXqvQ6Ay6EdliWD69qv3Is35E+JrROey7/mBVETGj7y20XvQv9hA9auPlultegf +nuGy9oJva1CPaGk1YmGHXsiHywiSqvgKv/pbOB2tgBC4MldagQmZoa10sL6IXZkEkgZmuKosi6REa7vd +Kv0f79m8LbXl37nKkukUWtonXW0c4Yt52jjHCdhgvQR+K20S/zJcBGdNAUF/M/3lYdW7VuQQ5xZKs2k0 ++hsAAP//YYz4ZpoCAAA= +`, }, "/data/en/months": { - local: "data/en/months", - size: 86, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xf2J\xcc+M,\xaa\xe4rKM*\x023|\x13\x8b\x923\xb8\x1c\v\x8a2s\x80\xecJ.\xafҼT \x91S\xc9\xe5X\x9a^Z\\\xc2\x15\x9cZP\x92\x9a\x9b\x94Z\xc4\xe5\x9f\\\x92\x0f\xa2\xfd\xf2\xcb \x02.\xa9\xc9\x10\x06 \x00\x00\xff\xff\xa4\x95F\xf2V\x00\x00\x00", + local: "data/en/months", + size: 86, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA//JKzCtNLKrkcktNKgIzfBOLkjO4HAuKMnOA7Eour9K8VCCRU8nlWJpeWlzCFZxaUJKa +m5RaxOWfXJIPov3yyyACLqnJEAYgAAD//6SVRvJWAAAA +`, }, "/data/en/months_short": { - local: "data/en/months_short", - size: 48, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xf2J\xcc\xe3rKM\xe2\xf2M,\xe2r,(\x02ҕ\\^\xa5y@\x9c\xc3\xe5X\x9a\xce\x15\x9cZ\xc0\xe5\x9f\\\xc2\xe5\x97_\xc6咚\xcc\x05\b\x00\x00\xff\xff\xc5\xed\xe490\x00\x00\x00", + local: "data/en/months_short", + size: 48, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA//JKzONyS03i8k0s4nIsKALSlVxepXlAnMPlWJrOFZxawOWfXMLll1/G5ZKazAUIAAD/ +/8Xt5DkwAAAA +`, }, "/data/en/nouns": { - local: "data/en/nouns", - size: 128, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff,\x8d\xc1\n\xc2@\f\x05\xef\xf9\xabZ\xf0\"^\xb4x_ڧ\x04w\x93%I\x15\xffެx\xca@\x867G\xae\x01\xa3Y[7\xb8\xab\xd1\xf5\xe3\x81F7\xc6;\x1fg\xdd%h.\x0e\x9a\xb6҇;\xb5^\xf9\xceI\a\xe3\xed\x81\xe6@\x96\xab\xbf\x02[\xa3b\xec\xef\x93\x0e\xde\xf2\x1b\x00\x00\xff\xff\x9e\xdfr&\xd7\x01\x00\x00", + local: "data/en/states", + size: 471, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0yQb2/CQAjG3/Mp+lUWzWbn1GV/NHuJLeuRXsEcV7X79OOqyZY05cdBHnh4iHjEAcGj +9R4S/6iU2KMYGiww8rcmYYSFRk3YqoMINZmbMcOSIl4wETx6kVuEJ9LUeffKn5mhbjEo1DGyKBvU0jK6 +fq0XhPVtxJokj00/wYuObHN5gyzk/zRFlNbBDJswGuVssOEmcIfi4HuYZu9ns/KdTjyzjslBJRexLR3T +bG5LZ2xLuFQrHE4W2Pcu2TMlo2nGDV250Rm/NPWw1ZRDtcCk7gDv6RL7MnUXWGHXR3foF9wl6lTglURs +imcsJ3sL2lJV2+ziXcf/Urf0LvVBxYoROV39Jp8ZA+wpDe4B9uwXLXIH9J2lyz7mQJarvwJbo2Ls75MO +3vIbAAD//57fcibXAQAA +`, }, "/data/en/street_suffixes": { - local: "data/en/street_suffixes", - size: 132, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x1c\xc9\xc1\n\xc2@\f\x84\xe1\xfb\xbcU\xa9\a\x11\x0fE\v\x9e\xc3:H0d!\x9b\xad\xacOo\xeb\xe5\x1b\x86\u007f2\xe3\xc0\xb4\xd1;1ӓ\x81Y\xa3\xd8\xfej\x8f\xc4\x1c\xb55\xf5\x17N\xa1\x1bqV3\\\xba\x97\xd4긊\x13\x8b\xc4\xfb\xcfGƾ\xada1)<\xfc\n\x96\xaa\x9e\xb8Uy\xe2\x9eA&VF\x1c}\rQ\xc3C\xc6/\x00\x00\xff\xff\xb0\xa40\r\x84\x00\x00\x00", + local: "data/en/street_suffixes", + size: 132, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/xzJwQrCQAyE4fu8VakHEQ9FC57DOkgwZCGbraxPb+vlG4Z/MuPAtNE7MdOTgVmj2P5q +j8QctTX1F06hG3FWM1y6l9TquIoTi8T7z0fGvq1hMSk8/AqWqp64VXninkEmVkYcfQ1Rw0PGLwAA//+w +pDANhAAAAA== +`, }, "/data/en/streets": { - local: "data/en/streets", - size: 4162, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffDW\xc9b\xea:\x12\xdd\xfb+\xfc\v=\xf7\xf6\x86$p_\xe0\x86\x86\xbcd-\xec\xc2ֳ,\xd1\x1ap\xc8\xd7\xf79%\xd2oA\xd5\x11\x1ak.\xff%\xe5毾o\xfe\x16\xfb\xe6\xefyl\xfe\x81\xdf?\xf1\xfb\x17~\xff\xc6\xef\xc7I\xe2\xd0\xfc\xe8&\x89\xcd\x0f7\x84ـ\xcd\x01\xe4b\xbd4?f\x89\xb63\xfe\xff\xa0\xfd\x91\xb0i\x0e\xdc\xea{\x89)`Ώ\xc6e0of\x13'\x02{Ŕ\x897\xe0\xbd|2N\u007f\xe2vi~\xa2x!a\xf5j\xf3\x9f\xccT^\x03\x0e\xb9\xe1gXL\xf3\x9b\xd1l\f\xee9\xb85\xbf\x89\xb7\x10\x80\x9c\xff\x84ѷ\x1fP\x91\"]X\x90\x90^\f\xfd\x02\xeay1\x8c\xa4\x17\u9fd4\xa1\x06p\x163\x90\x91.\x02\xa8\xef|\x81\x03\xf4\x82c_`\x8c\x17L\xa6J\xb5V\x01%\x8a\xfdb/\x8e\xbayA\xaa\xe6U/1\\\xce\xcdִ\xcf\xd0\a\x82C\x80'\xa9\xceA\xa4.A\xa0W|\x03$Ox6\u07b65Lq[S\"i\xdaxcE|\x8b\xc5|6op\xee\x96\x01\x95\x9a\xdf=\x1b\xea\xdf/\xa3\x99\x9b߳\x19\x9bwv\xfc\xbe\xa9\x19\xa2}\xe2\xd3\xde\xc5\xc2|\xefx\x03\x89\xb6\x89\xe0\x1e\xfb\xdem\x97\x99\xc1\x01z\x1d\xf2\xa3F\xbey[[54\x17\xb4\xc8\a\xfa,z\xe3\x87QS}\xb0\xab\f\xe4i\xbc\x17\xca\x0fZ,\x19\xf0O\x8d\xbe\x0fs\xab\xea\xfb\xb8\x17\xa3\x0f\x91\v\xbf\xc0\xf4s\x16#\xa7\x14\x8d\x19\tJH\xe5\xf7\x0e\x9aX\x05'\xd0s\xfe\x17\x00\x00\xff\xffT\xdd\xfd\xb3B\x10\x00\x00", + local: "data/en/streets", + size: 4162, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0RXyWLqOhLd+yv8Cz339oYkcF/ghoa8ZC3swtazLNEacMjX9zkl0m9B1REaay7/JeXm +r75v/hb75u95bP6B3z/x+xd+/8bvx0ni0PzoJonNDzeE2YDNAeRivTQ/Zom2M/7/oP2RsGkO3Op7iSlg +zo/GZTBvZhMnAnvFlIk34DxKAvuyfuAd0VzMGHBytF/B47Y4GZ8MlsTZpmw7TsWwhNADZJt4ea7Dksvs +262Yc/NgejEFzPc4GDyebqRecibP4iq3zuGJDyaN5wAdAFgHysW3ZHtpHkSFfxDrziUlAOeGGK6YsbEb +9eYHZ7rpZKMi6uXBFWkfcHa7p8Qc/sEzwVOWuXkIp2W0GQuD9zw9LDMEeQg3HBHFV4EeojWxXUXsIe4m +aPN+IDTgK1XxCh5F6k37Di0Z4NHx3OKyHlw8hGg3Vpf5XDdFbm4/9KpCpUK6krPEsxXX37EvuVkZZ40f +FNwuKYDPp2j7QYA87biCgiVWAI0bRyA6tKEz5BeIhSetTOpgnGZ1H45YgVesYoByV6PEMAlmR+tDmMih +6ZXDYXPwuSLfw2Qrx3+wxQVdceulXRvnzDDy2NDj8oA1kB48RNMHgjKfCjbBkX03CgE8t7N8cKBe8CrF +wVXxAuTiCbEX6ICAQoaYuoDXhJyDV1vRSh02t69mSjrK7ZauAMEWR03QWBC2z82jgXFApwBLPRpEEmhc +lF1tD7oQ3mDISI47mkc5RUOaQDpowWSrf7t2x1Xgx+DIzQIVETiIjJgDRMBxW5QJ9JNqf7TtNkTJAehq +kx5lP0mDVFvQRR4RgXCExxD1CZDW4mToOxtEyWOUBcp4jFA9ZsuEueLVIR8XO4y5eTID1A/q5O7GT+ZO +HGUkUO09DQOsinBsntwAcZ6cDcSTAZk1Dp9gKPwV8YKn1I0gDMsnJBKGNPkQBe94+rzgptQ8GxurMYiq +RxNdrSwAzt1BnLtAFs0ATwdYGEvPXJ8gtQCmqXmGB4lH8nmmJ8xkFKey9tE4+caH4gkTtfx899rn4hiN +YNTjmqvXuNEmHWVZkBvWEqnrNYKnWSOf2O94XTuqhluCg6JrfgOupF2FEpNU/E6R1lCoQ95r1tF08o0E +/kvukQfBUprMfCG6jWaZAKg7pe1BPX8d7QwCY8dmXVwSpPSNQSLeqFE30CATxsZ4XQJOaSrj3/EEryG/ +6GyZQK6Ig425Cee/xHWqw40YHi3nM5INTxYIbMCQ8MnhSX965Mb6/CXNJiCQQOVCJ9iE85lxvgl80/39 +GMxavABu9/SyCbOov22QW3TjFZ61Kb0+vXwyTn/idml+onghYfVq85/MVF4DDrnhZ1hM85vRbAzuObg1 +v4m3EICc/4TRtx9QkSJdWJCQXgz9Aup5MYykF+m/lKEGcBYzkJEuAqjvfIED9IJjX2CMF0ymSrVWASWK +/WIvjrp5QarmVS8xXM7N1rTP0AeCQ4Anqc5BpC5BoFd8AyRPeDbetjVMcVtTIjxmyzDdSuyRssgDZiw8 +Zcv4HkNJKHOG/zlWCHDfU+mjIl2XM4L/2UmJzRb2QhnDZDjnNEAGvHYb6E7bwKTeawkBHjQ4tyGg5oOh +R7jiBghS+ruGtmWaeH7hJjCNt+2Nvrcz3WWsrcfODMzbMOgOdRkESRGaIw+4aQdNRMhPYHNYLJoXQLoB +WDmbLkMLkUdenFRa6yVybsdFqF2YRxBeOR3/W1TfQDfV8g7OHklr/gFQne86Vk+s67oAL+8moKFYpO2d +IGl/u/B98M7g/xPr68SdlLLMgcG7uQQ5DUIi50QWtB0LJSoMeEAaslyBjsUgIQFEvVYVvkO+hBTdONue +c2wgdrCTpWV29nx2PNZqDgNbEMwo0TubUUHh4rvQTbCK9j+7UOXGdaj6YJkBQi5sBwDKLHxA0BcHbUG+ +udY7YFRKMMQCbwk1ae6gnmZ3i/Cm5peZZTID/v2FKn5rfomjsX/J1fQGbGlXrDBYGE7w4V9IRGOl1QwK +9Z2KLkxUimpLo1AdUNHCli16DpCn2+oKv8LVkFCJKDL8fdsGsJ7zOtrQvDpGFnyC4DiiRjSvXpjXX30a +6Iyv8CESNCvN66dG9t6w50zgA2re3vgJ5f6rYevXVkdQrHVxbxaN/r0Ydfk9skm6uSs82mBwQfqtLrun +a0ZcskdpQWmL5zOgvyeGvROT4OzNHmEIEjPuVg6j7yMKp5X2QKPdB6qgPXtV9uT/KZaWOJg5CZnvSa+I +0IP0LXq00hMtfOlBkBuYTwgQfOrsLNUV6cGKWBYPVhjgBzt4HqwfDhT7AKeTs6hPHrRNaQ9Cfz3w2+OA +nov2PYTPU4GHHwpqOAlUDZbotocCF6GdDjdsO5puTErzH8IhJo7IGRkNd3GABekOGjsiLPRSAGfngWsR +OHgkUzEgOkeyEr/AQnU4APQooDWLHQVdCJR2HA1D7cgognDgcByeAqCnjeEyBbI0shM5usB/tWXFWwOe +VGn1t+PFaNd1ROFKfOEFtQc0at2oXJV7RFAOpFE955hR9ZPqCxCpE5vY+SCrRX6cYFBwbuDf0RSG1DEX +NmvHwmbtiO7GXvmywpfdk1cd1PsALVf7U2RTD9Dz+wX8rh+0jfVr61jgrzbw0MiEcSxJD0YFiPWF+lFS +b1i0B2mOt87MDKw3fKZoRQSYDZe8sbTC3BXdGB9v8okm5m3UEIODvY0IB0j5Nob5ogvCiUeEWVv8t+Cx +Bq/FEXB8l+iUQD5p2nhjRXyLxXw2b3DulgGVmt89G+rfL6OZm9+zGZt3dvy+qRmifeLT3sXCfO94A4m2 +ieAe+95tl5nBAXod8qNGvnlbWzU0F7TIB/oseuOHUVN9sKsM5Gm8F8oPWiwZ8E+Nvg9zq+r7uBejD5EL +v8D0cxYjpxSNGQlKSOX3DppYBSfQc/4XAAD//1Td/bNCEAAA +`, }, "/data/en/top_level_domains": { - local: "data/en/top_level_domains", - size: 37, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffJʬ\xe2J\xce\xcf\xe5\xca\xccK\xcb\xe7\xcaK\xccM\xe5\xcaK-\xe1\xca/J\xe7J\xcf/\xe3JM)\xe5\xca\xcd\xcc\x01\x04\x00\x00\xff\xff\x04\x1a\xcc\xeb%\x00\x00\x00", + local: "data/en/top_level_domains", + size: 37, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0rKrOJKzs/lysxLy+fKS8xN5cpLLeHKL0rnSs8v40pNKeXKzcwBBAAA//8EGszrJQAA +AA== +`, }, "/data/en/weekdays": { - local: "data/en/weekdays", - size: 57, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\n.\xcdKI\xac\xe4\xf2\xcd\aS!\xa5\xa9\xc5 :<5%\x0f\xc2\n\xc9(-\x023܊2ATpbIi\x11\x88\x01\b\x00\x00\xff\xff\u007f&+w9\x00\x00\x00", + local: "data/en/weekdays", + size: 57, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wouzUtJrOTyzQdTIaWpxSA6PDUlD8IKySgtAjPcijJBVHBiSWkRiAEIAAD//38mK3c5 +AAAA +`, }, "/data/en/weekdays_short": { - local: "data/en/weekdays_short", - size: 28, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\n.\xcd\xe3\xf2\xcd\xcf\xe3\n)M\xe5\nOM\xe1\n\xc9(\xe5r+\xca\xe4\nN,\xe1\x02\x04\x00\x00\xff\xffܹ\x9c\x9e\x1c\x00\x00\x00", + local: "data/en/weekdays_short", + size: 28, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wouzePyzc/jCilN5QpPTeEKySjlcivK5ApOLOECBAAA///cuZyeHAAAAA== +`, }, "/data/en/words": { - local: "data/en/words", - size: 1685, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffLU\xdbr\xeb0\b|\xe7/\xb1D\x1bft;B\xca\xf4\xf3ς\x9c\x8c_:\xb1\xcdewY(\x17e\xa3ԛɿ\xcdkO\xe2\xbdh\xc8\xfc\x91)-\xab\x91\xe9\xa2w/{,^R\x89S\xda\xc6m鮔{\xe9S\xea\xbf-\xc4HQ\xae$\xecO:\x8c\t\xf5\xf0\xfe\"-\xa5\x93\xb6\xb7\xb4\x85hz#\x10\xa5PY\x96ǘ\x12\xcf\xf4\xd2%iu\xba\x84\x17\xd2\xde\xea\u007f\xb3\xa6\xc5d\xbb-\x92\xbfQ4\xf1Չ\r\xad\xda\x17j\xcf\xc0\xe7?~\xf6/~\x99d\x14U\xfePB.\x02+\xff6\xbd\xe1\xa2o7\x8f\xa1\t\x14\xbdɓ\x9d\xa7(5\xb1\xa4\u07b5\x89\xb3\xb9i:+\x90\x8e\xea\xf1*\xa4\xe1\n\x1a\xd1,-\tPY\x87\"\x1fD\xcb\x13P\xeb\x8dچX\xae\x92n\xa3\n脦\xa3O\x86>I\xb3\xb7\x04\x93\x02\x9a\x10\nuO瀏,\xcc*\xb2]X`\u007f\xe2F\x964EH\xa6\xaa\xf8\xc1\xe8\xde4b!t\xeb\xb6&\xa0˟\xcc\x14\xe2\x836\x92JAD\xea\x13\b\b\xdc\xcf\xc7\x11\xb6Aq\xe8\rV\xbb'4\xc5,\x81$pjF;\xd8\x01\xf5k0}z,Pah(\r\x95H\x80M7\x88N\x19S^\xf0\x9d{$f\xa4\xcdk|\xa1ܢ\x8a\x99Ph\xd1\xf4\xa5\x05R\x16\xb1\xa5\x1c\xa2A[\x18\t-;\f\x84\xb9\x9bi\xc5\xc4\xf3NZ\xf7\x99\xfcU\x18\xde^\n\x14c\xb2\x98\x1c?\x17\xde\xf9\xb6\xf6\xea\v\xd5}\xea\x9f\xde\xeew)\xd0g\xc1\xb0\xcb}\x01\xe5&>)Jz\xfd\x8f\xbb\x8e\xab\xbf\x98\xf0\xe6/\xc9\x00m\x85r\x98pO\x89%a\b\x94\xf6Ь\xc1\xcb\xdd1f\u007fk\x06\x960\xcdYC\x1b\x9a4\xb6eC\x15\xea\x15|H\xcd3\x00\t\xb5\xe7\f#Vu\xd1\xe5,\vDK\xbb\f\x0e\xae\xfd\xe7\xc7K\x00\xbc\xc9\xf4\xaf\x00\x06\r\xf1\x861k(\x8cA\xd9=G\xf7\xc8\xed:\xfc\xc4F\xb1?\xbfx\x1e\xdfgqI\xe2\x13'4\xb4Ȕ\xd8Nq\"\x10\x1c\x94[\x82\xc1\xc8\x1d[\xf4\x92\xd9o\x93C0d\x1a\xe4\\\xbe\r\xd7'\xbd\xe8\xaf_\x1a\xea\xc3\xd3Ҏ{r\xe6\xaa5\xea\xba\xc0\x84\n(\xe5\xce9+d\xc7 \xb0;dP_\xb2\x0e\xf3\xf3\x9fV\xa1Q8\xe1\x908L\x9c1\xa4\xba\a\x10v\xe4\xfb\x1a\x99\r\v\x8d\xde\x1c\xd5\xcedz\xd90\xa2\x14\f;#\xe9\xa0\xd7k\u007f,\x8b\xb6x\xc8\x1cb\xf9\xe9yZ\xdb\xfd\x8c\x8bw\x04\xfb\x9e\x0e9rb\x92\xc1勠\xf9\x0e\xd2`\xdcθ\x1d\xcb\xcfc\x8f\v\xe5\xb5\xe3\xd6\x06\xf0\x18\xa2ÓK\xd7Y\x9e{\x14M\x12\xd6!\xb6\xda!\x1a\x03:\x89\xaf\xbf\xc45\x91ǡ0'\xb6\xb3\xc2\xfdؕp\xa3\xac\xc7\xf6\xb8\v\xa7ā\xf7\x00\x14\xf5YH\xcc\xfft{i\x82 \xed\\:4\x1b\n\xbfJlFr?\xeeuC\x03\xdc\xf3\xff\xe3\xd3<\xd0U\xd6X\x92\xd0\xe5H\xea\xe7\xfc\xbc<\xa2C\x83\xff\x01\x00\x00\xff\xff]\xcec\x0f\x95\x06\x00\x00", + local: "data/en/words", + size: 1685, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0xV23LrMAh85y+xRBtmdDtCyvTzz4KcjF86sc1ld1koF2Wj1JvJv81rT+K9aMj8kSkt +q5HponcveyxeUolT2sZt6a6Ue+lT6r8txEhRriTsTzqMCfXw/iItpZO2t7SFaHojEKVQWZbHmBLP9NIl +aXW6hBfS3up/s6bFZLstkr9RNPHViQ2t2hdqz8DnP372L36ZZBRV/lBCLgIr/za94aJvN4+hCRS9yZOd +pyg1saTetYmzuWk6K5CO6vEqpOEKGtEsLQlQWYciH0TLE1DrjdqGWK6SbqMK6ISmo0+GPkmztwSTApoQ +CnVP54CPLMwqsl1YYH/iRpY0RUimqvjB6N40YiF067YmoMufzBTigzaSSkFE6hMIPEpqP1V8fPVZPgjc +z8cRtkFx6A1Wuyc0xSyBJHBqRjvYAfVrMH16LFBhaCgNlUiATTeIThlTXvCdeyRmpM1rfKHcooqZUGjR +9KUFUhaxpRyiQVsYCS07DIS5m2nFxPNOWveZ/FUY3l4KFGOymBw/F975tvbqC9V96p/e7ncp0GfBsMt9 +AeUmPilKev2Pu46rv5jw5i/JAG2FcphwT4klYQiU9tCswcvdMWZ/awaWMM1ZQxuaNLZlQxXqFXxIzTMA +CbXnDCNWddHlLAtES7sMDq7958dLALzJ9K8ABg3xhjFrKIxB2T1H98jtOvzERrE/v3ge32dxSeITJzS0 +yJTYTnEiEByUW4LByB1b9JLZb5NDMGQa5Fy+DdcnveivXxrqw9PSjnty5qo16rrAhAoo5c45K2THILA7 +ZFBfsg7z859WoVE44ZA4TJwxpLoHEHbk+xqZDQuN3hzVzsez2TCiFAw7I+mg12t/LIu2eMgcYvnpeVrb +/YyLdwT7ng45cmKSweWLoPkO0mDczrgdy89jjwvltePWBvAYosOTS9dZnnsUTRLWIbbaIRoDOomvv8Q1 +kcehMCe2s8L92JVwo6zH9rgLp8SB9wAU9VlIzP90e2mCIO1cOjQbCr9KbEZyP+51QwPc8//j0zzQVdZY +ktDlSOrn/Lw8okOD/wEAAP//Xc5jD5UGAAA= +`, }, "/data/en/zips_format": { - local: "data/en/zips_format", - size: 8, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffR\x86\x00.@\x00\x00\x00\xff\xff\x87\xdd'=\b\x00\x00\x00", + local: "data/en/zips_format", + size: 8, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1KGAC5AAAAA//+H3Sc9CAAAAA== +`, }, "/data/ru/characters": { - local: "data/ru/characters", - size: 119, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x04\xc0U\x15\xc3\x00\x00\xc5\xd0\xff\xa8\x19\x83\xbb1Ù\x931\xb7\xb5\xf0\xe2\xa87gr!Wr#w\xf2\xc0\x13y\x92\x17y\x93\x0f\xf9\x92\x1f\xf9\x93\x82\x94\xa4\xc2\x11\x8eq\x82S\x9c\xe1\x1c\x17\xb8\xc4\x15\xaeq\x83[\xdc\xe1\x1e\x0fx\xa4A\x93\x16m:t\xe9\xd1g\xc0\x90:\x00\x00\xff\xff\xb7\x8c\"\x8ew\x00\x00\x00", + local: "data/ru/characters", + size: 119, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wTAVRXDAADF0P+oGYO7McOZkzG3tfDiqDdnciFXciN38sATeZIXeZMP+ZIf+ZOClKTC +EY5xglOc4RwXuMQVrnGDW9zhHg94pEGTFm06dOnRZ8CQOgAA//+3jCKOdwAAAA== +`, }, "/data/ru/cities": { - local: "data/ru/cities", - size: 2271, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xfflVir\xf2F\x10\xfd\xcf)\xb8\x00wD\xe0\xd8N\xe1\n\xf1Vv\xe4\x05\x03\x95\xf2\xaf\xc4b\x11\x8c\x85\x90\xaf0s\xa3\xbc\xf7zF\x88\xd4\xf7\x8bަ\x97\u05cb\xf0\u007f\xfa\xad?\xf82\f{ A\xf8*d\xbe\xf0G\xbf\rC\xdf\xf85\xc5G\b~|\x01\x12\xb2=\x98\xda\x17!\x13\x1b~\x93\xf1\x06\x0f\x0f\xe1\x06O\xab$vx\xd2\f\xfc;d\"\xfd\xdaW\xe6#\v#\xf8)\xeci\xb8\xe9\xf9[\xbc\xde!\x87K\xbe&s\x80\xc3F\xf1\xb7\x14\x18\xb96\xef\xb7\xf0>\xc5;1wpq@\x05\x85\xff&×\x0ea\x9c\xff\xee\xfb7\xc5\xec8\xfa\x9f~\xa9D\xfe\xf0\x1bi`T\x86)\xc9\x03\xbcma\xb2\xc6KX\xe0m\xd5\x15\xd7\xde\x11\xac;ȕ\xa6߰\x18\xf3O\x11\x04LH\xac\"\x1fY\x1d\xd80\xf1+\x89\x18\x10%\xec\xc3\r\x81\xec\xf9{\x15\xe1\u0095H\xe4t\x850GӔ\xea\t\xba\x01\x80\x1c\x13\xb9O\xf5\x10\xaf\x96\x05\x96,V\xa2\a\xa58J\xed{\bcĕ\xbbGC\x03q˄\xe6\xa3\xffND\xc5\xd8\x02\x82\xd1Wal\xa9>\xaar\xb0x\\\x18\xab0O0g\xe1\xf1\xfd\x13\xc3\xe3\x9d\xeb\"\xfe\f!ǃ\xb95dw\xa7\xc8Ϙ$\xe1a\xec_ \xaf\x95\xc3\x10CØ=\x9f\xe3\xf1>\rIn()\xc4\xf1\x04\xba\xc4)9c\x00-m\xc4j\xfajC\"G\xf0Z\x05\xc6|r\xea\x90\xc0\xc4H4\n)\xd4\xe6\xc8\t\x87\x83\x1a\xbaN\x82\x96\xccL\xce*-\xfd\xdcr#\xc1ImM\x1b\xe4\xd2Y\x8d<\x8eHm\r\xc9m\xc4dnq\xb5\x18\x19\xb5a\xda\xd7ڰ\x9e㹎\xdd/8\x84\x1dQ\x98&$s\x9b\xbap\x8dn\x02\xa20\xa2h\x9c\xb4/\x86)\xc7\xdd:\x01ےb.i\\\xc1\x17\x98\xdb@\xb9pIt^\x85\xbdb0cMD\x9c\xb6W\xd8\xedNc\xf0*}ž\x83\xd1\f\xd5\xea\xa0i%@\xad$/9/I>A\xb2.\xfc\xee\x9d1\xd7ZR\xc0\xf9\x86\x9f\x9dz\xfe\xab\x8d>\xd3.\x10gÞ\xf5\xa2\xa1mF\xa6\x11\x88\xe9%\x05E+\xb6\xd4\xc4\xef\x18\x03# \xb9\xa5\x87w\xad~\xa1D\xd4ʙJ\x8e]\xef\xb3#}<\xab\x88\xddL\x83\xbfgųxH\x12Dh\xfc\x80\x9b\xa2\xa5Ʉ\x8c\xe3\xa92\xbb\x9asM\xd2֎\x85]D\x81*\xdc\xcbG;c3\xf3B\x82\x13МƊ\x82*\r\xdd,vU\xe4\xf8\x04e\x87\x89\x89\x94\xfdx\x10&\xd4Nق(\x90\u05cf\xf6\x00\xae\xfb\xe7\xc7\xf3L7 \x18\x03\x9c\x1d\x0e\xdd\x18*l\xa3\xc0\xf8\xd0\xc5s\xa9\xc9\x1fZ̸\xcd\xf3\xf8\x15\x19\xd2p\xae#Q\x85Ѡ\x83F{\x80\xe6\xf1\xd0D7\x89\xfdA\x98C\xcbZ*d\xd7\xf2`w\xb8-e\xcei\xe7\xaa\xc8\xce\xd6JY\x18\xee\x8e\xea>a\xd4\xc7o\x9b4?i\x11(\xa8\xb5\xbb\xe5)\x8f&\x02R\xa4\xe9\x99\xc7\xed\xe6\x97Ή\xe5)\a!D\xb6:N\x88j\x83ʂر\x8d\tꄌ1+\x8b\xba`uH\"#L\v\xd564\xa3F&\xed\x04,\"\x83&\xb2\x8d&\xa8[\x1d\"\xed\xecCFf\x94\xbe<\vb\x18\t]\x8bRA\xf1Q\xacU(\"-\x91j\xfc8--\x82\xddss\xbd\f\x17|\xfe\xb7\x92\x1f\x85\xc9@\xa7\xe2\xd8]\xb9OxZi>3\x1531\x11\xcfZg8>mq\xe2\x1f\x05]\x96\u007f\x14Wk\xd8\xf3\xff\xa6\xcf\xd6@\xc3\x1e\xeb\xb6Y\xfc\x02+\xa3\xaf\xb3\xf3D\xac\xff\v\x00\x00\xff\xffL\x92o\xa5\xdf\b\x00\x00", + local: "data/ru/cities", + size: 2271, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2xWaXLyRhD9zym4AHdE4NhO4QrxVnbkBQOV8q/EYhGMhZCvMHOjvPd6RojU94veppfX +i/B/+q0/+DIMeyBB+CpkvvBHvw1D3/g1xUcIfnwBErI9mNoXIRMbfpPxBg8P4QZPqyR2eNIM/DtkIv3a +V+YjCyP4KexpuOn5W7zeIYdLviZzgMNG8bcUGLk277fwPsU7MXdwcUAFhf8mw5cOYZz/7vs3xew4+p9+ +qUT+8BtpYFSGKckDvG1hssZLWOBt1RXX3hGsO8iVpt+wGPNPEQRMSKwiH1kd2DDxK4kYECXsww2B7Pl7 +FeHClUjkdIUwR9OU6gm6AYAcE7lP9RCvlgWWLFaiB6U4Su17CGPElbtHQwNxy4Tmo/9ORMXYAoLRV2Fs +qT6qcrB4XBirME8wZ+Hx/RPD453rIv4MIceDuTVkd6fIz5gk4WHsXyCvlcMQQ8OYPZ/j8T4NSW4oKcTx +BLrEKTljAC1txGr6akMiR/BaBcZ8cuqQwMRINAop1ObICYeDGrpOgpbMTM4qLf3cciPBSW1NG+TSWY08 +jkhtDcltxGRucbUYGbVh2tfasJ7juY7dLziEHVGYJiRzm7pwjW4CojCiaJy0L4Ypx906AduSYi5pXMEX +mNtAuXBJdF6FvWIwY01EnLZX2O1OY/AqfcW+g9EM1eqgaSVArSQvOS9JPkGyLvzunTHXWlLA+YafnXr+ +q40+0y4QZ8Oe9aKhbUamEYjpJQVFK7bUxO8YAyMguaWHd61+oUTUyplKjl3vsyN9PKuI3UyDv2fFs3hI +EkRo/ICboqXJhIzjqTK7mnNN0taOhV1EgSrcy0c7YzPzQoIT0JzGioIqDd0sdlXk+ARlh4mJlP14ECbU +TtmCKJDXj/YArvvnx/NMNyAYA5wdDt0YKmyjwPjQxXOpyR9azLjN8/gVGdJwriNRhdGgg0Z7gObx0EQ3 +if1BmEPLWipk1/Jgd7gtZc5p56rIztZKWRjujuo+YdTHb5s0P2kRKKi1u+UpjyYCUqTpmcft5pfOieUp +ByFEtjpOiGqDyoLYsY0J6oSMMSuLumB1SCIjTAvVNjSjRibtBCwigyayjSaoWx0i7exDRmaUvjwLYhgJ +XYtSQfFRrFUoIi2Ravw4LS2C3XNzvQwXfP63kh+FyUCn4thduU94Wmk+MxUzMRHPWmc4Pm1x4h8FXZZ/ +FFdr2PP/ps/WQMMe67ZZ/AIro6+z80Ss/wsAAP//TJJvpd8IAAA= +`, }, "/data/ru/colors": { - local: "data/ru/colors", - size: 216, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffD\x8e\xbd\x0e\xc20\f\x84\xf7\x8e\xdcF\x0e\x1e\xfa\xa1\xdd\xe6\xfbQc\xa4-6\xea\xbb0MU\x8a>\xba\x16\xb4\xc5Rl\xa1\xe2eJ\xf8\xc0\xf8\x03s\xee\x8d\xcb\xc9\xe2\xfc(\xcd{\x03\xec\xd1|K\xa5\x1e\xbd\x8c\xa4;\x89\xb3\xf1\u007f\xcc\xe2\x94,{\x02\xc1\xccxT\x8d|\xa2OE\x00E\xfb\xd7@t\u007f,\x95\xd5>ז\xe4\xa7&Q\x18\x81\xa9\x99\x03\xbe\xf2H\x96>*G\x06\xb1\x9c\n\xdbVC\x0f(\xdba\xddbO*\xcb \x1a,\xb7\nl[s+1\xb49\xc7f\xb0%Ă\xb9\xb4\xc1\xaa\x9bўk\f\x99\xf2N\xb2\xf8n)O\xc9^\xb1\xcaZ\x9c}c\xc2rk\x11\x94E\xb6t\xe5\xff\x14'\xa2\x92D\x0e5\xc3b\x8e\xf1\xca2ѣ\xd2\x03B\xe7\x98\xd7\xf4\x99K\xad\x93\x932Γw%\xc0ka%\xeb\x15ԕ\x8a2\xe6a\xb9\xd2\xecԿgȆ`\r\u007f\x00\xd7\x15\xea\xa8\xf1}J<٨\xb0P\x19Y\xa9(\\#z|\xc3\bx\v|7\xab\xbf\x9bO\xbeK\xaf\xcaܗ3\x80\xe0E\xdeF\v\xe5\xabw\xf5\x8f\xdd\xefNP\xd6\xe5\x95\xe8P\x1d\xbf\xb2\xbe\xf5\x86\xa5W:N\xea\vE}\xb2\x86\xd2\xe6͚\xb2\xfe'\"\xf5\xd5\xca\xd1x\xc377\x82<\x1b\xf97\x1aȒ\xcb\xcf\xfc\x13\xfb\xa1\x94ۛ\xdc\x1f\xb8\x97\x9f\xfe\x1b\x00\x00\xff\xff\xf3G\xd8e\xc2\v\x00\x00", + local: "data/ru/countries", + size: 3010, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2xWWXYbtxL95164Rw6Wn86RX2QNObZJMSIlJdaP4maTMMGhm1tAbyEryb23Ct2t43wB +dQHUPCB9TmUzbibNKBXpmGJzPehBTu5SALHGjX3app9YK8JHQVW+dcRJbEbcVmmTagCFEdtUNyNKENlM +UkybZioS6CYFB6sMnQg53+YDbpgYKGWyb7AQPDVXRlAgxEFSaC4FucIUPTbgAlCABXofcJ1KTcF0bJIM +jGnn2+YTmLYnFfXjlnZtxN/Par0qWxL8qo6YgCylIWy7kZt3uO6uvqEKOINeJKY4P5gjhukFQsapdlzX +tika6X645UJPQsyUpFlwgE5rKTjpAnQrIzZZbyMDzJ82/7dQ3VJ3PKmb/4HrFVW6hRMCoIrOHqQ7LGsw +r2xL/tG2+2wiiRMuSchdh5ZUEjJPyjOHolS4fkcM4TaEGtenxIPSobXijtLTVp4qGNk7RbVSqAsnm49+ +WW7bGXHfMblnpsJDU9P/HjxPEk/XFb8AcMaYK5/+zpxIZzplkL70bf0C/KScW8OYMEhf007hjkwlkoof +r9q2Vtx3GUI20oSs41e9PeRNZZujLmQ2UOsX4NxnMemK+pt8H8hoZlEcMgckNBi2U5G0RTZz62qr+QwE +y0UjW7/PFN6C5T/rindGXxkWVekx22tApL8sCLO0SEsuKCfwb906UyxYqij1JRMWHKc4PXbRomV1Oigl +wAzpG7qIkfE9Wf/n45nnPOpt2ccmw7T9Z/QNcSlVX7RBLwvblCxZ5sAcHlCLmUu4t4G5ZNUsJhK0M+TK +m6tbyMXzrnHMVU0l+XN7oWKpmkutalrz5jfYOJa1axXAZpAewKiUJ9k39j2gX/sPFib1LXPMyMADuFkm +tveYUSUjkol9jpkB+QSdYUv1GRcHKFIE5CMe7ENONpd6i56bHwTZ4h5/AL7LxcSkf1BX3ZoqJrtWsjnL +uh0xdgrZ14BOZLYQo5gTaMFOwpzlNqg+jtxGDh76od3m+1FjpC026rswTVWKProWtMVSbKHiZUr4wPgD +c+6Ny8ni/CjNewPs0XxLpR69jKQ7ibPxf8zilCx7AsHMeFSNfKJPRQBF+9dAdH8sldU+15bkpyZRGIGp +mQO+8kiWPipHBrGcCttWQw8o22HdYk8qyyAaLLcKbFtzKzG0OcdmsCXEgrm0waqb0Z5rDJnyTrL4bilP +yV6xylqcfWPCcmsRlEW2dOX/FCeikkQONcNijvHKMtGj0gNC55jX9JlLrZOTMs6TdyXAa2El6xXUlYoy +5mG50uzUv2fIhmANfwDXFeqo8X1KPNmosFAZWakoXCN6fMMIPHn2I0BPLi9KBb5Sa2JMp0bo26Stvha9 +j5WgPCmf/Y+lHHmG2DULtK/es/XX/Et71hRoc/NFfSTkDgyYH4jAg2jG2vao4XlWcK8MqqDsdTfDXmzc +ZcX+9NKyxg7gL4u7/VfhYUalaD54C3w3q7+bT75Lr8rclzOA4EXeRgvlq3f1j93vTlDW5ZXoUB2/sr71 +hqVXOk7qC0V9sobS5s2asv4nIvXVytF4wzc3gjwb+TcayJLLz/wT+6GU25vcH7iXn/4bAAD///NH2GXC +CwAA +`, }, "/data/ru/currencies": { - local: "data/ru/currencies", - size: 4636, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x8cX]\x8e\xdcD\x10~\xefS\xf8\x02\xb9\x06\x8a\xe0\x05!x\x80\xd3\xcc\xcf\xeef\xa5\xec2\vBB\n,\xcaF\b\xf1\x12\xe1\xf1\xd8;=\xb6ǾB\xfbF\xd4\xf7U{\xdc\xedm/(\x0f\x99\xb8\xbb\xab\xab\xbe\xfa\xea\xab\xea\xb8\xd2\xd9a5\\\xbbܵ\x99\xfb\xc3=\xb8\xcf\xc6\xe5Õ;ȗ\xf3\xb0v\xb5\xb3\xee\x94M\x9f\x9c\x95u\u05f8}\xbc\u07b8\xca\xd58\xb9r\xed\xb0\vWJ\xf9$\xc6\r\xf7o\xe4[3\xdcM\xab\x87a\x8b\x0f\xe2F\xe5\xce\xdc#\xd7t\x97=\xf9\xb0\xcb䯂\vG\x97\xeb\r\al\xa6-\xbd\xa7sU\xe6zW\xc9?:\xd8(\x86\xf5\xb0\xe1\xb5\rn\t|\x81i\xf9#F\xb0\xef(GV\x8c\xe4$K\xcfqD-\xeḟ\x8d\xd1X\xe5V9\bG\x87ۋo\xe2D\x8e\x9f\xd8\x03\xd3\a\x98\x8eQ)x~\xb8\x96\x9b*\xb9'D\x06\x01\xa8/\xfba+\xe7\xb6\xf2\xcf2\xf2x\xb8b\x18g`\xbb\xf7;\xaaň\xd4\a+pEQ\x87\x9fa\xab\xa3-\xc6\x1fg\x83.\nh\x1a1\xd2\xdd.\xdf$\b\xaf51S\xa6zdSѨ\xe4G\a\x8f%\x17\x93}Y\xdf\xe3J\x83\x13\b^葾\x01Y\xf5\\\x10[\xc7\x14\"í\xdc\x0f4n\"\xd4\xc3\x1d\xef\x10\xe1\x05\x8d\x98'\xb2\x9b\xe9\v\xd0\xfe\x91\xe1\xdc\xe9\xed\x8d8ۊ\xbbK\xa7;\xb0\x8c|\xb4\x1a\xcd\x14\t\x8f#\x00\xd9ǐ\x93L\x15\xefB.\xc9\xd6\x15\x83\xce\xcd\x14B\xe6~\x11bZ\x12d\x83\xda+A\xc9\xd4\x19\xb2\xfd\x99՜`\xd8pOo\xbb0[\xc1\xd9J\x90\xb6tl\x13\xe2\xb8E\x99\xe1\xec\x95|\xe9$\xbd\x13\xa7\x86\xf7Ȓ\xd0\x1bFL\x98\xbb\xcc\xfd){PO\u058c62ގjk\xe8\x12\xf2Zd\xee\t\x80x/\xa5\xa4\xc1M,\x11@:\xc7\x02\xe2\xd9\x02n\x1eȠ\xe3\x05N_d́\x99I\x96\xfc\xa0i\xfd\x1e&\xd2C\x93\xf3\xe4Zw\x14އt\xe9a=G\x00T\x85H\xc0jbv\xa3\x9f\r\x03;\x8f\xe4]\xa0\xb6\xee)Q\xf2p`JH\xc3\vz\xe4\x10$\xb8&\b\xc5<\xe1[MYA\xc4\x0e\x005\xf0\x99G,!\xcf2\xf7sb\x0f\tq\xc3|\x9e\xd5k\xd9\xfd^uB)\x97\xbd\xfd\xee\vC+V\xdd1\xa4l\x87NY{\xc2vZE\xa1\x95\x15\xef\x17,q\xff\xe3\u007fe\xd2}\x88-e\xd9Wo\xbf1\xac\x8c\x82\xd5\xd8\xf9J\xab\x82\x8c\xc8R7R\x8c?2\xf7\x91\x8aիzS\xee,l\xf3$\x12\aR\xaa\x14o\x92ɫ\xd9l\xd0\x04)\x99a\x1a7#E\xff_@\v\x9e\xcc\xccK\x9c?|K\x8c]\x9f\xb9\xdf\xe4S\xe7묃\xb5G\x11Տ\xc6\xf7\xc4ț\x8b\xe4\xdd\x02\xe97\x9eW\xf5\"c\x1b\xf6\x10\x94@ G\x163CC\xc1\x98u\xe2F\xe7\x89D\x8f\x0e\xc0j\xa9g\xc8L\xfd\x82\x95㨆] q\xa9\xd3N8o\x9c\x8c\x8a\x94vp\xe8[x\x8f\xb6+/\x98\xa5R\x19\x92\x9d\xc4\xf5w\x0e7\x95\x97\x01\x06\xdcJi\xcbx\xa7\xd3ф\xdb;\r\xac\x9d\x9av(\x01\x1b1{\xd0>\xa9Ρi\u0600\t\x84u\x8bj\xe0\x1d\xe3\x8eW\x80\x1fC,\xa2\x1d:*\xc2\x1b\xec\xa8(%as\x8e[\xf8h\xe3\x14\xe8ۥ\xc8\x10\xc6AS\x89\xa8\x8e\x97\x1eR\x87#b\xc5)\xb4V!\x8az\xe0#\x0fX\x1e\xb1\x86b@\x1d\x8e\xfd=S\x99\xa0\xf6\xdcQ339\xa7\xe2h\xb0:\xea@\xc1yc7\xb6Gܷף\xda(*\xf7\x9c\xec\xee\x90\xf0>h\\I\x11g\x90U\xa4\xa4/ղ\x9b'\xfe\xa2½\x9f\xe7\xdap\xee\xd4\x1a\x86\xfc䆸\xaf\x82\xc0|3\x1a\xfb\a\xc5\x0fM\x82\xc3F\xc3q\xa4_\x18\xf1{\x12\xd3Fj2\x0f\xaa\x9f\xb1P\xa2#\x82\xb8\x8c\x16\x14i*\xc0)~\x90\xe4\xbe\xf3[*\x97\x0ey\x89\x90\x03\xdfqo+?\xcf\xf3Z\x84\xd6⍑\xec-k\xf9kK\x80\x8bȼTX\xa3*}b\xfb\\ț\x84\xbf\x9du\xae@\xc0ȇtG\\{~\xe7(\xf8x^\x9cr-\xd6\xef\x981\xc1\xe2\r\xa3\xe9\xe6\xe1q80ڵ^<\xb6f\r\x0f\xce\xfa\xc2Z|V\xc0\xb1\xa0B\xe2\x80\xf4\xb1\xc1'\ve\xab\x8c$\xd7\xf3\xf6\xa0}א\x17\xf6%\x99\xf7\xd4)\xaejk\xadg\xcdW\x95.\xca톎\xd7\x14\x94\xe4\xfb\x90\xfav&\x1dSY\xd6\xf3\x954\xb6˘\xa7\x03^,\x18\x9f<:\x96)-\xd1vE\x82?i\x8dCSc\xa7\xa8[ڽ\xee\x16\xd0܌\xaf\xe6\xd7G\x11q\xbe\xf6\x83[\xa08\xaaׅ\x12f\xeb\xdf\xfe\xe5\xab#M\x14Γ\xfb\xdb=\x18\xff\xac\r\xab,~\x02a\x9a\xdf{\xa5\x1e\xf3\x80Z\x1a\xe7ۊ\xbc\xb9\x8f+yz\xd0\xe2*PD\x9e(+\x8c\x12r\x8c\xacݤh\xc6`\x83\x97\xd5\ay\xa8\xb4\xa7\xdaen\x163\x0e\xd4S\x83\xcfT\xb2\xc3\xe7g\xf4\xf8\xa0.\x86\x8enA\x15\x8d\xb6h\xa4\x16\xbf\x94\xf1G>K\x04\xd2)#Mqw\x8e\xee\x15\xaa\xeb\xb8;\x97\xc4\x16\xd0\xfe\x13\xcaCv(\xfe\x86p\x81_\x153W\xd8k\xe8\xc4xt\xaa\x83˰\x9c\xec\xec\a\x04z O\x81=vKż\xc0ℶ\xa6\xe4;\x1a\xfb\xb9\xf2\xd8x-\xfcdrf\b=\xfbÕc.h\xe3\xe7\xd6\xdd\xd2\x19-kw\u007f\xd9\x16]\xf0?D\xfe\x04\x87{\x04@\xc9y\xc3^\x8f\xb6wJ\xc9+\xceHh\xe7\xd8a\xa4\xd0S\xa7>\xb2\xb4\xf8M\xca5\xa6F\xd9I\xbb\xbc\xa0\x04z*\xde\x1d>2,S\xc6R`\x81\f\xe4\xe4,\xb4\x19\x04g\xf5\x115\nE \x01\x1ar\xb08+ȍ\x18-\xa4\xaf\x04I~Y\xb0\x13$\xad2ËF\x03\xbb\xc0\xec9\x06~`\xd1[\x8d^\xa5\xe1d\x1a\xa2ڌ\xf7\xc2\xde\x05\xf7uT\xb9\x06\xa8\xa7d\x1e\xf6\x80\x88\xd9\x19w\x82\x8fQOx\x06\xd5\x062\x1bp\xe4\x1c\xe5}-]\x1e\x94\xab\x95\xbb\x153\xa7\xdd\xc1\x9e\xb0\x85\xf67\x82c\x91\xee\x8f\x00n#Wor\xe9\xc6p\x17\x93\x003\x9c\xd1]\xbb\xe8Κo+\xc0+!\xda\x00d\xed\x10\xc4ܥ\xa5\x82\v\x19J(\xfe\x8a\xac\xd6\xd8X\xda\x16\xea\xc9ߢ`!\f\x8fz\xaf\x99\xceV\xfd\x96\x8b\x97\xcc\v\xf3.\x96\xa9\\\x86\xb9\xb8\xe5%\x9d\xbf\x18\x01\xb0\x9a\x1e\v\xd1\xef\xe2\xea6\xff>8\x85\\\x9a8\xa0\x94LڡV\xa2v\xc2}\xe7\xed\xe7\xb9͒\x98\x80Y\xea\xbb6\xb3\x8f\xd8\x06\xd7f\xb8\xe2ѻO\x81\xec\x83n\x18J\xb3\x16\x90\xa9U;\x152L\x1ax%\x94\xdd\xca#\x968\x1cb\xe3\xc85\a[\u007f\x0e\x04bc|\xa4\xfb\x02D\x0fJ\xceV<\xe2G\f\xa1w\xb4\x87\x00\x90:<\xe03\xeb\xe7\xa37\x96wڒ\x1f7\xb5\x80\b\x84\x82{\xb9DO\x9c\\\v\xf5\x99\xda.\xc7m4\x14\xfct_\xac#\xd6(\x18\xac\xabĒ,1+\x1a\u07bc+\x8f\r\x11\r\x9a\x03z\xa4\xeao\x00\x00\x00\xff\xff\xc0T\xbbH\xbe\x06\x00\x00", + local: "data/ru/female_last_names", + size: 1726, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2xUW27bQAz876kdJQ0KJED8SmO4blynBpp+VZIlWNHzCtwbdch9kHb7YXjFJbnDmdml +DZWU00Aj/3+iJeXuhhrq3CPVPrSn2mVuFjMO1FODz1Syw+dn9PigLoaObkEVjbZopBa/lPFHPksE0ikj +TXF3ju4Vquu4O5fEFtD+E8pDdij+hnCBXxUzV9hr6MR4dKqDy7Cc7OwHBHogT4E9dkvFvMDihLam5Dsa ++7ny2Hgt/GRyZgg9+8OVYy5o4+fW3dIZLWt3f9kWXfA/RP4Eh3sEQMl5w16PtndKySvOSGjn2GGk0FOn +PrK0+E3KNaZG2Um7vKAEeireHT4yLFPGUmCBDOTkLLQZBGf1ETUKRSABGnKwOCvIjRgtpK8ESX5ZsBMk +rTLDi0YDu8DsOQZ+YNFbjV6l4WQaotqM98LeBfd1VLkGqKdkHvaAiNkZd4KPUU94BtUGMhtw5BzlfS1d +HpSrlbsVM6fdwZ6whfY3gmOR7o8AbiNXb3LpxnAXkwAznNFdu+jOmm8rwCsh2gBk7RDE3KWlggsZSij+ +iqzW2FjaFurJ36JgIQyPeq+Zzlb9louXzAvzLpapXIa5uOUlnb8YAbCaHgvR7+LqNv8+OIVcmjiglEza +oVaidsJ95+3nuc2SmIBZ6rs2s4/YBtdmuOLRu0+B7INuGEqzFpCpVTsVMkwaeCWU3cojljgcYuPINQdb +fw4EYmN8pPsCRA9KzlY84kcMoXe0hwCQOjzgM+vnozeWd9qSHze1gAiEgnu5RE+cXAv1mdoux200FPx0 +X6wj1igYrKvEkiwxKxrevCuPDRENmgN6pOpvAAAA///AVLtIvgYAAA== +`, }, "/data/ru/female_patronymics": { - local: "data/ru/female_patronymics", - size: 237, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffT\x8eA\x0e\xc3 \f\x04\xef}5X\xed\x8dC\x9f\xe2V UP\x92/\xac\u007f\x94\x15\t\x91\x11\x17<\f\xeb\xc5\x1b\r\x05\xd5\"\x14\x1d\xd9\x026|y\xd3\a\x9fNPx&\xb2`/\xfc\xb0{k\x06x\x0f݄Nw\x1e\x8dʱYB^\xbe\x13|P\x98,\xde\x0e\xb4\x95\xfb\x93\xdf\xfe\x1c-\xd5\xe2\x82\a\x92+{\xe9*\x1c\xffw\xea\x11\x00\x00\xff\xff\xfc;\xa2\x9c\xed\x00\x00\x00", + local: "data/ru/female_patronymics", + size: 237, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1SOQQ7DIAwE7301WO2NQ5/iViBVUJIvrH+UFQmRERc8DOvFGw0F1SIUHdkCNnx50wef +TlB4JrJgL/ywe2sGeA/dhE53Ho3KsVlCXr4TfFCYLN4OtJX7k9/+HC3V4oIHkit76Soc/3fqEQAA///8 +O6Kc7QAAAA== +`, }, "/data/ru/genders": { - local: "data/ru/genders", - size: 30, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xba0\xe7b\xf3\x85m\x17\x1b/캰\xef\xc2N\xae\v\xd3.l\xbd\xb0\x17\xcc\xdd\x01\xe4\x02\x02\x00\x00\xff\xffdgd\x9f\x1e\x00\x00\x00", + local: "data/ru/genders", + size: 30, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/7ow52LzhW0XGy/surDvwk6uC9MubL2wF8zdAeQCAgAA//9kZ2SfHgAAAA== +`, }, "/data/ru/languages": { - local: "data/ru/languages", - size: 419, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\\\x90Mn\x830\x10\x85\xf7\x9cڀ`\x85ԟ\x15\xa2TT\xb4]\xe36\xa0\x98\x80\xc9\x15\xde\xdc(o\x90\x90MVx\xbe\x99y|6\x1a8\xc9`1K\x8a\x1b\x1c\xe6\x045\x8fw\"\x1f\xd0+<.X\xb4\b\xf0\x97\x1f\x8f\x11\x8e}1\\\xf8\v\xbd\x0e\x9b\x18\xc9$\xe7\x9a\xc5\"Uh\xbda\xdaӞ\xf0\x97䒆r\xa0\xc2\x16+\f\xf8?;}\xc0J\xc1\xdf{\xd8\x04\x9f\f]1Iyt\x1b\x15 \x8c|\u007fvI/%\xad\xae\x01\xf7\x9cZTT\xf2\x04-C9E\xf3B\xef\xd5S\xcaı=\x13V\x1eO\xea\xefRq&S\x13\xac\x01\u007fsu\xd4\xd0z\u007fa]y\x89/\xd0*\f\xf7\x01\x1ba\xb1!\xe1\xc0\x16\xac\x14\x95C\xca\x16\xa5W\x1d\xf8[\xd4F#H\b\xc7?\xaf\x92\xcc$+\r\xfa\x8fl\xde4\xd7\xc5K\b\x1a4]\xa9\x0f\x99b\xb6\x84\xa3\x17\xf8\x1aGo\xb2\xeb\xce\x13\xce|\xe8\xae\xe83)\x93\nx\xb9\xed\x05\xab\xed\xed.\xe1\x85!\x9b\r\xbeZ\xe3\xb7\xe8\xe1+\xc9\xe2IV\x91b\xb7\x14\x18+\xe1M\x91\"I'\x9b'\xe1\x9cw?\xe2\x94\xf0A~&\xac\x82Y{%|\xf2\xdd\x1ak\x9c\xfc`S\x1c\xf3\xc4V\x19?\xe1|\x11\xceq\xae\xefk\x98\xdf\x00\x00\x00\xff\xfft5E\xb6\xae\x01\x00\x00", + local: "data/ru/male_first_names", + size: 430, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0xQy0rEQBC8z1ebBW8L6rqCiK8FzxI2GZjNZOIvVP+RVd076CWpx/SjGveoyFhswIiG +2W7SPynjItow2g4b5dIFPgz3ARthsSHhwBasFJVDyhalVx34W9RGI0gIxz+vkswkKw36j2zeNNfFSwga +NF2pD5litoSjF/gaR2+y684TznzorugzKZMKeLntBavt7S7hhSGbDb5a47fo4SvJ4klWkWK3FBgr4U2R +IkknmyfhnHc/4pTwQX4mrIJZeyV88t0aa5z8YFMc88RWGT/hfBHOca7va5jfAAAA//90NUW2rgEAAA== +`, }, "/data/ru/male_last_names": { - local: "data/ru/male_last_names", - size: 1531, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffdT\xdbn\x1aK\x10|\xf7W\xe3\xc5\a\x1dɖ\xc2\xcd1\"\xd8\x04\a)\xceS\x96\x85\x15xaw\u007f\xa1\xe7\x8fR]==\x03\xc9\x03Zf\xa6/\xd5U5#\v\xa9\xa4\x94V:\xa9\xeed*e\xb8\x97\x93\x9cÓԺ\xb1\x96:\x14a`\xa7\x1b\xb9\xc8\t\x8b\x18\xbc\xc2\xe2?\xe4~\xca\xd96\xb6a\"\a\xe9rx'\r~\xf1\xf47\x17\x15\x96\xb1r'\xbd\x9d\x8cQ\xf1\x80\xac\xdaN\xc6\fi\x00䟍2F2\xed\x1b6w\xf8\x1d,j\x86\xfd\x93쵿\xa3߄\x02\u007f\xfa<\xdf\x06\xcb\vP\xc6\xe5\x1a'\x95\xe3\x9b\xe0\xb3G\xb1\x14\xfc\x8ar\x86\xbf\xb4rs\xce_\xb0\x0f7\x9e\xad\x9ds\xa7\xa1\x8d-\x96a(G\x14\xaa\xc3\xe8\xba\x18\xb2\xf1m\x8d\x1b\xf6\rO\x80\x83\xf3w\xec_P\xec\xc1\x87~C݈l\x8c]E\x05m|\xb2\xad\x8a\x84_\xef\x1cb2$\xec=\xfb\x05\xc1\xd0Ʊ\xad\xf0\xb7\xc0\xa8\xf1t\xaa t\\\x9c\x97*Y\x82\x8c\xfa\x17C\x88\x14RNX<\xc7\xe7\xe8\x90\x16\xb4\b\x03g\xec\\^\x87\xaeع\xf1\xc9U\xf5\x93/W\x91\xb1#\x97w\xf2\x1d\xdfK&\xfd\x8du\xfaT\aii\x8a\x175\x1b\b\xadM\xae\x1a\x18\xbeD\xedUH\xearN\x96\xc2\xc0\x9dW}\x06\x83\t\x9d\xfa\xa6\xd3s's\xce\xecG'b\x16\x86\xf4^P\x14\xa4\x86\x91\xbd\x8c\x83쾭\x99B=2\xd5\xd7\xc4e$\xdd\b\x1dy\x93-_\xb3\xce\xf9x\x05\xeac\x1e\xf3G\xf8?\xab:Gh\x9b\x1dA#\xa9T\xaa\x8d=2\xb7\xfeh\xad?J\x02\xa6Q\xf1'\x00\x00\xff\xff\f\xe6\xecL\xfb\x05\x00\x00", + local: "data/ru/male_last_names", + size: 1531, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2RU224aSxB891fjxQcdyZbCzTEi2AQHKc5TloUVeGF3f6Hnj1JdPT0DyQNaZqYv1VU1 +IwuppJRWOqnuZCpluJeTnMOT1LqxljoUYWCnG7nICYsYvMLiP+R+ytk2tmEiB+lyeCcNfvH0NxcVlrFy +J72djFHxgKzaTsYMaQDkn40yRjLtGzZ3+B0saob9k+y1v6PfhAJ/+jzfBssLUMblGieV45vgs0exFPyK +coa/tHJzzl+wDzeerZ1zp6GNLZZhKEcUqsPouhiy8W2NG/YNT4CD83fsX1DswYd+Q92IbIxdRQVtfLKt +ioRf7xxiMiTsPfsFwdDGsa3wt8Co8XSqIHRcnJcqWYKM+hdDiBRSTlg8x+fokBa0CANn7Fxeh67YufHJ +VfWTL1eRsSOXd/Id30sm/Y11+lQHaWmKFzUbCK1NrhoYvkTtVUjqck6WwsCdV30Ggwmd+qbTcydzzuxH +J2IWhvRePGlz1SUEvGffSTQ4oTVGxDvvQxcvSeR0gLrnWws8ZM8sCfFA/hIcFQJbmK3Kw2qKNmfaV0Q0 +yXUstnMj/aIcOzLX+UVToho3SkkjpCv+QcUPocAEWuqaqp/aE8hS9oRqXN2n0983fkdn2yAM7j2zdiJW +ZPSsQI21IgoDSJU/JYP8cizg6/aGIfOMt11HFQDdIyagvXEr7Ag5jjQjHUO+HJGd1ssZg7rVWG0QruJ+ +RksDwaOPvqTKNgg3PlAUpIaRvYyD7L6tmUI9MtXXxGUk3QgdeZMtX7PO+XgF6mMe80f4P6s6R2ibHUEj +qVSqjT0yt/5orT9KAqZR8ScAAP//DObsTPsFAAA= +`, }, "/data/ru/male_patronymics": { - local: "data/ru/male_patronymics", - size: 1165, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffl\x93\xcfN\xf30\x10\xc4\xef\xdfS\xb7\xfd@\xbdT\x02J+UP\xfe\x14q\x05J\x12K!N\xd2WX\xbf\x11\xb3Cpv\x1b\xd4C\xad\x9f\xc7\xeb\xf1\xecF\xae%J\x90&\xcd\xe5(\x9dTi&\xbd\x14R\xa7\xe5?\xb3\x15\xf0˰\x93cZ@\x15\xd3\xcac=\xec\x95\xd4u\xa6\"\x14\r.\xaa\xdc\xd14\x83.H;\xean\xb0,\xa5\xa2%\vq\xbc\x86\x9d\x8c\xd6P\xa8G\xbd\xa8\xb6\xdaa\x03\x95\xcdE\x808\\{\xe3k\x80F}ڗ\x03\x02\x1dϕQ\xadC\xdf\x028\xf5\xb0\x81\xea\xba*\xccV\xbaJK\xf8\x98lܪk\x8d\x92\x05\x83\xc5\xea\xa4tP\x9f\r\xd4\xfb\xe7l\x18\x0f\x9e3Vݰ\xaa\x8bhC\xb7\v\x96\xc8G\xb7X\x94\xccmea\xe9Sئ\v>6\x83\x1d\x16\xae%\xbb\xe1H\x18\x81F6,{M\x1b5\xb2\xfc\x8e\xb9\xa9\xe3h!F$͙\xf7\xa4\x8f\xf7\x9a\a_Y\x19\x88+L\x94{\x1cl\xd8\xd8\xd6A\xd4*\xec<\xee\xf1w\t헽\xfdAۯÌ\x8d\xac|\xe4P\x95\xa3\xea\x89͋\x16\x04fj@\x1c>\v\xe3\xfe\x19\xcbON\xe1\xc2\xc3\xd6\xc7x\xe0\xf4\x873\xc410\xfe\x0f?\x11\xfd5f\a~@'_\xf5\x05\x86f\x1cy\x83\x18\x12zb\xea\xbebY\xf9\xce+\x8a\xfc0\xe6\x16ք'\xfc2|÷\xfc\x9f\x17\x99\x06\xbd\xfbA\xfd`\xc2\x05C\xfdEz\xdb\xe4\x1d\xdf\x01\x00\x00\xff\xff[hP\x9b\x8d\x04\x00\x00", + local: "data/ru/male_patronymics", + size: 1165, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2yTz07zMBDE799Tt/1AvVQCSitVUP4UcQVKEkshTtJXWL8Rs0NwdhvUQ62fx+vx7Eau +JUqQJs3lKJ1UaSa9FFKn5T+zFfDLsJNjWkAV08pjPeyV1HWmIhQNLqrc0TSDLkg76m6wLKWiJQtxvIad +jNZQqEe9qLbaYQOVzUWAOFx742uARn3alwMCHc+VUa1D3wI49bCB6roqzFa6Skv4mGzcqmuNkgWDxeqk +dFCfDdT752wYD54zVt2wqotoQ7cLlshHt1iUzG1lYelT2KYLPjaDHRauJbvhSBiBRjYse00bNbL8jrmp +42ghRiTNmfekj/eaB19ZGYgrTJR7HGzY2NZB1CrsPO7xdwntl739Qduvw4yNrHzkUJWj6onNixYEZmpA +HD4L4/4Zy09O4cLD1sd44PSHM8QxMP4PPxH9NWYHfkAnX/UFhmYceYMYEnpi6r5iWfnOK4r8MOYW1oQn +/DJ8w7f8nxeZBr37Qf1gwgVD/UV62+Qd3wEAAP//W2hQm40EAAA= +`, }, "/data/ru/months": { - local: "data/ru/months", - size: 148, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffL\x8c1\x0e\x02!\x14\x05{N\xbd\xae\xadQ\n\v\v51\xb1\x171\x14b\xd0+̻\x91\xffC\xa2\xdb1\xc3\xfbÍF&i\xd2&p\xa5\x905\x91x9\x1e\xbb\x9f\x03\x91\x8f\xd9\xf2\xb3<\x03\ami\xce\xfe\xe8\x1f\xd1B\x0f\xad\xb5\xf2\x93\x8b͛f\xed\xb8\x8f\xf6\x99\xba\xc4\x13\xef?\xecm\\-;\xf0\x1b\x00\x00\xff\xff\xe9\xeb\xb4ٔ\x00\x00\x00", + local: "data/ru/months", + size: 148, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0yMMQ4CIRQFe069rq1RCgsLNTGxFzEUYtArzLuR/0Oi2zHD+8ONRiZp0iZwpZA1kXg5 +HrufA5GP2fKzPAMHbWnO/ugf0UIPrbXyk4vNm2btuI/2mbrEE+8/7G1cLTvwGwAA///p67TZlAAAAA== +`, }, "/data/ru/phones_format": { - local: "data/ru/phones_format", - size: 26, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffR\xd6UV\x86a \xe2B\xb0\x00\x01\x00\x00\xff\xff\xb5\xe6\x87^\x1a\x00\x00\x00", + local: "data/ru/phones_format", + size: 26, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1LWVVaGYSDiQrAAAQAA//+15odeGgAAAA== +`, }, "/data/ru/states": { - local: "data/ru/states", - size: 2756, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x8cVKR\x1bA\f\xdds\n/\x93\x05w4C\bTA\xc5@H\x852`bS\x14\xab\x04c{`\xf0|\xb8\x82\xfa\n9I\xde{\xdd6\xa4\x98\x91Y@yZ\xaf\xf5yRK\xb2c[\x84C\x9b[\x1e\x06[\xf8(CfS{\u07b2\x13\x9b\x86\x03[Z\x13\xfa8j\u008e\x045\x04a\x17G\x03|\x16\xbcr\x86S\xde^\xcbϭ\xb690\a8L\x98!$\x0f\xd0\u05f7\x85\x15\x107\xdbTo%\xd4\xf3p\x8d)\xad\x82/\xcb\xf5\x01dӰ\x0fAn3^\xba\x83\xca>\xe4\xb0\xf6\x16\x93\xe3b\xfal\xac\xb2b\xcb.\xa3^{\xee\xd9o+\xf9\xdd\xc8x\x03=B\x8e\x01سi\xef\x93\xdd\xdb\x12\xce\xca\xd1\xcf<\xa7)Z\xa9\x81\x18\xf4l\x04S)\x8e\xde\xdf\xfeY\x8f\x141Ψf\x02PF[\xaf\xe1O\x10\xc1L\x9a'a\x97\xbf\xa0\xf5\x06\xa6+і\b\xb9\x05\x96\xb1\xa70\x18\u05fe\xd5\xfa\x19/\x81\xbd\x18\x91(x\x9b\x19\xdcY\xc6Ȗ\x941U?#\xbd\xf6L\x9d\xc0\x1d\xb5`HoE.C\xd6&\x95\x99\x1d\xa6\x06\xae*\x1e\x0f\x83\xec\xb7!\xaeE\\\xd5&Q6*\x15\xd3{\xe9X\x91\xcd\xf0\xd9\xd8\v\xfe\xda#\xb8]\x17\x11\xb2\xd8\"\x1fAZ\xd2C\x92L\xc2\"\xe3;\"\x1a\x99l^\xe5\xe1\br\xc8\xf6\x94\xc99\v(\x99lG\xf2G?V\f\xb2ԅ;Q!\xceUj\xa0\xb1\x1b\xc7\xe7\xe3\xe89U\x85-DX\xe1DpJ\xaah\x0fύ\x1ct[\x8c\xc8FX\x17%\xcfk\xc4\xf1؉:gy\xaaPf\xdd\x18\xbeR\xbe\xaaND|\xed\xec\x05\x85څ\xef\xbf\xd0x\x18\xdd^\r\xe1s\xa5\xf2\xf3\xfc\x1a\x92\xcf\r\x88&e\xbbI\x85܊be\x81M\xaf\x1a\x86n\xf5]\xc0ߏ\xc5~\x01\xd4\v\"\xfb\xda!\xbfT\xffe\xbdxް\x01R\xe6\xc5~\xa9\xa8*W\xcf\x15\xbcy\x84\uf6eb\xfcJ\xcd\xf6\xa38zW@\xe0\xd5\xfb\xc8\xc9\xc8Hc\xa0\xb6\x87\x98\x19\x17W\xba,\\K\xcf\x13\xffwc6r\xf9+ML\x17\x83.\xf0\xe4\xb2=f\xd3^\xb7\xe3\x0e\x84:\x93o)M\xbb\xf8\xe2\x1cT\x9c|\x8b\r\f\x8d\xd9\xc8q\xe014\x91\xe7\x0f\xae\x9eI\xb4\xe7Ƚ7\xc8\xe9\xeau\xedI\xf8Ǝ\xe0\xf8x\xa3\xfb\x83\r\xbd\xecN\xd3a\xc0\xdattݳ\xca!-5ȺP\xdfW\xaf\x01\xfbA\xf8\x02\xc5\v\x11\xae\x99-7\xf0\\z\xa8\x89ZkO\xbe\xda2V\x8f\x17\x8d7\xd6D\x8d\xee\x9amk\xdefҐ\xca~\xb5\xbfLS\xed\xa5a\xcaa8\xd3A\xad\x05\xa9nu\xee\x87&p\x9e6\f!\x8em\xf4\xee.֛\x9cw1w\x91\x819]\xba\x92\xab\xb1Ei&\xebޭJ;\v\x87\xdb\xeaQ\xb5^\xf8\x9b\xf5\x05\xa0\xb8Q\xfd\x89=0\xee>\\8\xb3\xff@ WM\xa9\xe4\x06\xd8j\xea_\x00\x00\x00\xff\xff\x9du\x89T\xc4\n\x00\x00", + local: "data/ru/states", + size: 2756, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/4xWS1IbQQzdcwovkwV3NEMIVEHFQEiFMmBiUxSrBGN7YPB8uIL6CjlJ3nvdNqSYkVlA +eVqv9XlSS7JjW4RDm1seBlv4KENmU3veshObhgNbWhP6OGrCjgQ1BGEXRwN8FrxyhlPeXsvPrbY5MAc4 +TJghJA/Q17eFFRA321RvJdTzcI0prYIvy/UBZNOwD0FuM166g8o+5LD2FpPjYvpsrLJiyy6jXnvu2W8r ++d3IeAM9Qo4B2LNp75Pd2xLOytHPPKcpWqmBGPRsBFMpjt7f/lmPFDHOqGYCUEZbr+FPEMFMmidhl7+g +9QamK9GWCLkFlrGnMBjXvtX6GS+BvRiRKHibGdxZxsiWlDFVPyO99kydwB21YEhvRS5D1iaVmR2mBq4q +Hg+D7LchrkVc1SZRNioV03vpWJHN8NnYC/7aI7hdFxGy2CIfQVrSQ5JMwiLjOyIamWxe5eEIcsj2lMk5 +CyiZbEfyRz9WDLLUhTtRIc5VaqCxG8fn4+g5VYUtRFjhRHBKqmgPz40cdFuMyEZYFyXPa8Tx2Ik6Z3mq +UGbdGL5SvqpORHzt7AWF2oXvv9B4GN1eDeFzpfLz/BqSzw2IJmW7SYXcimJlgU2vGoZu9V3A34/FfgHU +CyL72iG/VP9lvXjesAFS5sV+qagqV88VvHmE75ur/ErN9qM4eldA4NX7yMnISGOgtoeYGRdXuixcS88T +/3djNnL5K01MF4Mu8OSyPWbTXrfjDoQ6k28pTbv44hxUnHyLDQyN2chx4DE0kecPrp5JtOfIvTfI6ep1 +7Un4xo7g+Hij+4MNvexO02HA2nR03bPKIS01yLpQ31evAftB+ALFCxGumS038Fx6qIlaa0++2jJWjxeN +N9ZEje6abWveZtKQyn61v0xT7aVhymE400GtBalude6HJnCeNgwhjm307i7Wm5x3MXeRgTldupKrsUVp +JuverUo7C4fb6lG1Xvib9QWguFH9iT0w7j5cOLP/QCBXTankBthq6l8AAAD//511iVTECgAA +`, }, "/data/ru/streets": { - local: "data/ru/streets", - size: 694, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\\\x92\xcbn\xf2@\f\x85\xf7\x1a\x94\xad\xb3\xa5k\xad\xad۹\xc9\xca;8Ee\x1b\xfd\xe3\xfb\x9cR\x0f\xac\x97\x84\x1b\x9c\xe4=Ǫe&w\x1c\x9b66\xc6^/\xabF8\xd1s\xb4^\x1b\xeb\xc71\x98\xf0\xe4=\xf5\xaa:\xe4\xef\xf7\"st\xe3\xa9xu\x1ce\xae\x979\xe7\xdeU\xfa\x01\x1a@\x84\xf8d\xe2\xc6'\x8cf=Q\x96x\u007f\x02\x00\x00\xff\xff#>\x03\x17\xb6\x02\x00\x00", + local: "data/ru/streets", + size: 694, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1ySy27yQAyF9zx1Avr1VwIJ9aJWCqUpm7YrFC4DCSnhFY7fqMfOTD3qIkG2D/bn4+AD +AVeZSoEGvSxwRSPLCV4xoOdzZPmUkl+4aNpVG4Z7BP69ZMlSK4Zlqq+tHqUNm/2Ga4Y7Sou8/wt/mJD/ +TtEqmHVlrtW8ygLZQhLVhhpS55XMcPBBb7gQb4mdFLJwzIqKb4Z8jyt56ZFoByOJ82rj3Ju2QefKjU3V +YvJDpkzdcnt6BtlGlW1kdBNsffWawwaTFt7/PhqUrbOla62t27nJyjs4RWUb/eP7nFIPrJeEG5zkPceq +ZSZ3HJs2NsZeL6tGONFztF4b68cxmPDkPfWqOuTv9yJzdOOpeHUcZa6XOefeVfoBGkCE+GTixieMZj1R +lnh/AgAA//8jPgMXtgIAAA== +`, }, "/data/ru/weekdays": { - local: "data/ru/weekdays", - size: 117, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff4\x8d;\n\x031\fD{\x9d\xdaI U \xe0\v\x18Wi\xb3\x1f\xc1\xe2\xc5>\xc3Ӎv\\,\xc6\xd2<\xcd\bQ\x18t\x9c]\xff\x8c\x8f\xf4A3r<\x19\x91n\xac\x923\xf37~\xb8\xbcU5\xb1\x19%\xbeB\xc5\xe2=\xdd\x1a/\x16\xbd\xa1\xa10K\x98{a#H\xa2\x91\v\x10\x00\x00\xff\xff\xber!\xd8#\x00\x00\x00", + local: "data/ru/weekdays_short", + size: 35, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/7ow/8JerguTLjZxXVh4sYHrwnIQaz6Ye2EjSKKRCxAAAP//vnIh2CMAAAA= +`, }, "/data/ru/zips_format": { - local: "data/ru/zips_format", - size: 8, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffR\x86\x00.@\x00\x00\x00\xff\xff\x87\xdd'=\b\x00\x00\x00", + local: "data/ru/zips_format", + size: 8, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1KGAC5AAAAA//+H3Sc9CAAAAA== +`, }, "/": { isDir: true, + local: "/", }, "/data": { isDir: true, + local: "/data", }, "/data/en": { isDir: true, + local: "/data/en", }, "/data/ru": { isDir: true, + local: "/data/ru", }, } diff --git a/vendor/github.com/icrowley/fake/fake.go b/vendor/github.com/icrowley/fake/fake.go index df3cb77c0..b9ada47a6 100644 --- a/vendor/github.com/icrowley/fake/fake.go +++ b/vendor/github.com/icrowley/fake/fake.go @@ -93,7 +93,7 @@ func (s *rndSrc) Seed(n int64) { // GetLangs returns a slice of available languages func GetLangs() []string { var langs []string - for k, v := range data { + for k, v := range _escData { if v.isDir && k != "/" && k != "/data" { langs = append(langs, strings.Replace(k, "/data/", "", 1)) } diff --git a/vendor/github.com/icrowley/fake/glide.lock b/vendor/github.com/icrowley/fake/glide.lock deleted file mode 100644 index 515144a38..000000000 --- a/vendor/github.com/icrowley/fake/glide.lock +++ /dev/null @@ -1,6 +0,0 @@ -hash: 9238b15272824ad573d8ef645fb468cb646b72598c63eae8977c3410ebfebe4a -updated: 2017-07-23T15:10:00.972860398Z -imports: -- name: github.com/corpix/uarand - version: 031be390f409fb4bac8fb299e3bcd101479f89f8 -testImports: [] diff --git a/vendor/github.com/icrowley/fake/glide.yaml b/vendor/github.com/icrowley/fake/glide.yaml deleted file mode 100644 index 93f9bfae3..000000000 --- a/vendor/github.com/icrowley/fake/glide.yaml +++ /dev/null @@ -1,3 +0,0 @@ -package: github.com/icrowley/fake -import: -- package: github.com/corpix/uarand diff --git a/vendor/github.com/inconshreveable/mousetrap/LICENSE b/vendor/github.com/inconshreveable/mousetrap/LICENSE index 5f0d1fb6a..5f920e973 100644 --- a/vendor/github.com/inconshreveable/mousetrap/LICENSE +++ b/vendor/github.com/inconshreveable/mousetrap/LICENSE @@ -1,13 +1,201 @@ -Copyright 2014 Alan Shreve + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Alan Shreve (@inconshreveable) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_others.go b/vendor/github.com/inconshreveable/mousetrap/trap_others.go index 9d2d8a4ba..06a91f086 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_others.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_others.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package mousetrap diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go index 336142a5e..0c5688021 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go @@ -1,81 +1,32 @@ -// +build windows -// +build !go1.4 - package mousetrap import ( - "fmt" - "os" "syscall" "unsafe" ) -const ( - // defined by the Win32 API - th32cs_snapprocess uintptr = 0x2 -) - -var ( - kernel = syscall.MustLoadDLL("kernel32.dll") - CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot") - Process32First = kernel.MustFindProc("Process32FirstW") - Process32Next = kernel.MustFindProc("Process32NextW") -) - -// ProcessEntry32 structure defined by the Win32 API -type processEntry32 struct { - dwSize uint32 - cntUsage uint32 - th32ProcessID uint32 - th32DefaultHeapID int - th32ModuleID uint32 - cntThreads uint32 - th32ParentProcessID uint32 - pcPriClassBase int32 - dwFlags uint32 - szExeFile [syscall.MAX_PATH]uint16 -} - -func getProcessEntry(pid int) (pe *processEntry32, err error) { - snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) - if snapshot == uintptr(syscall.InvalidHandle) { - err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1) - return +func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { + snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err } - defer syscall.CloseHandle(syscall.Handle(snapshot)) - - var processEntry processEntry32 - processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) - ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32First: %v", e1) - return + defer syscall.CloseHandle(snapshot) + var procEntry syscall.ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = syscall.Process32First(snapshot, &procEntry); err != nil { + return nil, err } - for { - if processEntry.th32ProcessID == uint32(pid) { - pe = &processEntry - return + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil } - - ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32Next: %v", e1) - return + err = syscall.Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err } } } -func getppid() (pid int, err error) { - pe, err := getProcessEntry(os.Getpid()) - if err != nil { - return - } - - pid = int(pe.th32ParentProcessID) - return -} - // StartedByExplorer returns true if the program was invoked by the user double-clicking // on the executable from explorer.exe // @@ -83,16 +34,9 @@ func getppid() (pid int, err error) { // It does not guarantee that the program was run from a terminal. It only can tell you // whether it was launched from explorer.exe func StartedByExplorer() bool { - ppid, err := getppid() + pe, err := getProcessEntry(syscall.Getppid()) if err != nil { return false } - - pe, err := getProcessEntry(ppid) - if err != nil { - return false - } - - name := syscall.UTF16ToString(pe.szExeFile[:]) - return name == "explorer.exe" + return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) } diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go deleted file mode 100644 index 9a28e57c3..000000000 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build windows -// +build go1.4 - -package mousetrap - -import ( - "os" - "syscall" - "unsafe" -) - -func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { - snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) - if err != nil { - return nil, err - } - defer syscall.CloseHandle(snapshot) - var procEntry syscall.ProcessEntry32 - procEntry.Size = uint32(unsafe.Sizeof(procEntry)) - if err = syscall.Process32First(snapshot, &procEntry); err != nil { - return nil, err - } - for { - if procEntry.ProcessID == uint32(pid) { - return &procEntry, nil - } - err = syscall.Process32Next(snapshot, &procEntry) - if err != nil { - return nil, err - } - } -} - -// StartedByExplorer returns true if the program was invoked by the user double-clicking -// on the executable from explorer.exe -// -// It is conservative and returns false if any of the internal calls fail. -// It does not guarantee that the program was run from a terminal. It only can tell you -// whether it was launched from explorer.exe -func StartedByExplorer() bool { - pe, err := getProcessEntry(os.Getppid()) - if err != nil { - return false - } - return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) -} diff --git a/vendor/github.com/kardianos/osext/README.md b/vendor/github.com/kardianos/osext/README.md index 61350baba..15cbc3d95 100644 --- a/vendor/github.com/kardianos/osext/README.md +++ b/vendor/github.com/kardianos/osext/README.md @@ -1,7 +1,12 @@ ### Extensions to the "os" package. +[![GoDoc](https://godoc.org/github.com/kardianos/osext?status.svg)](https://godoc.org/github.com/kardianos/osext) + ## Find the current Executable and ExecutableFolder. +As of go1.8 the Executable function may be found in `os`. The Executable function +in the std lib `os` package is used if available. + There is sometimes utility in finding the current executable file that is running. This can be used for upgrading the current executable or finding resources located relative to the executable file. Both diff --git a/vendor/github.com/kardianos/osext/osext_plan9.go b/vendor/github.com/kardianos/osext/osext_plan9.go index 655750c54..95e237137 100644 --- a/vendor/github.com/kardianos/osext/osext_plan9.go +++ b/vendor/github.com/kardianos/osext/osext_plan9.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//+build !go1.8 + package osext import ( diff --git a/vendor/github.com/kardianos/osext/osext_procfs.go b/vendor/github.com/kardianos/osext/osext_procfs.go index d59847ee5..e1f16f885 100644 --- a/vendor/github.com/kardianos/osext/osext_procfs.go +++ b/vendor/github.com/kardianos/osext/osext_procfs.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux netbsd solaris dragonfly +// +build !go1.8,android !go1.8,linux !go1.8,netbsd !go1.8,solaris !go1.8,dragonfly package osext @@ -16,7 +16,7 @@ import ( func executable() (string, error) { switch runtime.GOOS { - case "linux": + case "linux", "android": const deletedTag = " (deleted)" execpath, err := os.Readlink("/proc/self/exe") if err != nil { diff --git a/vendor/github.com/kardianos/osext/osext_sysctl.go b/vendor/github.com/kardianos/osext/osext_sysctl.go index 66da0bcf9..33cee2522 100644 --- a/vendor/github.com/kardianos/osext/osext_sysctl.go +++ b/vendor/github.com/kardianos/osext/osext_sysctl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin freebsd openbsd +// +build !go1.8,darwin !go1.8,freebsd openbsd package osext diff --git a/vendor/github.com/kardianos/osext/osext_windows.go b/vendor/github.com/kardianos/osext/osext_windows.go index 72d282cf8..074b3b385 100644 --- a/vendor/github.com/kardianos/osext/osext_windows.go +++ b/vendor/github.com/kardianos/osext/osext_windows.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//+build !go1.8 + package osext import ( diff --git a/vendor/github.com/magiconair/properties/.gitignore b/vendor/github.com/magiconair/properties/.gitignore index 7054822dc..e7081ff52 100644 --- a/vendor/github.com/magiconair/properties/.gitignore +++ b/vendor/github.com/magiconair/properties/.gitignore @@ -2,3 +2,5 @@ *.sublime-workspace *.un~ *.swp +.idea/ +*.iml diff --git a/vendor/github.com/magiconair/properties/.travis.yml b/vendor/github.com/magiconair/properties/.travis.yml deleted file mode 100644 index 5ef5d72f3..000000000 --- a/vendor/github.com/magiconair/properties/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: go -go: - - 1.4.3 - - 1.5.3 - - 1.6 - - tip diff --git a/vendor/github.com/magiconair/properties/CHANGELOG.md b/vendor/github.com/magiconair/properties/CHANGELOG.md deleted file mode 100644 index bf49a1376..000000000 --- a/vendor/github.com/magiconair/properties/CHANGELOG.md +++ /dev/null @@ -1,81 +0,0 @@ -## Changelog - -### [1.7.0](https://github.com/magiconair/properties/tags/v1.7.0) - 20 Mar 2016 - - * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#Properties.LoadURL) method to load properties from a URL. - * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#Properties.LoadString) method to load properties from an UTF8 string. - * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) - -### [1.6.0](https://github.com/magiconair/properties/tags/v1.6.0) - 11 Dec 2015 - - * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. - -### [1.5.6](https://github.com/magiconair/properties/tags/v1.5.6) - 18 Oct 2015 - - * Vendored in gopkg.in/check.v1 - -### [1.5.5](https://github.com/magiconair/properties/tags/v1.5.5) - 31 Jul 2015 - - * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) - -### [1.5.4](https://github.com/magiconair/properties/tags/v1.5.4) - 23 Jun 2015 - - * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. - -### [1.5.3](https://github.com/magiconair/properties/tags/v1.5.3) - 02 Jun 2015 - - * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) - -### [1.5.2](https://github.com/magiconair/properties/tags/v1.5.2) - 10 Apr 2015 - - * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty - * Add clickable links to README - -### [1.5.1](https://github.com/magiconair/properties/tags/v1.5.1) - 08 Dec 2014 - - * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with - [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). - -### [1.5.0](https://github.com/magiconair/properties/tags/v1.5.0) - 18 Nov 2014 - - * Added support for single and multi-line comments (reading, writing and updating) - * The order of keys is now preserved - * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry - * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method - * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) - -### [1.4.2](https://github.com/magiconair/properties/tags/v1.4.2) - 15 Nov 2014 - - * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one - -### [1.4.1](https://github.com/magiconair/properties/tags/v1.4.1) - 13 Nov 2014 - - * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string - -### [1.4.0](https://github.com/magiconair/properties/tags/v1.4.0) - 23 Sep 2014 - - * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys - * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties - -### [1.3.0](https://github.com/magiconair/properties/tags/v1.3.0) - 18 Mar 2014 - -* Added support for time.Duration -* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tags/vior configurable (log.Fatal, panic) - custom) -* Changed default of MustXXX() failure from panic to log.Fatal - -### [1.2.0](https://github.com/magiconair/properties/tags/v1.2.0) - 05 Mar 2014 - -* Added MustGet... functions -* Added support for int and uint with range checks on 32 bit platforms - -### [1.1.0](https://github.com/magiconair/properties/tags/v1.1.0) - 20 Jan 2014 - -* Renamed from goproperties to properties -* Added support for expansion of environment vars in - filenames and value expressions -* Fixed bug where value expressions were not at the - start of the string - -### [1.0.0](https://github.com/magiconair/properties/tags/v1.0.0) - 7 Jan 2014 - -* Initial release diff --git a/vendor/github.com/magiconair/properties/LICENSE b/vendor/github.com/magiconair/properties/LICENSE deleted file mode 100644 index 7eab43b6b..000000000 --- a/vendor/github.com/magiconair/properties/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -goproperties - properties file decoder for Go - -Copyright (c) 2013-2014 - Frank Schroeder - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/magiconair/properties/README.md b/vendor/github.com/magiconair/properties/README.md index 1ae0035a0..4872685f4 100644 --- a/vendor/github.com/magiconair/properties/README.md +++ b/vendor/github.com/magiconair/properties/README.md @@ -1,7 +1,8 @@ -Overview [![Build Status](https://travis-ci.org/magiconair/properties.svg?branch=master)](https://travis-ci.org/magiconair/properties) -======== +[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases) +[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE) +[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) -#### Current version: 1.7.0 +# Overview properties is a Go library for reading and writing properties files. @@ -25,8 +26,9 @@ changed from `panic` to `log.Fatal` but this is configurable and custom error handling functions can be provided. See the package documentation for details. -Getting Started ---------------- +Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) + +## Getting Started ```go import ( @@ -35,13 +37,38 @@ import ( ) func main() { + // init from a file p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) - // via getters + // or multiple files + p = properties.MustLoadFiles([]string{ + "${HOME}/config.properties", + "${HOME}/config-${USER}.properties", + }, properties.UTF8, true) + + // or from a map + p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"}) + + // or from a string + p = properties.MustLoadString("key=value\nabc=def") + + // or from a URL + p = properties.MustLoadURL("http://host/path") + + // or from multiple URLs + p = properties.MustLoadURL([]string{ + "http://host/config", + "http://host/config-${USER}", + }, true) + + // or from flags + p.MustFlag(flag.CommandLine) + + // get values through getters host := p.MustGetString("host") port := p.GetInt("port", 8080) - // or via decode + // or through Decode type Config struct { Host string `properties:"host"` Port int `properties:"port,default=9000"` @@ -52,30 +79,20 @@ func main() { if err := p.Decode(&cfg); err != nil { log.Fatal(err) } - - // or via flags - p.MustFlag(flag.CommandLine) - - // or via url - p = properties.MustLoadURL("http://host/path") } ``` -Read the full documentation on [GoDoc](https://godoc.org/github.com/magiconair/properties) [![GoDoc](https://godoc.org/github.com/magiconair/properties?status.png)](https://godoc.org/github.com/magiconair/properties) - -Installation and Upgrade ------------------------- +## Installation and Upgrade ``` $ go get -u github.com/magiconair/properties ``` -License -------- +## License 2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. -ToDo ----- +## ToDo + * Dump contents with passwords and secrets obscured diff --git a/vendor/github.com/magiconair/properties/decode.go b/vendor/github.com/magiconair/properties/decode.go index b989e6397..f5e252f8d 100644 --- a/vendor/github.com/magiconair/properties/decode.go +++ b/vendor/github.com/magiconair/properties/decode.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -48,49 +48,49 @@ import ( // // Examples: // -// // Field is ignored. -// Field int `properties:"-"` +// // Field is ignored. +// Field int `properties:"-"` // -// // Field is assigned value of 'Field'. -// Field int +// // Field is assigned value of 'Field'. +// Field int // -// // Field is assigned value of 'myName'. -// Field int `properties:"myName"` +// // Field is assigned value of 'myName'. +// Field int `properties:"myName"` // -// // Field is assigned value of key 'myName' and has a default -// // value 15 if the key does not exist. -// Field int `properties:"myName,default=15"` +// // Field is assigned value of key 'myName' and has a default +// // value 15 if the key does not exist. +// Field int `properties:"myName,default=15"` // -// // Field is assigned value of key 'Field' and has a default -// // value 15 if the key does not exist. -// Field int `properties:",default=15"` +// // Field is assigned value of key 'Field' and has a default +// // value 15 if the key does not exist. +// Field int `properties:",default=15"` // -// // Field is assigned value of key 'date' and the date -// // is in format 2006-01-02 -// Field time.Time `properties:"date,layout=2006-01-02"` +// // Field is assigned value of key 'date' and the date +// // is in format 2006-01-02 +// Field time.Time `properties:"date,layout=2006-01-02"` // -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas. -// Field []string +// // Field is assigned the non-empty and whitespace trimmed +// // values of key 'Field' split by commas. +// Field []string // -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas and has a default -// // value ["a", "b", "c"] if the key does not exist. -// Field []string `properties:",default=a;b;c"` +// // Field is assigned the non-empty and whitespace trimmed +// // values of key 'Field' split by commas and has a default +// // value ["a", "b", "c"] if the key does not exist. +// Field []string `properties:",default=a;b;c"` // -// // Field is decoded recursively with "Field." as key prefix. -// Field SomeStruct +// // Field is decoded recursively with "Field." as key prefix. +// Field SomeStruct // -// // Field is decoded recursively with "myName." as key prefix. -// Field SomeStruct `properties:"myName"` +// // Field is decoded recursively with "myName." as key prefix. +// Field SomeStruct `properties:"myName"` // -// // Field is decoded recursively with "Field." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string +// // Field is decoded recursively with "Field." as key prefix +// // and the next dotted element of the key as map key. +// Field map[string]string // -// // Field is decoded recursively with "myName." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string `properties:"myName"` +// // Field is decoded recursively with "myName." as key prefix +// // and the next dotted element of the key as map key. +// Field map[string]string `properties:"myName"` func (p *Properties) Decode(x interface{}) error { t, v := reflect.TypeOf(x), reflect.ValueOf(x) if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct { @@ -158,16 +158,16 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle // keydef returns the property key and the default value based on the // name of the struct field and the options in the tag. keydef := func(f reflect.StructField) (string, *string, map[string]string) { - key, opts := parseTag(f.Tag.Get("properties")) + _key, _opts := parseTag(f.Tag.Get("properties")) - var def *string - if d, ok := opts["default"]; ok { - def = &d + var _def *string + if d, ok := _opts["default"]; ok { + _def = &d } - if key != "" { - return key, def, opts + if _key != "" { + return _key, _def, _opts } - return f.Name, def, opts + return f.Name, _def, _opts } switch { @@ -189,12 +189,12 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle for i := 0; i < v.NumField(); i++ { fv := v.Field(i) fk, def, opts := keydef(t.Field(i)) - if !fv.CanSet() { - return fmt.Errorf("cannot set ", t.Field(i).Name) - } if fk == "-" { continue } + if !fv.CanSet() { + return fmt.Errorf("cannot set %s", t.Field(i).Name) + } if key != "" { fk = key + "." + fk } @@ -223,7 +223,7 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle case isMap(t): valT := t.Elem() m := reflect.MakeMap(t) - for postfix, _ := range p.FilterStripPrefix(key + ".").m { + for postfix := range p.FilterStripPrefix(key + ".").m { pp := strings.SplitN(postfix, ".", 2) mk, mv := pp[0], reflect.New(valT) if err := dec(p, key+"."+mk, nil, nil, mv); err != nil { @@ -274,7 +274,6 @@ func isArray(t reflect.Type) bool { return t.Kind() == reflect.Array || t.Kin func isBool(t reflect.Type) bool { return t.Kind() == reflect.Bool } func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } -func isNumeric(t reflect.Type) bool { return isInt(t) || isUint(t) || isFloat(t) } func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } func isString(t reflect.Type) bool { return t.Kind() == reflect.String } func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } diff --git a/vendor/github.com/magiconair/properties/doc.go b/vendor/github.com/magiconair/properties/doc.go index ed1ff510a..7c7979315 100644 --- a/vendor/github.com/magiconair/properties/doc.go +++ b/vendor/github.com/magiconair/properties/doc.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -13,7 +13,7 @@ // // To load a single properties file use MustLoadFile(): // -// p := properties.MustLoadFile(filename, properties.UTF8) +// p := properties.MustLoadFile(filename, properties.UTF8) // // To load multiple properties files use MustLoadFiles() // which loads the files in the given order and merges the @@ -23,25 +23,25 @@ // Filenames can contain environment variables which are expanded // before loading. // -// f1 := "/etc/myapp/myapp.conf" -// f2 := "/home/${USER}/myapp.conf" -// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) +// f1 := "/etc/myapp/myapp.conf" +// f2 := "/home/${USER}/myapp.conf" +// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) // // All of the different key/value delimiters ' ', ':' and '=' are // supported as well as the comment characters '!' and '#' and // multi-line values. // -// ! this is a comment -// # and so is this +// ! this is a comment +// # and so is this // -// # the following expressions are equal -// key value -// key=value -// key:value -// key = value -// key : value -// key = val\ -// ue +// # the following expressions are equal +// key value +// key=value +// key:value +// key = value +// key : value +// key = val\ +// ue // // Properties stores all comments preceding a key and provides // GetComments() and SetComments() methods to retrieve and @@ -55,62 +55,62 @@ // and malformed expressions are not allowed and cause an // error. Expansion of environment variables is supported. // -// # standard property -// key = value +// # standard property +// key = value // -// # property expansion: key2 = value -// key2 = ${key} +// # property expansion: key2 = value +// key2 = ${key} // -// # recursive expansion: key3 = value -// key3 = ${key2} +// # recursive expansion: key3 = value +// key3 = ${key2} // -// # circular reference (error) -// key = ${key} +// # circular reference (error) +// key = ${key} // -// # malformed expression (error) -// key = ${ke +// # malformed expression (error) +// key = ${ke // -// # refers to the users' home dir -// home = ${HOME} +// # refers to the users' home dir +// home = ${HOME} // -// # local key takes precendence over env var: u = foo -// USER = foo -// u = ${USER} +// # local key takes precedence over env var: u = foo +// USER = foo +// u = ${USER} // // The default property expansion format is ${key} but can be // changed by setting different pre- and postfix values on the // Properties object. // -// p := properties.NewProperties() -// p.Prefix = "#[" -// p.Postfix = "]#" +// p := properties.NewProperties() +// p.Prefix = "#[" +// p.Postfix = "]#" // // Properties provides convenience functions for getting typed // values with default values if the key does not exist or the // type conversion failed. // -// # Returns true if the value is either "1", "on", "yes" or "true" -// # Returns false for every other value and the default value if -// # the key does not exist. -// v = p.GetBool("key", false) +// # Returns true if the value is either "1", "on", "yes" or "true" +// # Returns false for every other value and the default value if +// # the key does not exist. +// v = p.GetBool("key", false) // -// # Returns the value if the key exists and the format conversion -// # was successful. Otherwise, the default value is returned. -// v = p.GetInt64("key", 999) -// v = p.GetUint64("key", 999) -// v = p.GetFloat64("key", 123.0) -// v = p.GetString("key", "def") -// v = p.GetDuration("key", 999) +// # Returns the value if the key exists and the format conversion +// # was successful. Otherwise, the default value is returned. +// v = p.GetInt64("key", 999) +// v = p.GetUint64("key", 999) +// v = p.GetFloat64("key", 123.0) +// v = p.GetString("key", "def") +// v = p.GetDuration("key", 999) // -// As an alterantive properties may be applied with the standard +// As an alternative properties may be applied with the standard // library's flag implementation at any time. // -// # Standard configuration -// v = flag.Int("key", 999, "help message") -// flag.Parse() +// # Standard configuration +// v = flag.Int("key", 999, "help message") +// flag.Parse() // -// # Merge p into the flag set -// p.MustFlag(flag.CommandLine) +// # Merge p into the flag set +// p.MustFlag(flag.CommandLine) // // Properties provides several MustXXX() convenience functions // which will terminate the app if an error occurs. The behavior @@ -119,30 +119,30 @@ // of logging the error set a different ErrorHandler before // you use the Properties package. // -// properties.ErrorHandler = properties.PanicHandler +// properties.ErrorHandler = properties.PanicHandler // -// # Will panic instead of logging an error -// p := properties.MustLoadFile("config.properties") +// # Will panic instead of logging an error +// p := properties.MustLoadFile("config.properties") // // You can also provide your own ErrorHandler function. The only requirement // is that the error handler function must exit after handling the error. // -// properties.ErrorHandler = func(err error) { -// fmt.Println(err) -// os.Exit(1) -// } +// properties.ErrorHandler = func(err error) { +// fmt.Println(err) +// os.Exit(1) +// } // -// # Will write to stdout and then exit -// p := properties.MustLoadFile("config.properties") +// # Will write to stdout and then exit +// p := properties.MustLoadFile("config.properties") // // Properties can also be loaded into a struct via the `Decode` // method, e.g. // -// type S struct { -// A string `properties:"a,default=foo"` -// D time.Duration `properties:"timeout,default=5s"` -// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` -// } +// type S struct { +// A string `properties:"a,default=foo"` +// D time.Duration `properties:"timeout,default=5s"` +// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` +// } // // See `Decode()` method for the full documentation. // @@ -152,5 +152,4 @@ // http://en.wikipedia.org/wiki/.properties // // http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 -// package properties diff --git a/vendor/github.com/magiconair/properties/integrate.go b/vendor/github.com/magiconair/properties/integrate.go index 37baaad95..35d0ae97b 100644 --- a/vendor/github.com/magiconair/properties/integrate.go +++ b/vendor/github.com/magiconair/properties/integrate.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -10,8 +10,9 @@ import "flag" // the respective key for flag.Flag.Name. // // It's use is recommended with command line arguments as in: -// flag.Parse() -// p.MustFlag(flag.CommandLine) +// +// flag.Parse() +// p.MustFlag(flag.CommandLine) func (p *Properties) MustFlag(dst *flag.FlagSet) { m := make(map[string]*flag.Flag) dst.VisitAll(func(f *flag.Flag) { diff --git a/vendor/github.com/magiconair/properties/lex.go b/vendor/github.com/magiconair/properties/lex.go index 014e63f0e..3d15a1f6e 100644 --- a/vendor/github.com/magiconair/properties/lex.go +++ b/vendor/github.com/magiconair/properties/lex.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -72,7 +72,7 @@ type lexer struct { // next returns the next rune in the input. func (l *lexer) next() rune { - if int(l.pos) >= len(l.input) { + if l.pos >= len(l.input) { l.width = 0 return eof } @@ -96,8 +96,8 @@ func (l *lexer) backup() { // emit passes an item back to the client. func (l *lexer) emit(t itemType) { - item := item{t, l.start, string(l.runes)} - l.items <- item + i := item{t, l.start, string(l.runes)} + l.items <- i l.start = l.pos l.runes = l.runes[:0] } @@ -114,7 +114,7 @@ func (l *lexer) appendRune(r rune) { // accept consumes the next rune if it's from the valid set. func (l *lexer) accept(valid string) bool { - if strings.IndexRune(valid, l.next()) >= 0 { + if strings.ContainsRune(valid, l.next()) { return true } l.backup() @@ -123,23 +123,11 @@ func (l *lexer) accept(valid string) bool { // acceptRun consumes a run of runes from the valid set. func (l *lexer) acceptRun(valid string) { - for strings.IndexRune(valid, l.next()) >= 0 { + for strings.ContainsRune(valid, l.next()) { } l.backup() } -// acceptRunUntil consumes a run of runes up to a terminator. -func (l *lexer) acceptRunUntil(term rune) { - for term != l.next() { - } - l.backup() -} - -// hasText returns true if the current parsed text is not empty. -func (l *lexer) isNotEmpty() bool { - return l.pos > l.start -} - // lineNumber reports which line we're on, based on the position of // the previous item returned by nextItem. Doing it this way // means we don't have to worry about peek double counting. @@ -156,9 +144,9 @@ func (l *lexer) errorf(format string, args ...interface{}) stateFn { // nextItem returns the next item from the input. func (l *lexer) nextItem() item { - item := <-l.items - l.lastPos = item.pos - return item + i := <-l.items + l.lastPos = i.pos + return i } // lex creates a new scanner for the input string. @@ -196,9 +184,8 @@ func lexBeforeKey(l *lexer) stateFn { return lexComment case isWhitespace(r): - l.acceptRun(whitespace) l.ignore() - return lexKey + return lexBeforeKey default: l.backup() @@ -279,8 +266,7 @@ func lexValue(l *lexer) stateFn { for { switch r := l.next(); { case isEscape(r): - r := l.peek() - if isEOL(r) { + if isEOL(l.peek()) { l.next() l.acceptRun(whitespace) } else { diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go index 3915c7397..6567e0c71 100644 --- a/vendor/github.com/magiconair/properties/load.go +++ b/vendor/github.com/magiconair/properties/load.go @@ -1,13 +1,12 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package properties import ( - "bytes" "fmt" - "io/ioutil" + "io" "net/http" "os" "strings" @@ -17,53 +16,221 @@ import ( type Encoding uint const ( + // utf8Default is a private placeholder for the zero value of Encoding to + // ensure that it has the correct meaning. UTF8 is the default encoding but + // was assigned a non-zero value which cannot be changed without breaking + // existing code. Clients should continue to use the public constants. + utf8Default Encoding = iota + // UTF8 interprets the input data as UTF-8. - UTF8 Encoding = 1 << iota + UTF8 // ISO_8859_1 interprets the input data as ISO-8859-1. ISO_8859_1 ) +type Loader struct { + // Encoding determines how the data from files and byte buffers + // is interpreted. For URLs the Content-Type header is used + // to determine the encoding of the data. + Encoding Encoding + + // DisableExpansion configures the property expansion of the + // returned property object. When set to true, the property values + // will not be expanded and the Property object will not be checked + // for invalid expansion expressions. + DisableExpansion bool + + // IgnoreMissing configures whether missing files or URLs which return + // 404 are reported as errors. When set to true, missing files and 404 + // status codes are not reported as errors. + IgnoreMissing bool +} + +// Load reads a buffer into a Properties struct. +func (l *Loader) LoadBytes(buf []byte) (*Properties, error) { + return l.loadBytes(buf, l.Encoding) +} + +// LoadReader reads an io.Reader into a Properties struct. +func (l *Loader) LoadReader(r io.Reader) (*Properties, error) { + if buf, err := io.ReadAll(r); err != nil { + return nil, err + } else { + return l.loadBytes(buf, l.Encoding) + } +} + +// LoadAll reads the content of multiple URLs or files in the given order into +// a Properties struct. If IgnoreMissing is true then a 404 status code or +// missing file will not be reported as error. Encoding sets the encoding for +// files. For the URLs see LoadURL for the Content-Type header and the +// encoding. +func (l *Loader) LoadAll(names []string) (*Properties, error) { + all := NewProperties() + for _, name := range names { + n, err := expandName(name) + if err != nil { + return nil, err + } + + var p *Properties + switch { + case strings.HasPrefix(n, "http://"): + p, err = l.LoadURL(n) + case strings.HasPrefix(n, "https://"): + p, err = l.LoadURL(n) + default: + p, err = l.LoadFile(n) + } + if err != nil { + return nil, err + } + all.Merge(p) + } + + all.DisableExpansion = l.DisableExpansion + if all.DisableExpansion { + return all, nil + } + return all, all.check() +} + +// LoadFile reads a file into a Properties struct. +// If IgnoreMissing is true then a missing file will not be +// reported as error. +func (l *Loader) LoadFile(filename string) (*Properties, error) { + data, err := os.ReadFile(filename) + if err != nil { + if l.IgnoreMissing && os.IsNotExist(err) { + LogPrintf("properties: %s not found. skipping", filename) + return NewProperties(), nil + } + return nil, err + } + return l.loadBytes(data, l.Encoding) +} + +// LoadURL reads the content of the URL into a Properties struct. +// +// The encoding is determined via the Content-Type header which +// should be set to 'text/plain'. If the 'charset' parameter is +// missing, 'iso-8859-1' or 'latin1' the encoding is set to +// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the +// encoding is set to UTF-8. A missing content type header is +// interpreted as 'text/plain; charset=utf-8'. +func (l *Loader) LoadURL(url string) (*Properties, error) { + resp, err := http.Get(url) + if err != nil { + return nil, fmt.Errorf("properties: error fetching %q. %s", url, err) + } + defer resp.Body.Close() + + if resp.StatusCode == 404 && l.IgnoreMissing { + LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode) + return NewProperties(), nil + } + + if resp.StatusCode != 200 { + return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("properties: %s error reading response. %s", url, err) + } + + ct := resp.Header.Get("Content-Type") + ct = strings.Join(strings.Fields(ct), "") + var enc Encoding + switch strings.ToLower(ct) { + case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1": + enc = ISO_8859_1 + case "", "text/plain;charset=utf-8": + enc = UTF8 + default: + return nil, fmt.Errorf("properties: invalid content type %s", ct) + } + + return l.loadBytes(body, enc) +} + +func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) { + p, err := parse(convert(buf, enc)) + if err != nil { + return nil, err + } + p.DisableExpansion = l.DisableExpansion + if p.DisableExpansion { + return p, nil + } + return p, p.check() +} + // Load reads a buffer into a Properties struct. func Load(buf []byte, enc Encoding) (*Properties, error) { - return loadBuf(buf, enc) + l := &Loader{Encoding: enc} + return l.LoadBytes(buf) } // LoadString reads an UTF8 string into a properties struct. func LoadString(s string) (*Properties, error) { - return loadBuf([]byte(s), UTF8) + l := &Loader{Encoding: UTF8} + return l.LoadBytes([]byte(s)) +} + +// LoadMap creates a new Properties struct from a string map. +func LoadMap(m map[string]string) *Properties { + p := NewProperties() + for k, v := range m { + p.Set(k, v) + } + return p } // LoadFile reads a file into a Properties struct. func LoadFile(filename string, enc Encoding) (*Properties, error) { - return loadFiles([]string{filename}, enc, false) + l := &Loader{Encoding: enc} + return l.LoadAll([]string{filename}) +} + +// LoadReader reads an io.Reader into a Properties struct. +func LoadReader(r io.Reader, enc Encoding) (*Properties, error) { + l := &Loader{Encoding: enc} + return l.LoadReader(r) } // LoadFiles reads multiple files in the given order into // a Properties struct. If 'ignoreMissing' is true then // non-existent files will not be reported as error. func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - return loadFiles(filenames, enc, ignoreMissing) + l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} + return l.LoadAll(filenames) } // LoadURL reads the content of the URL into a Properties struct. -// -// The encoding is determined via the Content-Type header which -// should be set to 'text/plain'. If the 'charset' parameter is -// missing, 'iso-8859-1' or 'latin1' the encoding is set to -// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the -// encoding is set to UTF-8. A missing content type header is -// interpreted as 'text/plain; charset=utf-8'. +// See Loader#LoadURL for details. func LoadURL(url string) (*Properties, error) { - return loadURLs([]string{url}, false) + l := &Loader{Encoding: UTF8} + return l.LoadAll([]string{url}) } // LoadURLs reads the content of multiple URLs in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code will -// not be reported as error. See LoadURL for the Content-Type header +// Properties struct. If IgnoreMissing is true then a 404 status code will +// not be reported as error. See Loader#LoadURL for the Content-Type header // and the encoding. func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - return loadURLs(urls, ignoreMissing) + l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing} + return l.LoadAll(urls) +} + +// LoadAll reads the content of multiple URLs or files in the given order into a +// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will +// not be reported as error. Encoding sets the encoding for files. For the URLs please see +// LoadURL for the Content-Type header and the encoding. +func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) { + l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} + return l.LoadAll(names) } // MustLoadString reads an UTF8 string into a Properties struct and @@ -72,6 +239,12 @@ func MustLoadString(s string) *Properties { return must(LoadString(s)) } +// MustLoadSReader reads an io.Reader into a Properties struct and +// panics on error. +func MustLoadReader(r io.Reader, enc Encoding) *Properties { + return must(LoadReader(r, enc)) +} + // MustLoadFile reads a file into a Properties struct and // panics on error. func MustLoadFile(filename string, enc Encoding) *Properties { @@ -91,81 +264,19 @@ func MustLoadURL(url string) *Properties { return must(LoadURL(url)) } -// MustLoadFiles reads the content of multiple URLs in the given order into a +// MustLoadURLs reads the content of multiple URLs in the given order into a // Properties struct and panics on error. If 'ignoreMissing' is true then a 404 // status code will not be reported as error. func MustLoadURLs(urls []string, ignoreMissing bool) *Properties { return must(LoadURLs(urls, ignoreMissing)) } -func loadBuf(buf []byte, enc Encoding) (*Properties, error) { - p, err := parse(convert(buf, enc)) - if err != nil { - return nil, err - } - return p, p.check() -} - -func loadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - var buf bytes.Buffer - for _, filename := range filenames { - f, err := expandFilename(filename) - if err != nil { - return nil, err - } - - data, err := ioutil.ReadFile(f) - if err != nil { - if ignoreMissing && os.IsNotExist(err) { - LogPrintf("properties: %s not found. skipping", filename) - continue - } - return nil, err - } - - // concatenate the buffers and add a new line in case - // the previous file didn't end with a new line - buf.Write(data) - buf.WriteRune('\n') - } - return loadBuf(buf.Bytes(), enc) -} - -func loadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - var buf bytes.Buffer - for _, u := range urls { - resp, err := http.Get(u) - if err != nil { - return nil, fmt.Errorf("properties: error fetching %q. %s", u, err) - } - if resp.StatusCode == 404 && ignoreMissing { - LogPrintf("properties: %s returned %d. skipping", u, resp.StatusCode) - continue - } - if resp.StatusCode != 200 { - return nil, fmt.Errorf("properties: %s returned %d", u, resp.StatusCode) - } - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - return nil, fmt.Errorf("properties: %s error reading response. %s", u, err) - } - - ct := resp.Header.Get("Content-Type") - var enc Encoding - switch strings.ToLower(ct) { - case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1": - enc = ISO_8859_1 - case "", "text/plain; charset=utf-8": - enc = UTF8 - default: - return nil, fmt.Errorf("properties: invalid content type %s", ct) - } - - buf.WriteString(convert(body, enc)) - buf.WriteRune('\n') - } - return loadBuf(buf.Bytes(), UTF8) +// MustLoadAll reads the content of multiple URLs or files in the given order into a +// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will +// not be reported as error. Encoding sets the encoding for files. For the URLs please see +// LoadURL for the Content-Type header and the encoding. It panics on error. +func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties { + return must(LoadAll(names, enc, ignoreMissing)) } func must(p *Properties, err error) *Properties { @@ -175,12 +286,12 @@ func must(p *Properties, err error) *Properties { return p } -// expandFilename expands ${ENV_VAR} expressions in a filename. +// expandName expands ${ENV_VAR} expressions in a name. // If the environment variable does not exist then it will be replaced // with an empty string. Malformed expressions like "${ENV_VAR" will // be reported as error. -func expandFilename(filename string) (string, error) { - return expand(filename, make(map[string]bool), "${", "}", make(map[string]string)) +func expandName(name string) (string, error) { + return expand(name, []string{}, "${", "}", make(map[string]string)) } // Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. @@ -188,7 +299,7 @@ func expandFilename(filename string) (string, error) { // first 256 unicode code points cover ISO-8859-1. func convert(buf []byte, enc Encoding) string { switch enc { - case UTF8: + case utf8Default, UTF8: return string(buf) case ISO_8859_1: runes := make([]rune, len(buf)) diff --git a/vendor/github.com/magiconair/properties/parser.go b/vendor/github.com/magiconair/properties/parser.go index ff0e1e157..fccfd39f6 100644 --- a/vendor/github.com/magiconair/properties/parser.go +++ b/vendor/github.com/magiconair/properties/parser.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -59,14 +59,6 @@ func (p *parser) errorf(format string, args ...interface{}) { panic(fmt.Errorf(format, args...)) } -func (p *parser) expect(expected itemType) (token item) { - token = p.lex.nextItem() - if token.typ != expected { - p.unexpected(token) - } - return token -} - func (p *parser) expectOneOf(expected ...itemType) (token item) { token = p.lex.nextItem() for _, v := range expected { @@ -91,5 +83,4 @@ func (p *parser) recover(errp *error) { } *errp = e.(error) } - return } diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go index 884ef4e07..fb2f7b404 100644 --- a/vendor/github.com/magiconair/properties/properties.go +++ b/vendor/github.com/magiconair/properties/properties.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -8,17 +8,21 @@ package properties // BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. import ( + "bytes" "fmt" "io" "log" "os" "regexp" + "sort" "strconv" "strings" "time" "unicode/utf8" ) +const maxExpansionDepth = 64 + // ErrorHandlerFunc defines the type of function which handles failures // of the MustXXX() functions. An error handler function must exit // the application after handling the error. @@ -28,8 +32,10 @@ type ErrorHandlerFunc func(error) // functions. The default is LogFatalHandler. var ErrorHandler ErrorHandlerFunc = LogFatalHandler +// LogHandlerFunc defines the function prototype for logging errors. type LogHandlerFunc func(fmt string, args ...interface{}) +// LogPrintf defines a log handler which uses log.Printf. var LogPrintf LogHandlerFunc = log.Printf // LogFatalHandler handles the error by logging a fatal error and exiting. @@ -65,6 +71,9 @@ type Properties struct { // Stores the keys in order of appearance. k []string + + // WriteSeparator specifies the separator of key and value while writing the properties. + WriteSeparator string } // NewProperties creates a new Properties struct with the default @@ -79,6 +88,17 @@ func NewProperties() *Properties { } } +// Load reads a buffer into the given Properties struct. +func (p *Properties) Load(buf []byte, enc Encoding) error { + l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion} + newProperties, err := l.LoadBytes(buf) + if err != nil { + return err + } + p.Merge(newProperties) + return nil +} + // Get returns the expanded value for the given key if exists. // Otherwise, ok is false. func (p *Properties) Get(key string) (value string, ok bool) { @@ -90,13 +110,13 @@ func (p *Properties) Get(key string) (value string, ok bool) { return "", false } - expanded, err := p.expand(v) + expanded, err := p.expand(key, v) // we guarantee that the expanded value is free of // circular references and malformed expressions // so we panic if we still get an error here. if err != nil { - ErrorHandler(fmt.Errorf("%s in %q", err, key+" = "+v)) + ErrorHandler(err) } return expanded, true @@ -444,6 +464,8 @@ func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { pp := NewProperties() for _, k := range p.k { if re.MatchString(k) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) pp.Set(k, p.m[k]) } } @@ -456,6 +478,8 @@ func (p *Properties) FilterPrefix(prefix string) *Properties { pp := NewProperties() for _, k := range p.k { if strings.HasPrefix(k, prefix) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) pp.Set(k, p.m[k]) } } @@ -469,6 +493,9 @@ func (p *Properties) FilterStripPrefix(prefix string) *Properties { n := len(prefix) for _, k := range p.k { if len(k) > len(prefix) && strings.HasPrefix(k, prefix) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference + // TODO(fs): this function should probably return an error but the signature is fixed pp.Set(k[n:], p.m[k]) } } @@ -483,9 +510,7 @@ func (p *Properties) Len() int { // Keys returns all keys in the same order as in the input. func (p *Properties) Keys() []string { keys := make([]string, len(p.k)) - for i, k := range p.k { - keys[i] = k - } + copy(keys, p.k) return keys } @@ -504,6 +529,9 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { if p.DisableExpansion { prev, ok = p.Get(key) p.m[key] = value + if !ok { + p.k = append(p.k, key) + } return prev, ok, nil } @@ -515,7 +543,7 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { p.m[key] = value // now check for a circular reference - _, err = p.expand(value) + _, err = p.expand(key, value) if err != nil { // revert to the previous state @@ -535,6 +563,13 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { return prev, ok, nil } +// SetValue sets property key to the default string value +// as defined by fmt.Sprintf("%v"). +func (p *Properties) SetValue(key string, value interface{}) error { + _, _, err := p.Set(key, fmt.Sprintf("%v", value)) + return err +} + // MustSet sets the property key to the corresponding value. // If a value for key existed before then ok is true and prev // contains the previous value. An empty key is silently ignored. @@ -556,6 +591,12 @@ func (p *Properties) String() string { return s } +// Sort sorts the properties keys in alphabetical order. +// This is helpfully before writing the properties. +func (p *Properties) Sort() { + sort.Strings(p.k) +} + // Write writes all unexpanded 'key = value' pairs to the given writer. // Write returns the number of bytes written and any write error encountered. func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { @@ -596,7 +637,7 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i } for _, c := range comments { - x, err = fmt.Fprintf(w, "%s%s\n", prefix, encode(c, "", enc)) + x, err = fmt.Fprintf(w, "%s%s\n", prefix, c) if err != nil { return } @@ -605,8 +646,11 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i } } } - - x, err = fmt.Fprintf(w, "%s = %s\n", encode(key, " :", enc), encode(value, "", enc)) + sep := " = " + if p.WriteSeparator != "" { + sep = p.WriteSeparator + } + x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc)) if err != nil { return } @@ -615,6 +659,30 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i return } +// Map returns a copy of the properties as a map. +func (p *Properties) Map() map[string]string { + m := make(map[string]string) + for k, v := range p.m { + m[k] = v + } + return m +} + +// FilterFunc returns a copy of the properties which includes the values which passed all filters. +func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties { + pp := NewProperties() +outer: + for k, v := range p.m { + for _, f := range filters { + if !f(k, v) { + continue outer + } + pp.Set(k, v) + } + } + return pp +} + // ---------------------------------------------------------------------------- // Delete removes the key and its comments. @@ -624,67 +692,95 @@ func (p *Properties) Delete(key string) { newKeys := []string{} for _, k := range p.k { if k != key { - newKeys = append(newKeys, key) + newKeys = append(newKeys, k) } } p.k = newKeys } +// Merge merges properties, comments and keys from other *Properties into p +func (p *Properties) Merge(other *Properties) { + for _, k := range other.k { + if _, ok := p.m[k]; !ok { + p.k = append(p.k, k) + } + } + for k, v := range other.m { + p.m[k] = v + } + for k, v := range other.c { + p.c[k] = v + } +} + // ---------------------------------------------------------------------------- // check expands all values and returns an error if a circular reference or // a malformed expression was found. func (p *Properties) check() error { - for _, value := range p.m { - if _, err := p.expand(value); err != nil { + for key, value := range p.m { + if _, err := p.expand(key, value); err != nil { return err } } return nil } -func (p *Properties) expand(input string) (string, error) { +func (p *Properties) expand(key, input string) (string, error) { // no pre/postfix -> nothing to expand if p.Prefix == "" && p.Postfix == "" { return input, nil } - return expand(input, make(map[string]bool), p.Prefix, p.Postfix, p.m) + return expand(input, []string{key}, p.Prefix, p.Postfix, p.m) } // expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. // The function keeps track of the keys that were already expanded and stops if it // detects a circular reference or a malformed expression of the form '(prefix)key'. -func expand(s string, keys map[string]bool, prefix, postfix string, values map[string]string) (string, error) { - start := strings.Index(s, prefix) - if start == -1 { - return s, nil +func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) { + if len(keys) > maxExpansionDepth { + return "", fmt.Errorf("expansion too deep") } - keyStart := start + len(prefix) - keyLen := strings.Index(s[keyStart:], postfix) - if keyLen == -1 { - return "", fmt.Errorf("malformed expression") - } - - end := keyStart + keyLen + len(postfix) - 1 - key := s[keyStart : keyStart+keyLen] + for { + start := strings.Index(s, prefix) + if start == -1 { + return s, nil + } - // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) + keyStart := start + len(prefix) + keyLen := strings.Index(s[keyStart:], postfix) + if keyLen == -1 { + return "", fmt.Errorf("malformed expression") + } - if _, ok := keys[key]; ok { - return "", fmt.Errorf("circular reference") - } + end := keyStart + keyLen + len(postfix) - 1 + key := s[keyStart : keyStart+keyLen] - val, ok := values[key] - if !ok { - val = os.Getenv(key) - } + // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) - // remember that we've seen the key - keys[key] = true + for _, k := range keys { + if key == k { + var b bytes.Buffer + b.WriteString("circular reference in:\n") + for _, k1 := range keys { + fmt.Fprintf(&b, "%s=%s\n", k1, values[k1]) + } + return "", fmt.Errorf(b.String()) + } + } - return expand(s[:start]+val+s[end+1:], keys, prefix, postfix, values) + val, ok := values[key] + if !ok { + val = os.Getenv(key) + } + new_val, err := expand(val, append(keys, key), prefix, postfix, values) + if err != nil { + return "", err + } + s = s[:start] + new_val + s[end+1:] + } } // encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. @@ -737,6 +833,8 @@ func escape(r rune, special string) string { return "\\r" case '\t': return "\\t" + case '\\': + return "\\\\" default: if strings.ContainsRune(special, r) { return "\\" + string(r) diff --git a/vendor/github.com/magiconair/properties/rangecheck.go b/vendor/github.com/magiconair/properties/rangecheck.go index d9ce2806b..dbd60b36e 100644 --- a/vendor/github.com/magiconair/properties/rangecheck.go +++ b/vendor/github.com/magiconair/properties/rangecheck.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/mattn/go-runewidth/.travis.yml b/vendor/github.com/mattn/go-runewidth/.travis.yml deleted file mode 100644 index 5c9c2a30f..000000000 --- a/vendor/github.com/mattn/go-runewidth/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -go: - - tip -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL diff --git a/vendor/github.com/mattn/go-runewidth/README.mkd b/vendor/github.com/mattn/go-runewidth/README.mkd deleted file mode 100644 index ffb0edd2c..000000000 --- a/vendor/github.com/mattn/go-runewidth/README.mkd +++ /dev/null @@ -1,26 +0,0 @@ -go-runewidth -============ - -[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) -[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) -[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) - -Provides functions to get fixed width of the character or string. - -Usage ------ - -```go -runewidth.StringWidth("つのだ☆HIRO") == 12 -``` - - -Author ------- - -Yasuhiro Matsumoto - -License -------- - -under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go index 3fbf33d59..7dfbb3be9 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -1,380 +1,262 @@ package runewidth -var EastAsianWidth = IsEastAsian() -var DefaultCondition = &Condition{EastAsianWidth} +import ( + "os" + "strings" + + "github.com/rivo/uniseg" +) + +//go:generate go run script/generate.go + +var ( + // EastAsianWidth will be set true if the current locale is CJK + EastAsianWidth bool + + // StrictEmojiNeutral should be set false if handle broken fonts + StrictEmojiNeutral bool = true + + // DefaultCondition is a condition in current locale + DefaultCondition = &Condition{ + EastAsianWidth: false, + StrictEmojiNeutral: true, + } +) + +func init() { + handleEnv() +} + +func handleEnv() { + env := os.Getenv("RUNEWIDTH_EASTASIAN") + if env == "" { + EastAsianWidth = IsEastAsian() + } else { + EastAsianWidth = env == "1" + } + // update DefaultCondition + if DefaultCondition.EastAsianWidth != EastAsianWidth { + DefaultCondition.EastAsianWidth = EastAsianWidth + if len(DefaultCondition.combinedLut) > 0 { + DefaultCondition.combinedLut = DefaultCondition.combinedLut[:0] + CreateLUT() + } + } +} type interval struct { first rune last rune } -var combining = []interval{ - {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489}, - {0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, - {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603}, - {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670}, - {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, - {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A}, - {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902}, - {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D}, - {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981}, - {0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, - {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C}, - {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, - {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, - {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, - {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C}, - {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D}, - {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0}, - {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, - {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC}, - {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, - {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, - {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, - {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, - {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, - {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, - {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, - {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, - {0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F}, - {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, - {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD}, - {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD}, - {0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922}, - {0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B}, - {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34}, - {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, - {0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF}, - {0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063}, - {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F}, - {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, - {0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, - {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, - {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169}, - {0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F}, - {0xE0100, 0xE01EF}, +type table []interval + +func inTables(r rune, ts ...table) bool { + for _, t := range ts { + if inTable(r, t) { + return true + } + } + return false } -type ctype int +func inTable(r rune, t table) bool { + if r < t[0].first { + return false + } -const ( - narrow ctype = iota - ambiguous - wide - halfwidth - fullwidth - neutral -) + bot := 0 + top := len(t) - 1 + for top >= bot { + mid := (bot + top) >> 1 -type intervalType struct { - first rune - last rune - ctype ctype + switch { + case t[mid].last < r: + bot = mid + 1 + case t[mid].first > r: + top = mid - 1 + default: + return true + } + } + + return false +} + +var private = table{ + {0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD}, } -var ctypes = []intervalType{ - {0x0020, 0x007E, narrow}, - {0x00A1, 0x00A1, ambiguous}, - {0x00A2, 0x00A3, narrow}, - {0x00A4, 0x00A4, ambiguous}, - {0x00A5, 0x00A6, narrow}, - {0x00A7, 0x00A8, ambiguous}, - {0x00AA, 0x00AA, ambiguous}, - {0x00AC, 0x00AC, narrow}, - {0x00AD, 0x00AE, ambiguous}, - {0x00AF, 0x00AF, narrow}, - {0x00B0, 0x00B4, ambiguous}, - {0x00B6, 0x00BA, ambiguous}, - {0x00BC, 0x00BF, ambiguous}, - {0x00C6, 0x00C6, ambiguous}, - {0x00D0, 0x00D0, ambiguous}, - {0x00D7, 0x00D8, ambiguous}, - {0x00DE, 0x00E1, ambiguous}, - {0x00E6, 0x00E6, ambiguous}, - {0x00E8, 0x00EA, ambiguous}, - {0x00EC, 0x00ED, ambiguous}, - {0x00F0, 0x00F0, ambiguous}, - {0x00F2, 0x00F3, ambiguous}, - {0x00F7, 0x00FA, ambiguous}, - {0x00FC, 0x00FC, ambiguous}, - {0x00FE, 0x00FE, ambiguous}, - {0x0101, 0x0101, ambiguous}, - {0x0111, 0x0111, ambiguous}, - {0x0113, 0x0113, ambiguous}, - {0x011B, 0x011B, ambiguous}, - {0x0126, 0x0127, ambiguous}, - {0x012B, 0x012B, ambiguous}, - {0x0131, 0x0133, ambiguous}, - {0x0138, 0x0138, ambiguous}, - {0x013F, 0x0142, ambiguous}, - {0x0144, 0x0144, ambiguous}, - {0x0148, 0x014B, ambiguous}, - {0x014D, 0x014D, ambiguous}, - {0x0152, 0x0153, ambiguous}, - {0x0166, 0x0167, ambiguous}, - {0x016B, 0x016B, ambiguous}, - {0x01CE, 0x01CE, ambiguous}, - {0x01D0, 0x01D0, ambiguous}, - {0x01D2, 0x01D2, ambiguous}, - {0x01D4, 0x01D4, ambiguous}, - {0x01D6, 0x01D6, ambiguous}, - {0x01D8, 0x01D8, ambiguous}, - {0x01DA, 0x01DA, ambiguous}, - {0x01DC, 0x01DC, ambiguous}, - {0x0251, 0x0251, ambiguous}, - {0x0261, 0x0261, ambiguous}, - {0x02C4, 0x02C4, ambiguous}, - {0x02C7, 0x02C7, ambiguous}, - {0x02C9, 0x02CB, ambiguous}, - {0x02CD, 0x02CD, ambiguous}, - {0x02D0, 0x02D0, ambiguous}, - {0x02D8, 0x02DB, ambiguous}, - {0x02DD, 0x02DD, ambiguous}, - {0x02DF, 0x02DF, ambiguous}, - {0x0300, 0x036F, ambiguous}, - {0x0391, 0x03A2, ambiguous}, - {0x03A3, 0x03A9, ambiguous}, - {0x03B1, 0x03C1, ambiguous}, - {0x03C3, 0x03C9, ambiguous}, - {0x0401, 0x0401, ambiguous}, - {0x0410, 0x044F, ambiguous}, - {0x0451, 0x0451, ambiguous}, - {0x1100, 0x115F, wide}, - {0x2010, 0x2010, ambiguous}, - {0x2013, 0x2016, ambiguous}, - {0x2018, 0x2019, ambiguous}, - {0x201C, 0x201D, ambiguous}, - {0x2020, 0x2022, ambiguous}, - {0x2024, 0x2027, ambiguous}, - {0x2030, 0x2030, ambiguous}, - {0x2032, 0x2033, ambiguous}, - {0x2035, 0x2035, ambiguous}, - {0x203B, 0x203B, ambiguous}, - {0x203E, 0x203E, ambiguous}, - {0x2074, 0x2074, ambiguous}, - {0x207F, 0x207F, ambiguous}, - {0x2081, 0x2084, ambiguous}, - {0x20A9, 0x20A9, halfwidth}, - {0x20AC, 0x20AC, ambiguous}, - {0x2103, 0x2103, ambiguous}, - {0x2105, 0x2105, ambiguous}, - {0x2109, 0x2109, ambiguous}, - {0x2113, 0x2113, ambiguous}, - {0x2116, 0x2116, ambiguous}, - {0x2121, 0x2122, ambiguous}, - {0x2126, 0x2126, ambiguous}, - {0x212B, 0x212B, ambiguous}, - {0x2153, 0x2154, ambiguous}, - {0x215B, 0x215E, ambiguous}, - {0x2160, 0x216B, ambiguous}, - {0x2170, 0x2179, ambiguous}, - {0x2189, 0x218A, ambiguous}, - {0x2190, 0x2199, ambiguous}, - {0x21B8, 0x21B9, ambiguous}, - {0x21D2, 0x21D2, ambiguous}, - {0x21D4, 0x21D4, ambiguous}, - {0x21E7, 0x21E7, ambiguous}, - {0x2200, 0x2200, ambiguous}, - {0x2202, 0x2203, ambiguous}, - {0x2207, 0x2208, ambiguous}, - {0x220B, 0x220B, ambiguous}, - {0x220F, 0x220F, ambiguous}, - {0x2211, 0x2211, ambiguous}, - {0x2215, 0x2215, ambiguous}, - {0x221A, 0x221A, ambiguous}, - {0x221D, 0x2220, ambiguous}, - {0x2223, 0x2223, ambiguous}, - {0x2225, 0x2225, ambiguous}, - {0x2227, 0x222C, ambiguous}, - {0x222E, 0x222E, ambiguous}, - {0x2234, 0x2237, ambiguous}, - {0x223C, 0x223D, ambiguous}, - {0x2248, 0x2248, ambiguous}, - {0x224C, 0x224C, ambiguous}, - {0x2252, 0x2252, ambiguous}, - {0x2260, 0x2261, ambiguous}, - {0x2264, 0x2267, ambiguous}, - {0x226A, 0x226B, ambiguous}, - {0x226E, 0x226F, ambiguous}, - {0x2282, 0x2283, ambiguous}, - {0x2286, 0x2287, ambiguous}, - {0x2295, 0x2295, ambiguous}, - {0x2299, 0x2299, ambiguous}, - {0x22A5, 0x22A5, ambiguous}, - {0x22BF, 0x22BF, ambiguous}, - {0x2312, 0x2312, ambiguous}, - {0x2329, 0x232A, wide}, - {0x2460, 0x24E9, ambiguous}, - {0x24EB, 0x254B, ambiguous}, - {0x2550, 0x2573, ambiguous}, - {0x2580, 0x258F, ambiguous}, - {0x2592, 0x2595, ambiguous}, - {0x25A0, 0x25A1, ambiguous}, - {0x25A3, 0x25A9, ambiguous}, - {0x25B2, 0x25B3, ambiguous}, - {0x25B6, 0x25B7, ambiguous}, - {0x25BC, 0x25BD, ambiguous}, - {0x25C0, 0x25C1, ambiguous}, - {0x25C6, 0x25C8, ambiguous}, - {0x25CB, 0x25CB, ambiguous}, - {0x25CE, 0x25D1, ambiguous}, - {0x25E2, 0x25E5, ambiguous}, - {0x25EF, 0x25EF, ambiguous}, - {0x2605, 0x2606, ambiguous}, - {0x2609, 0x2609, ambiguous}, - {0x260E, 0x260F, ambiguous}, - {0x2614, 0x2615, ambiguous}, - {0x261C, 0x261C, ambiguous}, - {0x261E, 0x261E, ambiguous}, - {0x2640, 0x2640, ambiguous}, - {0x2642, 0x2642, ambiguous}, - {0x2660, 0x2661, ambiguous}, - {0x2663, 0x2665, ambiguous}, - {0x2667, 0x266A, ambiguous}, - {0x266C, 0x266D, ambiguous}, - {0x266F, 0x266F, ambiguous}, - {0x269E, 0x269F, ambiguous}, - {0x26BE, 0x26BF, ambiguous}, - {0x26C4, 0x26CD, ambiguous}, - {0x26CF, 0x26E1, ambiguous}, - {0x26E3, 0x26E3, ambiguous}, - {0x26E8, 0x26FF, ambiguous}, - {0x273D, 0x273D, ambiguous}, - {0x2757, 0x2757, ambiguous}, - {0x2776, 0x277F, ambiguous}, - {0x27E6, 0x27ED, narrow}, - {0x2985, 0x2986, narrow}, - {0x2B55, 0x2B59, ambiguous}, - {0x2E80, 0x2E9A, wide}, - {0x2E9B, 0x2EF4, wide}, - {0x2F00, 0x2FD6, wide}, - {0x2FF0, 0x2FFC, wide}, - {0x3000, 0x3000, fullwidth}, - {0x3001, 0x303E, wide}, - {0x3041, 0x3097, wide}, - {0x3099, 0x3100, wide}, - {0x3105, 0x312E, wide}, - {0x3131, 0x318F, wide}, - {0x3190, 0x31BB, wide}, - {0x31C0, 0x31E4, wide}, - {0x31F0, 0x321F, wide}, - {0x3220, 0x3247, wide}, - {0x3248, 0x324F, ambiguous}, - {0x3250, 0x32FF, wide}, - {0x3300, 0x4DBF, wide}, - {0x4E00, 0xA48D, wide}, - {0xA490, 0xA4C7, wide}, - {0xA960, 0xA97D, wide}, - {0xAC00, 0xD7A4, wide}, - {0xE000, 0xF8FF, ambiguous}, - {0xF900, 0xFAFF, wide}, - {0xFE00, 0xFE0F, ambiguous}, - {0xFE10, 0xFE1A, wide}, - {0xFE30, 0xFE53, wide}, - {0xFE54, 0xFE67, wide}, - {0xFE68, 0xFE6C, wide}, - {0xFF01, 0xFF60, fullwidth}, - {0xFF61, 0xFFBF, halfwidth}, - {0xFFC2, 0xFFC8, halfwidth}, - {0xFFCA, 0xFFD0, halfwidth}, - {0xFFD2, 0xFFD8, halfwidth}, - {0xFFDA, 0xFFDD, halfwidth}, - {0xFFE0, 0xFFE7, fullwidth}, - {0xFFE8, 0xFFEF, halfwidth}, - {0xFFFD, 0xFFFE, ambiguous}, - {0x1B000, 0x1B002, wide}, - {0x1F100, 0x1F10A, ambiguous}, - {0x1F110, 0x1F12D, ambiguous}, - {0x1F130, 0x1F169, ambiguous}, - {0x1F170, 0x1F19B, ambiguous}, - {0x1F200, 0x1F203, wide}, - {0x1F210, 0x1F23B, wide}, - {0x1F240, 0x1F249, wide}, - {0x1F250, 0x1F252, wide}, - {0x20000, 0x2FFFE, wide}, - {0x30000, 0x3FFFE, wide}, - {0xE0100, 0xE01F0, ambiguous}, - {0xF0000, 0xFFFFD, ambiguous}, - {0x100000, 0x10FFFE, ambiguous}, +var nonprint = table{ + {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, + {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, + {0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, } +// Condition have flag EastAsianWidth whether the current locale is CJK or not. type Condition struct { - EastAsianWidth bool + combinedLut []byte + EastAsianWidth bool + StrictEmojiNeutral bool } +// NewCondition return new instance of Condition which is current locale. func NewCondition() *Condition { - return &Condition{EastAsianWidth} + return &Condition{ + EastAsianWidth: EastAsianWidth, + StrictEmojiNeutral: StrictEmojiNeutral, + } } // RuneWidth returns the number of cells in r. // See http://www.unicode.org/reports/tr11/ func (c *Condition) RuneWidth(r rune) int { - if r == 0 { + if r < 0 || r > 0x10FFFF { return 0 } - if r < 32 || (r >= 0x7f && r < 0xa0) { - return 1 + if len(c.combinedLut) > 0 { + return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3 } - for _, iv := range combining { - if iv.first <= r && r <= iv.last { + // optimized version, verified by TestRuneWidthChecksums() + if !c.EastAsianWidth { + switch { + case r < 0x20: + return 0 + case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint + return 0 + case r < 0x300: + return 1 + case inTable(r, narrow): + return 1 + case inTables(r, nonprint, combining): return 0 + case inTable(r, doublewidth): + return 2 + default: + return 1 + } + } else { + switch { + case inTables(r, nonprint, combining): + return 0 + case inTable(r, narrow): + return 1 + case inTables(r, ambiguous, doublewidth): + return 2 + case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow): + return 2 + default: + return 1 } } +} - if c.EastAsianWidth && IsAmbiguousWidth(r) { - return 2 +// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation. +// This should not be called concurrently with other operations on c. +// If options in c is changed, CreateLUT should be called again. +func (c *Condition) CreateLUT() { + const max = 0x110000 + lut := c.combinedLut + if len(c.combinedLut) != 0 { + // Remove so we don't use it. + c.combinedLut = nil + } else { + lut = make([]byte, max/2) } - - if r >= 0x1100 && - (r <= 0x115f || r == 0x2329 || r == 0x232a || - (r >= 0x2e80 && r <= 0xa4cf && r != 0x303f) || - (r >= 0xac00 && r <= 0xd7a3) || - (r >= 0xf900 && r <= 0xfaff) || - (r >= 0xfe30 && r <= 0xfe6f) || - (r >= 0xff00 && r <= 0xff60) || - (r >= 0xffe0 && r <= 0xffe6) || - (r >= 0x20000 && r <= 0x2fffd) || - (r >= 0x30000 && r <= 0x3fffd)) { - return 2 + for i := range lut { + i32 := int32(i * 2) + x0 := c.RuneWidth(i32) + x1 := c.RuneWidth(i32 + 1) + lut[i] = uint8(x0) | uint8(x1)<<4 } - return 1 + c.combinedLut = lut } +// StringWidth return width as you can see func (c *Condition) StringWidth(s string) (width int) { - for _, r := range []rune(s) { - width += c.RuneWidth(r) + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // Our best guess at this point is to use the width of the first non-zero-width rune. + } + } + width += chWidth } - return width + return } +// Truncate return string truncated with w cells func (c *Condition) Truncate(s string, w int, tail string) string { if c.StringWidth(s) <= w { return s } - r := []rune(s) - tw := c.StringWidth(tail) - w -= tw - width := 0 - i := 0 - for ; i < len(r); i++ { - cw := c.RuneWidth(r[i]) - if width+cw > w { + w -= c.StringWidth(tail) + var width int + pos := len(s) + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // See StringWidth() for details. + } + } + if width+chWidth > w { + pos, _ = g.Positions() break } - width += cw + width += chWidth + } + return s[:pos] + tail +} + +// TruncateLeft cuts w cells from the beginning of the `s`. +func (c *Condition) TruncateLeft(s string, w int, prefix string) string { + if c.StringWidth(s) <= w { + return prefix + } + + var width int + pos := len(s) + + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // See StringWidth() for details. + } + } + + if width+chWidth > w { + if width < w { + _, pos = g.Positions() + prefix += strings.Repeat(" ", width+chWidth-w) + } else { + pos, _ = g.Positions() + } + + break + } + + width += chWidth } - return string(r[0:i]) + tail + + return prefix + s[pos:] } +// Wrap return string wrapped with w cells func (c *Condition) Wrap(s string, w int) string { width := 0 out := "" - for _, r := range []rune(s) { - cw := RuneWidth(r) + for _, r := range s { + cw := c.RuneWidth(r) if r == '\n' { out += string(r) width = 0 @@ -392,6 +274,7 @@ func (c *Condition) Wrap(s string, w int) string { return out } +// FillLeft return string filled in left by spaces in w cells func (c *Condition) FillLeft(s string, w int) string { width := c.StringWidth(s) count := w - width @@ -405,6 +288,7 @@ func (c *Condition) FillLeft(s string, w int) string { return s } +// FillRight return string filled in left by spaces in w cells func (c *Condition) FillRight(s string, w int) string { width := c.StringWidth(s) count := w - width @@ -424,41 +308,51 @@ func RuneWidth(r rune) int { return DefaultCondition.RuneWidth(r) } -func ct(r rune) ctype { - for _, iv := range ctypes { - if iv.first <= r && r <= iv.last { - return iv.ctype - } - } - return neutral -} - // IsAmbiguousWidth returns whether is ambiguous width or not. func IsAmbiguousWidth(r rune) bool { - return ct(r) == ambiguous + return inTables(r, private, ambiguous) } -// IsAmbiguousWidth returns whether is ambiguous width or not. +// IsNeutralWidth returns whether is neutral width or not. func IsNeutralWidth(r rune) bool { - return ct(r) == neutral + return inTable(r, neutral) } +// StringWidth return width as you can see func StringWidth(s string) (width int) { return DefaultCondition.StringWidth(s) } +// Truncate return string truncated with w cells func Truncate(s string, w int, tail string) string { return DefaultCondition.Truncate(s, w, tail) } +// TruncateLeft cuts w cells from the beginning of the `s`. +func TruncateLeft(s string, w int, prefix string) string { + return DefaultCondition.TruncateLeft(s, w, prefix) +} + +// Wrap return string wrapped with w cells func Wrap(s string, w int) string { return DefaultCondition.Wrap(s, w) } +// FillLeft return string filled in left by spaces in w cells func FillLeft(s string, w int) string { return DefaultCondition.FillLeft(s, w) } +// FillRight return string filled in left by spaces in w cells func FillRight(s string, w int) string { return DefaultCondition.FillRight(s, w) } + +// CreateLUT will create an in-memory lookup table of 557055 bytes for faster operation. +// This should not be called concurrently with other operations. +func CreateLUT() { + if len(DefaultCondition.combinedLut) > 0 { + return + } + DefaultCondition.CreateLUT() +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go index 0ce32c5e7..c2abbc2db 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_js.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -1,4 +1,5 @@ -// +build js +//go:build js && !appengine +// +build js,!appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go index a4495909d..5a31d738e 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -1,4 +1,5 @@ -// +build !windows,!js +//go:build !windows && !js && !appengine +// +build !windows,!js,!appengine package runewidth @@ -10,20 +11,25 @@ import ( var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) -func IsEastAsian() bool { - locale := os.Getenv("LC_CTYPE") - if locale == "" { - locale = os.Getenv("LANG") - } - - // ignore C locale - if locale == "POSIX" || locale == "C" { - return false - } - if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { - return false - } +var mblenTable = map[string]int{ + "utf-8": 6, + "utf8": 6, + "jis": 8, + "eucjp": 3, + "euckr": 2, + "euccn": 2, + "sjis": 2, + "cp932": 2, + "cp51932": 2, + "cp936": 2, + "cp949": 2, + "cp950": 2, + "big5": 2, + "gbk": 2, + "gb2312": 2, +} +func isEastAsian(locale string) bool { charset := strings.ToLower(locale) r := reLoc.FindStringSubmatch(locale) if len(r) == 2 { @@ -40,26 +46,11 @@ func IsEastAsian() bool { break } } - - mbc_max := 1 - switch charset { - case "utf-8", "utf8": - mbc_max = 6 - case "jis": - mbc_max = 8 - case "eucjp": - mbc_max = 3 - case "euckr", "euccn": - mbc_max = 2 - case "sjis", "cp932", "cp51932", "cp936", "cp949", "cp950": - mbc_max = 2 - case "big5": - mbc_max = 2 - case "gbk", "gb2312": - mbc_max = 2 + max := 1 + if m, ok := mblenTable[charset]; ok { + max = m } - - if mbc_max > 1 && (charset[0] != 'u' || + if max > 1 && (charset[0] != 'u' || strings.HasPrefix(locale, "ja") || strings.HasPrefix(locale, "ko") || strings.HasPrefix(locale, "zh")) { @@ -67,3 +58,24 @@ func IsEastAsian() bool { } return false } + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + locale := os.Getenv("LC_ALL") + if locale == "" { + locale = os.Getenv("LC_CTYPE") + } + if locale == "" { + locale = os.Getenv("LANG") + } + + // ignore C locale + if locale == "POSIX" || locale == "C" { + return false + } + if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { + return false + } + + return isEastAsian(locale) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go index bdd84454b..5f987a310 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -1,3 +1,6 @@ +//go:build windows && !appengine +// +build windows,!appengine + package runewidth import ( @@ -9,6 +12,7 @@ var ( procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") ) +// IsEastAsian return true if the current locale is CJK func IsEastAsian() bool { r1, _, _ := procGetConsoleOutputCP.Call() if r1 == 0 { diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go index 47e1f9ef8..25378537e 100644 --- a/vendor/github.com/mitchellh/go-homedir/homedir.go +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -76,34 +76,62 @@ func Expand(path string) (string, error) { return filepath.Join(dir, path[1:]), nil } +// Reset clears the cache, forcing the next call to Dir to re-detect +// the home directory. This generally never has to be called, but can be +// useful in tests if you're modifying the home directory via the HOME +// env var or something. +func Reset() { + cacheLock.Lock() + defer cacheLock.Unlock() + homedirCache = "" +} + func dirUnix() (string, error) { + homeEnv := "HOME" + if runtime.GOOS == "plan9" { + // On plan9, env vars are lowercase. + homeEnv = "home" + } + // First prefer the HOME environmental variable - if home := os.Getenv("HOME"); home != "" { + if home := os.Getenv(homeEnv); home != "" { return home, nil } - // If that fails, try getent var stdout bytes.Buffer - cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) - cmd.Stdout = &stdout - if err := cmd.Run(); err != nil { - // If the error is ErrNotFound, we ignore it. Otherwise, return it. - if err != exec.ErrNotFound { - return "", err + + // If that fails, try OS specific commands + if runtime.GOOS == "darwin" { + cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + result := strings.TrimSpace(stdout.String()) + if result != "" { + return result, nil + } } } else { - if passwd := strings.TrimSpace(stdout.String()); passwd != "" { - // username:password:uid:gid:gecos:home:shell - passwdParts := strings.SplitN(passwd, ":", 7) - if len(passwdParts) > 5 { - return passwdParts[5], nil + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } } } } // If all else fails, try the shell stdout.Reset() - cmd = exec.Command("sh", "-c", "cd && pwd") + cmd := exec.Command("sh", "-c", "cd && pwd") cmd.Stdout = &stdout if err := cmd.Run(); err != nil { return "", err @@ -123,14 +151,16 @@ func dirWindows() (string, error) { return home, nil } + // Prefer standard environment variable USERPROFILE + if home := os.Getenv("USERPROFILE"); home != "" { + return home, nil + } + drive := os.Getenv("HOMEDRIVE") path := os.Getenv("HOMEPATH") home := drive + path if drive == "" || path == "" { - home = os.Getenv("USERPROFILE") - } - if home == "" { - return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") + return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank") } return home, nil diff --git a/vendor/github.com/nxadm/tail/.gitignore b/vendor/github.com/nxadm/tail/.gitignore index 35d9351d3..063e5a65a 100644 --- a/vendor/github.com/nxadm/tail/.gitignore +++ b/vendor/github.com/nxadm/tail/.gitignore @@ -1,3 +1,2 @@ .idea/ -.test/ -examples/_* \ No newline at end of file +examples/_* diff --git a/vendor/github.com/nxadm/tail/CHANGES.md b/vendor/github.com/nxadm/tail/CHANGES.md index 224e54b44..e6c74d773 100644 --- a/vendor/github.com/nxadm/tail/CHANGES.md +++ b/vendor/github.com/nxadm/tail/CHANGES.md @@ -1,7 +1,15 @@ +# Version v1.4.11 +* Bump fsnotify to v1.6.0. Should fix some issues. + +# Version v1.4.9 +* Bump fsnotify to v1.5.1 fixes issue #28, hpcloud/tail#90. +* PR #27: "Add timeout to tests"by @kokes++. Also timeout on FreeBSD. +* PR #29: "Use temp directory for tests, instead of relative" by @ches++. + # Version v1.4.7-v1.4.8 * Documentation updates. * Small linter cleanups. -* Added example in test. +* Added example in test. # Version v1.4.6 diff --git a/vendor/github.com/nxadm/tail/README.md b/vendor/github.com/nxadm/tail/README.md index f47939c74..fca8901c0 100644 --- a/vendor/github.com/nxadm/tail/README.md +++ b/vendor/github.com/nxadm/tail/README.md @@ -1,12 +1,13 @@ -![ci](https://github.com/nxadm/tail/workflows/ci/badge.svg)[![Go Reference](https://pkg.go.dev/badge/github.com/nxadm/tail.svg)](https://pkg.go.dev/github.com/nxadm/tail) - +[![Go Reference](https://pkg.go.dev/badge/github.com/nxadm/tail.svg)](https://pkg.go.dev/github.com/nxadm/tail#section-documentation) +![ci](https://github.com/nxadm/tail/workflows/ci/badge.svg) +[![FreeBSD](https://api.cirrus-ci.com/github/nxadm/tail.svg)](https://cirrus-ci.com/github/nxadm/tail) # tail functionality in Go nxadm/tail provides a Go library that emulates the features of the BSD `tail` program. The library comes with full support for truncation/move detection as it is designed to work with log rotation tools. The library works on all -operating systems supported by Go, including POSIX systems like Linux and -*BSD, and MS Windows. Go 1.9 is the oldest compiler release supported. +operating systems supported by Go, including POSIX systems like Linux, *BSD, +MacOS, and MS Windows. Go 1.12 is the oldest compiler release supported. A simple example: @@ -24,7 +25,7 @@ for line := range t.Lines { } ``` -See [API documentation](https://pkg.go.dev/github.com/nxadm/tail). +See [API documentation](https://pkg.go.dev/github.com/nxadm/tail#section-documentation). ## Installing @@ -41,4 +42,4 @@ nxadm/tail continues the development by keeping up to date with the Go toolchain and fixing bugs. ## Examples -Examples, e.g. used to debug an issue, are kept in the [examples directory](/examples). \ No newline at end of file +Examples, e.g. used to debug an issue, are kept in the [examples directory](/examples). diff --git a/vendor/github.com/nxadm/tail/tail.go b/vendor/github.com/nxadm/tail/tail.go index 37ea4411e..c962599be 100644 --- a/vendor/github.com/nxadm/tail/tail.go +++ b/vendor/github.com/nxadm/tail/tail.go @@ -77,8 +77,9 @@ type Config struct { Pipe bool // The file is a named pipe (mkfifo) // Generic IO - Follow bool // Continue looking for new lines (tail -f) - MaxLineSize int // If non-zero, split longer lines into multiple lines + Follow bool // Continue looking for new lines (tail -f) + MaxLineSize int // If non-zero, split longer lines into multiple lines + CompleteLines bool // Only return complete lines (that end with "\n" or EOF when Follow is false) // Optionally, use a ratelimiter (e.g. created by the ratelimiter/NewLeakyBucket function) RateLimiter *ratelimiter.LeakyBucket @@ -97,6 +98,8 @@ type Tail struct { reader *bufio.Reader lineNum int + lineBuf *strings.Builder + watcher watch.FileWatcher changes *watch.FileChanges @@ -128,6 +131,10 @@ func TailFile(filename string, config Config) (*Tail, error) { Config: config, } + if config.CompleteLines { + t.lineBuf = new(strings.Builder) + } + // when Logger was not specified in config, use default logger if t.Logger == nil { t.Logger = DefaultLogger @@ -202,6 +209,9 @@ func (tail *Tail) closeFile() { } func (tail *Tail) reopen() error { + if tail.lineBuf != nil { + tail.lineBuf.Reset() + } tail.closeFile() tail.lineNum = 0 for { @@ -229,16 +239,32 @@ func (tail *Tail) readLine() (string, error) { tail.lk.Lock() line, err := tail.reader.ReadString('\n') tail.lk.Unlock() - if err != nil { + + newlineEnding := strings.HasSuffix(line, "\n") + line = strings.TrimRight(line, "\n") + + // if we don't have to handle incomplete lines, we can return the line as-is + if !tail.Config.CompleteLines { // Note ReadString "returns the data read before the error" in // case of an error, including EOF, so we return it as is. The // caller is expected to process it if err is EOF. return line, err } - line = strings.TrimRight(line, "\n") + if _, err := tail.lineBuf.WriteString(line); err != nil { + return line, err + } - return line, err + if newlineEnding { + line = tail.lineBuf.String() + tail.lineBuf.Reset() + return line, nil + } else { + if tail.Config.Follow { + line = "" + } + return line, io.EOF + } } func (tail *Tail) tailFileSync() { diff --git a/vendor/github.com/olekukonko/tablewriter/.travis.yml b/vendor/github.com/olekukonko/tablewriter/.travis.yml index 354b7f8b2..366d48a35 100644 --- a/vendor/github.com/olekukonko/tablewriter/.travis.yml +++ b/vendor/github.com/olekukonko/tablewriter/.travis.yml @@ -1,8 +1,22 @@ language: go - +arch: + - ppc64le + - amd64 go: - - 1.1 - - 1.2 - 1.3 - 1.4 + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 + - "1.10" - tip +jobs: + exclude : + - arch : ppc64le + go : + - 1.3 + - arch : ppc64le + go : + - 1.4 diff --git a/vendor/github.com/olekukonko/tablewriter/LICENCE.md b/vendor/github.com/olekukonko/tablewriter/LICENCE.md deleted file mode 100644 index 1fd848425..000000000 --- a/vendor/github.com/olekukonko/tablewriter/LICENCE.md +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2014 by Oleku Konko - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md index 805330adc..f06530d75 100644 --- a/vendor/github.com/olekukonko/tablewriter/README.md +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -1,11 +1,13 @@ ASCII Table Writer ========= -[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) [![Total views](https://sourcegraph.com/api/repos/github.com/olekukonko/tablewriter/counters/views.png)](https://sourcegraph.com/github.com/olekukonko/tablewriter) +[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) +[![Total views](https://img.shields.io/sourcegraph/rrc/github.com/olekukonko/tablewriter.svg)](https://sourcegraph.com/github.com/olekukonko/tablewriter) +[![Godoc](https://godoc.org/github.com/olekukonko/tablewriter?status.svg)](https://godoc.org/github.com/olekukonko/tablewriter) Generate ASCII table on the fly ... Installation is simple as - go get github.com/olekukonko/tablewriter + go get github.com/olekukonko/tablewriter #### Features @@ -22,7 +24,8 @@ Generate ASCII table on the fly ... Installation is simple as - Enable or disable table border - Set custom footer support - Optional identical cells merging - +- Set custom caption +- Optional reflowing of paragraphs in multi-line cells. #### Example 1 - Basic ```go @@ -75,21 +78,21 @@ table.Render() ``` DATE | DESCRIPTION | CV2 | AMOUNT -+----------+--------------------------+-------+---------+ +-----------+--------------------------+-------+---------- 1/1/2014 | Domain name | 2233 | $10.98 1/1/2014 | January Hosting | 2233 | $54.95 1/4/2014 | February Hosting | 2233 | $51.00 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 -+----------+--------------------------+-------+---------+ +-----------+--------------------------+-------+---------- TOTAL | $146 93 - +-------+---------+ + --------+---------- ``` #### Example 3 - CSV ```go -table, _ := tablewriter.NewCSV(os.Stdout, "test_info.csv", true) +table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test_info.csv", true) table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment table.Render() ``` @@ -107,12 +110,12 @@ table.Render() #### Example 4 - Custom Separator ```go -table, _ := tablewriter.NewCSV(os.Stdout, "test.csv", true) +table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test.csv", true) table.SetRowLine(true) // Enable row line // Change table lines table.SetCenterSeparator("*") -table.SetColumnSeparator("‡") +table.SetColumnSeparator("╪") table.SetRowSeparator("-") table.SetAlignment(tablewriter.ALIGN_LEFT) @@ -132,7 +135,7 @@ table.Render() *------------*-----------*---------* ``` -##### Example 5 - Markdown Format +#### Example 5 - Markdown Format ```go data := [][]string{ []string{"1/1/2014", "Domain name", "2233", "$10.98"}, @@ -194,11 +197,235 @@ table.Render() +----------+--------------------------+-------+---------+ ``` +#### Example 7 - Identical cells merging (specify the column index to merge) +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "1234", "$10.98"}, + []string{"1/1/2014", "January Hosting", "1234", "$10.98"}, + []string{"1/4/2014", "February Hosting", "3456", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) +table.SetAutoMergeCellsByColumnIndex([]int{2, 3}) +table.SetRowLine(true) +table.AppendBulk(data) +table.Render() +``` + +##### Output 7 +``` ++----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 1234 | $10.98 | ++----------+--------------------------+ + + +| 1/1/2014 | January Hosting | | | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Hosting | 3456 | $51.00 | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $146.93 | ++----------+--------------------------+-------+---------+ +``` + + +#### Table with color +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.SetBorder(false) // Set Border to false + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, + tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, + tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, + tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.FgHiRedColor}) + +table.AppendBulk(data) +table.Render() +``` + +#### Table with color Output +![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) + +#### Example - 8 Table Cells with Color + +Individual Cell Colors from `func Rich` take precedence over Column Colors + +```go +data := [][]string{ + []string{"Test1Merge", "HelloCol2 - 1", "HelloCol3 - 1", "HelloCol4 - 1"}, + []string{"Test1Merge", "HelloCol2 - 2", "HelloCol3 - 2", "HelloCol4 - 2"}, + []string{"Test1Merge", "HelloCol2 - 3", "HelloCol3 - 3", "HelloCol4 - 3"}, + []string{"Test2Merge", "HelloCol2 - 4", "HelloCol3 - 4", "HelloCol4 - 4"}, + []string{"Test2Merge", "HelloCol2 - 5", "HelloCol3 - 5", "HelloCol4 - 5"}, + []string{"Test2Merge", "HelloCol2 - 6", "HelloCol3 - 6", "HelloCol4 - 6"}, + []string{"Test2Merge", "HelloCol2 - 7", "HelloCol3 - 7", "HelloCol4 - 7"}, + []string{"Test3Merge", "HelloCol2 - 8", "HelloCol3 - 8", "HelloCol4 - 8"}, + []string{"Test3Merge", "HelloCol2 - 9", "HelloCol3 - 9", "HelloCol4 - 9"}, + []string{"Test3Merge", "HelloCol2 - 10", "HelloCol3 -10", "HelloCol4 - 10"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Col1", "Col2", "Col3", "Col4"}) +table.SetFooter([]string{"", "", "Footer3", "Footer4"}) +table.SetBorder(false) + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, + tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, + tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, + tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.FgHiRedColor}) + +colorData1 := []string{"TestCOLOR1Merge", "HelloCol2 - COLOR1", "HelloCol3 - COLOR1", "HelloCol4 - COLOR1"} +colorData2 := []string{"TestCOLOR2Merge", "HelloCol2 - COLOR2", "HelloCol3 - COLOR2", "HelloCol4 - COLOR2"} + +for i, row := range data { + if i == 4 { + table.Rich(colorData1, []tablewriter.Colors{tablewriter.Colors{}, tablewriter.Colors{tablewriter.Normal, tablewriter.FgCyanColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgWhiteColor}, tablewriter.Colors{}}) + table.Rich(colorData2, []tablewriter.Colors{tablewriter.Colors{tablewriter.Normal, tablewriter.FgMagentaColor}, tablewriter.Colors{}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgRedColor}, tablewriter.Colors{tablewriter.FgHiGreenColor, tablewriter.Italic, tablewriter.BgHiCyanColor}}) + } + table.Append(row) +} + +table.SetAutoMergeCells(true) +table.Render() + +``` + +##### Table cells with color Output +![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png) + +#### Example 9 - Set table caption +```go +data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) +table.SetCaption(true, "Movie ratings.") + +for _, v := range data { + table.Append(v) +} +table.Render() // Send output +``` + +Note: Caption text will wrap with total width of rendered table. + +##### Output 9 +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +Movie ratings. +``` + +#### Example 10 - Set NoWhiteSpace and TablePadding option +```go +data := [][]string{ + {"node1.example.com", "Ready", "compute", "1.11"}, + {"node2.example.com", "Ready", "compute", "1.11"}, + {"node3.example.com", "Ready", "compute", "1.11"}, + {"node4.example.com", "NotReady", "compute", "1.11"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Status", "Role", "Version"}) +table.SetAutoWrapText(false) +table.SetAutoFormatHeaders(true) +table.SetHeaderAlignment(ALIGN_LEFT) +table.SetAlignment(ALIGN_LEFT) +table.SetCenterSeparator("") +table.SetColumnSeparator("") +table.SetRowSeparator("") +table.SetHeaderLine(false) +table.SetBorder(false) +table.SetTablePadding("\t") // pad with tabs +table.SetNoWhiteSpace(true) +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 10 +``` +NAME STATUS ROLE VERSION +node1.example.com Ready compute 1.11 +node2.example.com Ready compute 1.11 +node3.example.com Ready compute 1.11 +node4.example.com NotReady compute 1.11 +``` + +#### Render table into a string + +Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the `strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example: + +```go +package main + +import ( + "strings" + "fmt" + + "github.com/olekukonko/tablewriter" +) + +func main() { + tableString := &strings.Builder{} + table := tablewriter.NewWriter(tableString) + + /* + * Code to fill the table + */ + + table.Render() + + fmt.Println(tableString.String()) +} +``` + #### TODO - ~~Import Directly from CSV~~ - `done` - ~~Support for `SetFooter`~~ - `done` - ~~Support for `SetBorder`~~ - `done` - ~~Support table with uneven rows~~ - `done` -- Support custom alignment +- ~~Support custom alignment~~ - General Improvement & Optimisation - `NewHTML` Parse table from HTML diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go index 3314bfba5..f913149c6 100644 --- a/vendor/github.com/olekukonko/tablewriter/table.go +++ b/vendor/github.com/olekukonko/tablewriter/table.go @@ -36,8 +36,8 @@ const ( ) var ( - decimal = regexp.MustCompile(`^-*\d*\.?\d*$`) - percent = regexp.MustCompile(`^-*\d*\.?\d*$%$`) + decimal = regexp.MustCompile(`^-?(?:\d{1,3}(?:,\d{3})*|\d+)(?:\.\d+)?$`) + percent = regexp.MustCompile(`^-?\d+\.?\d*$%$`) ) type Border struct { @@ -48,64 +48,81 @@ type Border struct { } type Table struct { - out io.Writer - rows [][]string - lines [][][]string - cs map[int]int - rs map[int]int - headers []string - footers []string - autoFmt bool - autoWrap bool - mW int - pCenter string - pRow string - pColumn string - tColumn int - tRow int - hAlign int - fAlign int - align int - newLine string - rowLine bool - autoMergeCells bool - hdrLine bool - borders Border - colSize int + out io.Writer + rows [][]string + lines [][][]string + cs map[int]int + rs map[int]int + headers [][]string + footers [][]string + caption bool + captionText string + autoFmt bool + autoWrap bool + reflowText bool + mW int + pCenter string + pRow string + pColumn string + tColumn int + tRow int + hAlign int + fAlign int + align int + newLine string + rowLine bool + autoMergeCells bool + columnsToAutoMergeCells map[int]bool + noWhiteSpace bool + tablePadding string + hdrLine bool + borders Border + colSize int + headerParams []string + columnsParams []string + footerParams []string + columnsAlign []int } // Start New Table // Take io.Writer Directly func NewWriter(writer io.Writer) *Table { t := &Table{ - out: writer, - rows: [][]string{}, - lines: [][][]string{}, - cs: make(map[int]int), - rs: make(map[int]int), - headers: []string{}, - footers: []string{}, - autoFmt: true, - autoWrap: true, - mW: MAX_ROW_WIDTH, - pCenter: CENTER, - pRow: ROW, - pColumn: COLUMN, - tColumn: -1, - tRow: -1, - hAlign: ALIGN_DEFAULT, - fAlign: ALIGN_DEFAULT, - align: ALIGN_DEFAULT, - newLine: NEWLINE, - rowLine: false, - hdrLine: true, - borders: Border{Left: true, Right: true, Bottom: true, Top: true}, - colSize: -1} + out: writer, + rows: [][]string{}, + lines: [][][]string{}, + cs: make(map[int]int), + rs: make(map[int]int), + headers: [][]string{}, + footers: [][]string{}, + caption: false, + captionText: "Table caption.", + autoFmt: true, + autoWrap: true, + reflowText: true, + mW: MAX_ROW_WIDTH, + pCenter: CENTER, + pRow: ROW, + pColumn: COLUMN, + tColumn: -1, + tRow: -1, + hAlign: ALIGN_DEFAULT, + fAlign: ALIGN_DEFAULT, + align: ALIGN_DEFAULT, + newLine: NEWLINE, + rowLine: false, + hdrLine: true, + borders: Border{Left: true, Right: true, Bottom: true, Top: true}, + colSize: -1, + headerParams: []string{}, + columnsParams: []string{}, + footerParams: []string{}, + columnsAlign: []int{}} return t } // Render table output -func (t Table) Render() { +func (t *Table) Render() { if t.borders.Top { t.printLine(true) } @@ -115,20 +132,27 @@ func (t Table) Render() { } else { t.printRows() } - if !t.rowLine && t.borders.Bottom { t.printLine(true) } t.printFooter() + if t.caption { + t.printCaption() + } } +const ( + headerRowIdx = -1 + footerRowIdx = -2 +) + // Set table header func (t *Table) SetHeader(keys []string) { t.colSize = len(keys) for i, v := range keys { - t.parseDimension(v, i, -1) - t.headers = append(t.headers, v) + lines := t.parseDimension(v, i, headerRowIdx) + t.headers = append(t.headers, lines) } } @@ -136,8 +160,16 @@ func (t *Table) SetHeader(keys []string) { func (t *Table) SetFooter(keys []string) { //t.colSize = len(keys) for i, v := range keys { - t.parseDimension(v, i, -1) - t.footers = append(t.footers, v) + lines := t.parseDimension(v, i, footerRowIdx) + t.footers = append(t.footers, lines) + } +} + +// Set table Caption +func (t *Table) SetCaption(caption bool, captionText ...string) { + t.caption = caption + if len(captionText) == 1 { + t.captionText = captionText[0] } } @@ -151,11 +183,21 @@ func (t *Table) SetAutoWrapText(auto bool) { t.autoWrap = auto } +// Turn automatic reflowing of multiline text when rewrapping. Default is on (true). +func (t *Table) SetReflowDuringAutoWrap(auto bool) { + t.reflowText = auto +} + // Set the Default column width func (t *Table) SetColWidth(width int) { t.mW = width } +// Set the minimal width for a column +func (t *Table) SetColMinWidth(column int, width int) { + t.cs[column] = width +} + // Set the Column Separator func (t *Table) SetColumnSeparator(sep string) { t.pColumn = sep @@ -186,6 +228,32 @@ func (t *Table) SetAlignment(align int) { t.align = align } +// Set No White Space +func (t *Table) SetNoWhiteSpace(allow bool) { + t.noWhiteSpace = allow +} + +// Set Table Padding +func (t *Table) SetTablePadding(padding string) { + t.tablePadding = padding +} + +func (t *Table) SetColumnAlignment(keys []int) { + for _, v := range keys { + switch v { + case ALIGN_CENTER: + break + case ALIGN_LEFT: + break + case ALIGN_RIGHT: + break + default: + v = ALIGN_DEFAULT + } + t.columnsAlign = append(t.columnsAlign, v) + } +} + // Set New Line func (t *Table) SetNewLine(nl string) { t.newLine = nl @@ -209,6 +277,21 @@ func (t *Table) SetAutoMergeCells(auto bool) { t.autoMergeCells = auto } +// Set Auto Merge Cells By Column Index +// This would enable / disable the merge of cells with identical values for specific columns +// If cols is empty, it is the same as `SetAutoMergeCells(true)`. +func (t *Table) SetAutoMergeCellsByColumnIndex(cols []int) { + t.autoMergeCells = true + + if len(cols) > 0 { + m := make(map[int]bool) + for _, col := range cols { + m[col] = true + } + t.columnsToAutoMergeCells = m + } +} + // Set Table Border // This would enable / disable line around the table func (t *Table) SetBorder(border bool) { @@ -241,6 +324,33 @@ func (t *Table) Append(row []string) { t.lines = append(t.lines, line) } +// Append row to table with color attributes +func (t *Table) Rich(row []string, colors []Colors) { + rowSize := len(t.headers) + if rowSize > t.colSize { + t.colSize = rowSize + } + + n := len(t.lines) + line := [][]string{} + for i, v := range row { + + // Detect string width + // Detect String height + // Break strings into words + out := t.parseDimension(v, i, n) + + if len(colors) > i { + color := colors[i] + out[0] = format(out[0], color) + } + + // Append broken words + line = append(line, out) + } + t.lines = append(t.lines, line) +} + // Allow Support for Bulk Append // Eliminates repeated for loops func (t *Table) AppendBulk(rows [][]string) { @@ -249,16 +359,44 @@ func (t *Table) AppendBulk(rows [][]string) { } } +// NumLines to get the number of lines +func (t *Table) NumLines() int { + return len(t.lines) +} + +// Clear rows +func (t *Table) ClearRows() { + t.lines = [][][]string{} +} + +// Clear footer +func (t *Table) ClearFooter() { + t.footers = [][]string{} +} + +// Center based on position and border. +func (t *Table) center(i int) string { + if i == -1 && !t.borders.Left { + return t.pRow + } + + if i == len(t.cs)-1 && !t.borders.Right { + return t.pRow + } + + return t.pCenter +} + // Print line based on row width -func (t Table) printLine(nl bool) { - fmt.Fprint(t.out, t.pCenter) +func (t *Table) printLine(nl bool) { + fmt.Fprint(t.out, t.center(-1)) for i := 0; i < len(t.cs); i++ { v := t.cs[i] fmt.Fprintf(t.out, "%s%s%s%s", t.pRow, strings.Repeat(string(t.pRow), v), t.pRow, - t.pCenter) + t.center(i)) } if nl { fmt.Fprint(t.out, t.newLine) @@ -266,7 +404,7 @@ func (t Table) printLine(nl bool) { } // Print line based on row width with our without cell separator -func (t Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { +func (t *Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { fmt.Fprint(t.out, t.pCenter) for i := 0; i < len(t.cs); i++ { v := t.cs[i] @@ -303,43 +441,82 @@ func pad(align int) func(string, string, int) string { } // Print heading information -func (t Table) printHeading() { +func (t *Table) printHeading() { // Check if headers is available if len(t.headers) < 1 { return } - // Check if border is set - // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) - // Identify last column end := len(t.cs) - 1 // Get pad function padFunc := pad(t.hAlign) - // Print Heading column - for i := 0; i <= end; i++ { - v := t.cs[i] - h := t.headers[i] - if t.autoFmt { - h = Title(h) + // Checking for ANSI escape sequences for header + is_esc_seq := false + if len(t.headerParams) > 0 { + is_esc_seq = true + } + + // Maximum height. + max := t.rs[headerRowIdx] + + // Print Heading + for x := 0; x < max; x++ { + // Check if border is set + // Replace with space if not set + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + } + + for y := 0; y <= end; y++ { + v := t.cs[y] + h := "" + + if y < len(t.headers) && x < len(t.headers[y]) { + h = t.headers[y][x] + } + if t.autoFmt { + h = Title(h) + } + pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn) + if t.noWhiteSpace { + pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding) + } + if is_esc_seq { + if !t.noWhiteSpace { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } else { + fmt.Fprintf(t.out, "%s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } + } else { + if !t.noWhiteSpace { + fmt.Fprintf(t.out, " %s %s", + padFunc(h, SPACE, v), + pad) + } else { + // the spaces between breaks the kube formatting + fmt.Fprintf(t.out, "%s%s", + padFunc(h, SPACE, v), + pad) + } + } } - pad := ConditionString((i == end && !t.borders.Left), SPACE, t.pColumn) - fmt.Fprintf(t.out, " %s %s", - padFunc(h, SPACE, v), - pad) + // Next line + fmt.Fprint(t.out, t.newLine) } - // Next line - fmt.Fprint(t.out, t.newLine) if t.hdrLine { t.printLine(true) } } // Print heading information -func (t Table) printFooter() { +func (t *Table) printFooter() { // Check if headers is available if len(t.footers) < 1 { return @@ -349,9 +526,6 @@ func (t Table) printFooter() { if !t.borders.Bottom { t.printLine(true) } - // Check if border is set - // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) // Identify last column end := len(t.cs) - 1 @@ -359,25 +533,56 @@ func (t Table) printFooter() { // Get pad function padFunc := pad(t.fAlign) - // Print Heading column - for i := 0; i <= end; i++ { - v := t.cs[i] - f := t.footers[i] - if t.autoFmt { - f = Title(f) - } - pad := ConditionString((i == end && !t.borders.Top), SPACE, t.pColumn) + // Checking for ANSI escape sequences for header + is_esc_seq := false + if len(t.footerParams) > 0 { + is_esc_seq = true + } - if len(t.footers[i]) == 0 { - pad = SPACE + // Maximum height. + max := t.rs[footerRowIdx] + + // Print Footer + erasePad := make([]bool, len(t.footers)) + for x := 0; x < max; x++ { + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) + + for y := 0; y <= end; y++ { + v := t.cs[y] + f := "" + if y < len(t.footers) && x < len(t.footers[y]) { + f = t.footers[y][x] + } + if t.autoFmt { + f = Title(f) + } + pad := ConditionString((y == end && !t.borders.Top), SPACE, t.pColumn) + + if erasePad[y] || (x == 0 && len(f) == 0) { + pad = SPACE + erasePad[y] = true + } + + if is_esc_seq { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(f, SPACE, v), + t.footerParams[y]), pad) + } else { + fmt.Fprintf(t.out, " %s %s", + padFunc(f, SPACE, v), + pad) + } + + //fmt.Fprintf(t.out, " %s %s", + // padFunc(f, SPACE, v), + // pad) } - fmt.Fprintf(t.out, " %s %s", - padFunc(f, SPACE, v), - pad) + // Next line + fmt.Fprint(t.out, t.newLine) + //t.printLine(true) } - // Next line - fmt.Fprint(t.out, t.newLine) - //t.printLine(true) hasPrinted := false @@ -385,7 +590,7 @@ func (t Table) printFooter() { v := t.cs[i] pad := t.pRow center := t.pCenter - length := len(t.footers[i]) + length := len(t.footers[i][0]) if length > 0 { hasPrinted = true @@ -398,6 +603,9 @@ func (t Table) printFooter() { // Print first junction if i == 0 { + if length > 0 && !t.borders.Left { + center = t.pRow + } fmt.Fprint(t.out, center) } @@ -405,16 +613,27 @@ func (t Table) printFooter() { if length == 0 { pad = SPACE } - // Ignore left space of it has printed before + // Ignore left space as it has printed before if hasPrinted || t.borders.Left { pad = t.pRow center = t.pCenter } + // Change Center end position + if center != SPACE { + if i == end && !t.borders.Right { + center = t.pRow + } + } + // Change Center start position if center == SPACE { - if i < end && len(t.footers[i+1]) != 0 { - center = t.pCenter + if i < end && len(t.footers[i+1][0]) != 0 { + if !t.borders.Left { + center = t.pRow + } else { + center = t.pCenter + } } } @@ -428,22 +647,53 @@ func (t Table) printFooter() { } fmt.Fprint(t.out, t.newLine) +} +// Print caption text +func (t Table) printCaption() { + width := t.getTableWidth() + paragraph, _ := WrapString(t.captionText, width) + for linecount := 0; linecount < len(paragraph); linecount++ { + fmt.Fprintln(t.out, paragraph[linecount]) + } +} + +// Calculate the total number of characters in a row +func (t Table) getTableWidth() int { + var chars int + for _, v := range t.cs { + chars += v + } + + // Add chars, spaces, seperators to calculate the total width of the table. + // ncols := t.colSize + // spaces := ncols * 2 + // seps := ncols + 1 + + return (chars + (3 * t.colSize) + 2) } func (t Table) printRows() { for i, lines := range t.lines { t.printRow(lines, i) } +} +func (t *Table) fillAlignment(num int) { + if len(t.columnsAlign) < num { + t.columnsAlign = make([]int, num) + for i := range t.columnsAlign { + t.columnsAlign[i] = t.align + } + } } // Print Row Information // Adjust column alignment based on type -func (t Table) printRow(columns [][]string, colKey int) { +func (t *Table) printRow(columns [][]string, rowIdx int) { // Get Maximum Height - max := t.rs[colKey] + max := t.rs[rowIdx] total := len(columns) // TODO Fix uneven col size @@ -455,9 +705,15 @@ func (t Table) printRow(columns [][]string, colKey int) { //} // Pad Each Height - // pads := []int{} pads := []int{} + // Checking for ANSI escape sequences for columns + is_esc_seq := false + if len(t.columnsParams) > 0 { + is_esc_seq = true + } + t.fillAlignment(total) + for i, line := range columns { length := len(line) pad := max - length @@ -471,14 +727,21 @@ func (t Table) printRow(columns [][]string, colKey int) { for y := 0; y < total; y++ { // Check if border is set - fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + fmt.Fprintf(t.out, SPACE) + } - fmt.Fprintf(t.out, SPACE) str := columns[y][x] + // Embedding escape sequence with column value + if is_esc_seq { + str = format(str, t.columnsParams[y]) + } + // This would print alignment // Default alignment would use multiple configuration - switch t.align { + switch t.columnsAlign[y] { case ALIGN_CENTER: // fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) case ALIGN_RIGHT: @@ -500,11 +763,17 @@ func (t Table) printRow(columns [][]string, colKey int) { } } - fmt.Fprintf(t.out, SPACE) + if !t.noWhiteSpace { + fmt.Fprintf(t.out, SPACE) + } else { + fmt.Fprintf(t.out, t.tablePadding) + } } // Check if border is set // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + } fmt.Fprint(t.out, t.newLine) } @@ -514,7 +783,7 @@ func (t Table) printRow(columns [][]string, colKey int) { } // Print the rows of the table and merge the cells that are identical -func (t Table) printRowsMergeCells() { +func (t *Table) printRowsMergeCells() { var previousLine []string var displayCellBorder []bool var tmpWriter bytes.Buffer @@ -537,14 +806,19 @@ func (t Table) printRowsMergeCells() { // Print Row Information to a writer and merge identical cells. // Adjust column alignment based on type -func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey int, previousLine []string) ([]string, []bool) { +func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx int, previousLine []string) ([]string, []bool) { // Get Maximum Height - max := t.rs[colKey] + max := t.rs[rowIdx] total := len(columns) // Pad Each Height pads := []int{} + // Checking for ANSI escape sequences for columns + is_esc_seq := false + if len(t.columnsParams) > 0 { + is_esc_seq = true + } for i, line := range columns { length := len(line) pad := max - length @@ -555,6 +829,7 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i } var displayCellBorder []bool + t.fillAlignment(total) for x := 0; x < max; x++ { for y := 0; y < total; y++ { @@ -565,10 +840,25 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i str := columns[y][x] + // Embedding escape sequence with column value + if is_esc_seq { + str = format(str, t.columnsParams[y]) + } + if t.autoMergeCells { + var mergeCell bool + if t.columnsToAutoMergeCells != nil { + // Check to see if the column index is in columnsToAutoMergeCells. + if t.columnsToAutoMergeCells[y] { + mergeCell = true + } + } else { + // columnsToAutoMergeCells was not set. + mergeCell = true + } //Store the full line to merge mutli-lines cells - fullLine := strings.Join(columns[y], " ") - if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { + fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") + if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" && mergeCell { // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. displayCellBorder = append(displayCellBorder, false) str = "" @@ -580,7 +870,7 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i // This would print alignment // Default alignment would use multiple configuration - switch t.align { + switch t.columnsAlign[y] { case ALIGN_CENTER: // fmt.Fprintf(writer, "%s", Pad(str, SPACE, t.cs[y])) case ALIGN_RIGHT: @@ -605,7 +895,7 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i //The new previous line is the current one previousLine = make([]string, total) for y := 0; y < total; y++ { - previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells + previousLine[y] = strings.TrimRight(strings.Join(columns[y], " "), " ") //Store the full line for multi-lines cells } //Returns the newly added line and wether or not a border should be displayed above. return previousLine, displayCellBorder @@ -613,44 +903,59 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i func (t *Table) parseDimension(str string, colKey, rowKey int) []string { var ( - raw []string - max int + raw []string + maxWidth int ) - w := DisplayWidth(str) - // Calculate Width - // Check if with is grater than maximum width - if w > t.mW { - w = t.mW - } - // Check if width exists - v, ok := t.cs[colKey] - if !ok || v < w || v == 0 { - t.cs[colKey] = w + raw = getLines(str) + maxWidth = 0 + for _, line := range raw { + if w := DisplayWidth(line); w > maxWidth { + maxWidth = w + } } - if rowKey == -1 { - return raw - } - // Calculate Height + // If wrapping, ensure that all paragraphs in the cell fit in the + // specified width. if t.autoWrap { - raw, _ = WrapString(str, t.cs[colKey]) - } else { - raw = getLines(str) - } + // If there's a maximum allowed width for wrapping, use that. + if maxWidth > t.mW { + maxWidth = t.mW + } - for _, line := range raw { - if w := DisplayWidth(line); w > max { - max = w + // In the process of doing so, we need to recompute maxWidth. This + // is because perhaps a word in the cell is longer than the + // allowed maximum width in t.mW. + newMaxWidth := maxWidth + newRaw := make([]string, 0, len(raw)) + + if t.reflowText { + // Make a single paragraph of everything. + raw = []string{strings.Join(raw, " ")} } + for i, para := range raw { + paraLines, _ := WrapString(para, maxWidth) + for _, line := range paraLines { + if w := DisplayWidth(line); w > newMaxWidth { + newMaxWidth = w + } + } + if i > 0 { + newRaw = append(newRaw, " ") + } + newRaw = append(newRaw, paraLines...) + } + raw = newRaw + maxWidth = newMaxWidth } - // Make sure the with is the same length as maximum word - // Important for cases where the width is smaller than maxu word - if max > t.cs[colKey] { - t.cs[colKey] = max + // Store the new known maximum width. + v, ok := t.cs[colKey] + if !ok || v < maxWidth || v == 0 { + t.cs[colKey] = maxWidth } + // Remember the number of lines for the row printer. h := len(raw) v, ok = t.rs[rowKey] diff --git a/vendor/github.com/olekukonko/tablewriter/test.csv b/vendor/github.com/olekukonko/tablewriter/test.csv deleted file mode 100644 index 1609327e9..000000000 --- a/vendor/github.com/olekukonko/tablewriter/test.csv +++ /dev/null @@ -1,4 +0,0 @@ -first_name,last_name,ssn -John,Barry,123456 -Kathy,Smith,687987 -Bob,McCornick,3979870 \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/test_info.csv b/vendor/github.com/olekukonko/tablewriter/test_info.csv deleted file mode 100644 index e4c40e983..000000000 --- a/vendor/github.com/olekukonko/tablewriter/test_info.csv +++ /dev/null @@ -1,4 +0,0 @@ -Field,Type,Null,Key,Default,Extra -user_id,smallint(5),NO,PRI,NULL,auto_increment -username,varchar(10),NO,,NULL, -password,varchar(100),NO,,NULL, \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/util.go b/vendor/github.com/olekukonko/tablewriter/util.go index 2deefbc52..380e7ab35 100644 --- a/vendor/github.com/olekukonko/tablewriter/util.go +++ b/vendor/github.com/olekukonko/tablewriter/util.go @@ -30,17 +30,38 @@ func ConditionString(cond bool, valid, inValid string) string { return inValid } +func isNumOrSpace(r rune) bool { + return ('0' <= r && r <= '9') || r == ' ' +} + // Format Table Header // Replace _ , . and spaces func Title(name string) string { - name = strings.Replace(name, "_", " ", -1) - name = strings.Replace(name, ".", " ", -1) + origLen := len(name) + rs := []rune(name) + for i, r := range rs { + switch r { + case '_': + rs[i] = ' ' + case '.': + // ignore floating number 0.0 + if (i != 0 && !isNumOrSpace(rs[i-1])) || (i != len(rs)-1 && !isNumOrSpace(rs[i+1])) { + rs[i] = ' ' + } + } + } + name = string(rs) name = strings.TrimSpace(name) + if len(name) == 0 && origLen > 0 { + // Keep at least one character. This is important to preserve + // empty lines in multi-line headers/footers. + name = " " + } return strings.ToUpper(name) } // Pad String -// Attempts to play string in the center +// Attempts to place string in the center func Pad(s, pad string, width int) string { gap := width - DisplayWidth(s) if gap > 0 { @@ -52,7 +73,7 @@ func Pad(s, pad string, width int) string { } // Pad String Right position -// This would pace string at the left side fo the screen +// This would place string at the left side of the screen func PadRight(s, pad string, width int) string { gap := width - DisplayWidth(s) if gap > 0 { @@ -62,7 +83,7 @@ func PadRight(s, pad string, width int) string { } // Pad String Left position -// This would pace string at the right side fo the screen +// This would place string at the right side of the screen func PadLeft(s, pad string, width int) string { gap := width - DisplayWidth(s) if gap > 0 { diff --git a/vendor/github.com/olekukonko/tablewriter/wrap.go b/vendor/github.com/olekukonko/tablewriter/wrap.go index 5290fb65a..a092ee1f7 100644 --- a/vendor/github.com/olekukonko/tablewriter/wrap.go +++ b/vendor/github.com/olekukonko/tablewriter/wrap.go @@ -10,7 +10,8 @@ package tablewriter import ( "math" "strings" - "unicode/utf8" + + "github.com/mattn/go-runewidth" ) var ( @@ -27,7 +28,7 @@ func WrapString(s string, lim int) ([]string, int) { var lines []string max := 0 for _, v := range words { - max = len(v) + max = runewidth.StringWidth(v) if max > lim { lim = max } @@ -55,9 +56,9 @@ func WrapWords(words []string, spc, lim, pen int) [][]string { length := make([][]int, n) for i := 0; i < n; i++ { length[i] = make([]int, n) - length[i][i] = utf8.RuneCountInString(words[i]) + length[i][i] = runewidth.StringWidth(words[i]) for j := i + 1; j < n; j++ { - length[i][j] = length[i][j-1] + spc + utf8.RuneCountInString(words[j]) + length[i][j] = length[i][j-1] + spc + runewidth.StringWidth(words[j]) } } nbrk := make([]int, n) @@ -94,10 +95,5 @@ func WrapWords(words []string, spc, lim, pen int) [][]string { // getLines decomposes a multiline string into a slice of strings. func getLines(s string) []string { - var lines []string - - for _, line := range strings.Split(s, nl) { - lines = append(lines, line) - } - return lines + return strings.Split(s, nl) } diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md index 494abdbfb..a26bc530f 100644 --- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.16.5 + +Ginkgo 2.0 now has a Release Candidate. 1.16.5 advertises the existence of the RC. +1.16.5 deprecates GinkgoParallelNode in favor of GinkgoParallelProcess + +You can silence the RC advertisement by setting an `ACK_GINKG_RC=true` environment variable or creating a file in your home directory called `.ack-ginkgo-rc` + ## 1.16.4 ### Fixes diff --git a/vendor/github.com/onsi/ginkgo/README.md b/vendor/github.com/onsi/ginkgo/README.md index 05321e6ea..a25ca5e03 100644 --- a/vendor/github.com/onsi/ginkgo/README.md +++ b/vendor/github.com/onsi/ginkgo/README.md @@ -1,23 +1,18 @@ ![Ginkgo: A Go BDD Testing Framework](https://onsi.github.io/ginkgo/images/ginkgo.png) -[![Build Status](https://travis-ci.org/onsi/ginkgo.svg?branch=master)](https://travis-ci.org/onsi/ginkgo) [![test](https://github.com/onsi/ginkgo/workflows/test/badge.svg?branch=master)](https://github.com/onsi/ginkgo/actions?query=workflow%3Atest+branch%3Amaster) Jump to the [docs](https://onsi.github.io/ginkgo/) | [中文文档](https://ke-chain.github.io/ginkgodoc) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)! If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW). -# Ginkgo 2.0 is coming soon! +# Ginkgo 2.0 Release Candidate is available! -An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [v2](https://github.com/onsi/ginkgo/tree/v2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion and links to the original [proposal doc](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#). +An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [ver2](https://github.com/onsi/ginkgo/tree/ver2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion. -As described in the [changelog](https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711). +As described in the [changelog](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711). -The current timeline for completion of 2.0 looks like: - -- Early April 2021: first public release of 2.0, deprecation warnings land in v1. -- May 2021: first beta/rc of 2.0 with most new functionality in place. -- June/July 2021: 2.0 ships and fully replaces the 1.x codebase on master. +Please start exploring and using the V2 release! To get started follow the [Using the Release Candidate](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta) directions in the migration guide. ## TLDR Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests. diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go index 5f3f43969..3130c7789 100644 --- a/vendor/github.com/onsi/ginkgo/config/config.go +++ b/vendor/github.com/onsi/ginkgo/config/config.go @@ -20,7 +20,7 @@ import ( "fmt" ) -const VERSION = "1.16.4" +const VERSION = "1.16.5" type GinkgoConfigType struct { RandomSeed int64 diff --git a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go index 4a6e1e1ee..ccd7685e3 100644 --- a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go +++ b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go @@ -73,9 +73,15 @@ func GinkgoRandomSeed() int64 { return config.GinkgoConfig.RandomSeed } -//GinkgoParallelNode returns the parallel node number for the current ginkgo process -//The node number is 1-indexed +//GinkgoParallelNode is deprecated, use GinkgoParallelProcess instead func GinkgoParallelNode() int { + deprecationTracker.TrackDeprecation(types.Deprecations.ParallelNode(), codelocation.New(1)) + return GinkgoParallelProcess() +} + +//GinkgoParallelProcess returns the parallel process number for the current ginkgo process +//The process number is 1-indexed +func GinkgoParallelProcess() int { return config.GinkgoConfig.ParallelNode } @@ -109,6 +115,7 @@ func GinkgoT(optionalOffset ...int) GinkgoTInterface { //in the testing package's T. type GinkgoTInterface interface { Cleanup(func()) + Setenv(key, value string) Error(args ...interface{}) Errorf(format string, args ...interface{}) Fail() diff --git a/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go b/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go index d7bbb7a96..4dcfaf4cd 100644 --- a/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go +++ b/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go @@ -34,6 +34,11 @@ func (t *ginkgoTestingTProxy) Cleanup(func()) { // No-op } +func (t *ginkgoTestingTProxy) Setenv(kev, value string) { + fmt.Println("Setenv is a noop for Ginkgo at the moment but will be implemented in V2") + // No-op until Cleanup is implemented +} + func (t *ginkgoTestingTProxy) Error(args ...interface{}) { t.fail(fmt.Sprintln(args...), t.offset) } diff --git a/vendor/github.com/onsi/ginkgo/types/deprecation_support.go b/vendor/github.com/onsi/ginkgo/types/deprecation_support.go index 305c134b7..d5a6658f3 100644 --- a/vendor/github.com/onsi/ginkgo/types/deprecation_support.go +++ b/vendor/github.com/onsi/ginkgo/types/deprecation_support.go @@ -52,6 +52,14 @@ func (d deprecations) Measure() Deprecation { } } +func (d deprecations) ParallelNode() Deprecation { + return Deprecation{ + Message: "GinkgoParallelNode is deprecated and will be removed in Ginkgo V2. Please use GinkgoParallelProcess instead.", + DocLink: "renamed-ginkgoparallelnode", + Version: "1.16.5", + } +} + func (d deprecations) Convert() Deprecation { return Deprecation{ Message: "The convert command is deprecated in Ginkgo V2", @@ -99,16 +107,18 @@ func (d *DeprecationTracker) DidTrackDeprecations() bool { } func (d *DeprecationTracker) DeprecationsReport() string { - out := formatter.F("{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n") + out := formatter.F("\n{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n") out += formatter.F("{{light-yellow}}============================================={{/}}\n") - out += formatter.F("Ginkgo 2.0 is under active development and will introduce (a small number of) breaking changes.\n") - out += formatter.F("To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md{{/}}\n") - out += formatter.F("To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n") + out += formatter.F("{{bold}}{{green}}Ginkgo 2.0{{/}} is under active development and will introduce several new features, improvements, and a small handful of breaking changes.\n") + out += formatter.F("A release candidate for 2.0 is now available and 2.0 should GA in Fall 2021. {{bold}}Please give the RC a try and send us feedback!{{/}}\n") + out += formatter.F(" - To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md{{/}}\n") + out += formatter.F(" - For instructions on using the Release Candidate visit {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta{{/}}\n") + out += formatter.F(" - To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n") for deprecation, locations := range d.deprecations { out += formatter.Fi(1, "{{yellow}}"+deprecation.Message+"{{/}}\n") if deprecation.DocLink != "" { - out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink) + out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink) } for _, location := range locations { out += formatter.Fi(2, "{{gray}}%s{{/}}\n", location) diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md index b797577ff..79c3f6199 100644 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.36.1 + +### Fixes +- Fix https://github.com/onsi/gomega/issues/803 [1c6c112] +- resolves onsi/gomega#696: make HaveField great on pointer receivers given only a non-addressable value [4feb9d7] + ## 1.36.0 ### Features diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go index eb74f6f6a..c6ac499f7 100644 --- a/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -22,7 +22,7 @@ import ( "github.com/onsi/gomega/types" ) -const GOMEGA_VERSION = "1.36.0" +const GOMEGA_VERSION = "1.36.1" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. If you're using Ginkgo then you probably forgot to put your assertion in an It(). diff --git a/vendor/github.com/onsi/gomega/matchers/have_field.go b/vendor/github.com/onsi/gomega/matchers/have_field.go index 8dd3f871a..293457e85 100644 --- a/vendor/github.com/onsi/gomega/matchers/have_field.go +++ b/vendor/github.com/onsi/gomega/matchers/have_field.go @@ -40,7 +40,12 @@ func extractField(actual interface{}, field string, matchername string) (any, er extractedValue = actualValue.Addr().MethodByName(strings.TrimSuffix(fields[0], "()")) } if extractedValue == (reflect.Value{}) { - return nil, missingFieldError(fmt.Sprintf("%s could not find method named '%s' in struct of type %T.", matchername, fields[0], actual)) + ptr := reflect.New(actualValue.Type()) + ptr.Elem().Set(actualValue) + extractedValue = ptr.MethodByName(strings.TrimSuffix(fields[0], "()")) + if extractedValue == (reflect.Value{}) { + return nil, missingFieldError(fmt.Sprintf("%s could not find method named '%s' in struct of type %T.", matchername, fields[0], actual)) + } } t := extractedValue.Type() if t.NumIn() != 0 || t.NumOut() != 1 { diff --git a/vendor/github.com/pborman/uuid/.travis.yml b/vendor/github.com/pborman/uuid/.travis.yml index a6a98db8a..3deb4a124 100644 --- a/vendor/github.com/pborman/uuid/.travis.yml +++ b/vendor/github.com/pborman/uuid/.travis.yml @@ -1,9 +1,9 @@ language: go go: - - 1.4.3 - - 1.5.3 - - release + - "1.9" + - "1.10" + - "1.11" - tip script: diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md index f023d47ca..810ad40dc 100644 --- a/vendor/github.com/pborman/uuid/README.md +++ b/vendor/github.com/pborman/uuid/README.md @@ -1,7 +1,9 @@ This project was automatically exported from code.google.com/p/go-uuid # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) -The uuid package generates and inspects UUIDs based on [RFC 412](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. +The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. + +This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package). ###### Install `go get github.com/pborman/uuid` diff --git a/vendor/github.com/pborman/uuid/doc.go b/vendor/github.com/pborman/uuid/doc.go index d8bd013e6..727d76167 100644 --- a/vendor/github.com/pborman/uuid/doc.go +++ b/vendor/github.com/pborman/uuid/doc.go @@ -4,5 +4,10 @@ // The uuid package generates and inspects UUIDs. // -// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// This package is a partial wrapper around the github.com/google/uuid package. +// This package represents a UUID as []byte while github.com/google/uuid +// represents a UUID as [16]byte. package uuid diff --git a/vendor/github.com/pborman/uuid/json.go b/vendor/github.com/pborman/uuid/json.go deleted file mode 100644 index 9dda1dfba..000000000 --- a/vendor/github.com/pborman/uuid/json.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import "errors" - -func (u UUID) MarshalJSON() ([]byte, error) { - if len(u) != 16 { - return []byte(`""`), nil - } - var js [38]byte - js[0] = '"' - encodeHex(js[1:], u) - js[37] = '"' - return js[:], nil -} - -func (u *UUID) UnmarshalJSON(data []byte) error { - if string(data) == `""` { - return nil - } - if data[0] != '"' { - return errors.New("invalid UUID format") - } - data = data[1 : len(data)-1] - uu := Parse(string(data)) - if uu == nil { - return errors.New("invalid UUID format") - } - *u = uu - return nil -} diff --git a/vendor/github.com/pborman/uuid/node.go b/vendor/github.com/pborman/uuid/node.go index 42d60da8f..e524e0101 100644 --- a/vendor/github.com/pborman/uuid/node.go +++ b/vendor/github.com/pborman/uuid/node.go @@ -5,24 +5,14 @@ package uuid import ( - "net" - "sync" -) - -var ( - nodeMu sync.Mutex - interfaces []net.Interface // cached list of interfaces - ifname string // name of interface being used - nodeID []byte // hardware for version 1 UUIDs + guuid "github.com/google/uuid" ) // NodeInterface returns the name of the interface from which the NodeID was // derived. The interface "user" is returned if the NodeID was set by // SetNodeID. func NodeInterface() string { - defer nodeMu.Unlock() - nodeMu.Lock() - return ifname + return guuid.NodeInterface() } // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. @@ -32,77 +22,20 @@ func NodeInterface() string { // // SetNodeInterface never fails when name is "". func SetNodeInterface(name string) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - return setNodeInterface(name) -} - -func setNodeInterface(name string) bool { - if interfaces == nil { - var err error - interfaces, err = net.Interfaces() - if err != nil && name != "" { - return false - } - } - - for _, ifs := range interfaces { - if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { - if setNodeID(ifs.HardwareAddr) { - ifname = ifs.Name - return true - } - } - } - - // We found no interfaces with a valid hardware address. If name - // does not specify a specific interface generate a random Node ID - // (section 4.1.6) - if name == "" { - if nodeID == nil { - nodeID = make([]byte, 6) - } - randomBits(nodeID) - return true - } - return false + return guuid.SetNodeInterface(name) } // NodeID returns a slice of a copy of the current Node ID, setting the Node ID // if not already set. func NodeID() []byte { - defer nodeMu.Unlock() - nodeMu.Lock() - if nodeID == nil { - setNodeInterface("") - } - nid := make([]byte, 6) - copy(nid, nodeID) - return nid + return guuid.NodeID() } // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes // of id are used. If id is less than 6 bytes then false is returned and the // Node ID is not set. func SetNodeID(id []byte) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - if setNodeID(id) { - ifname = "user" - return true - } - return false -} - -func setNodeID(id []byte) bool { - if len(id) < 6 { - return false - } - if nodeID == nil { - nodeID = make([]byte, 6) - } - copy(nodeID, id) - return true + return guuid.SetNodeID(id) } // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is diff --git a/vendor/github.com/pborman/uuid/sql.go b/vendor/github.com/pborman/uuid/sql.go index d015bfd13..929c3847e 100644 --- a/vendor/github.com/pborman/uuid/sql.go +++ b/vendor/github.com/pborman/uuid/sql.go @@ -40,7 +40,9 @@ func (uuid *UUID) Scan(src interface{}) error { // assumes a simple slice of bytes if 16 bytes // otherwise attempts to parse if len(b) == 16 { - *uuid = UUID(b) + parsed := make([]byte, 16) + copy(parsed, b) + *uuid = UUID(parsed) } else { u := Parse(string(b)) diff --git a/vendor/github.com/pborman/uuid/time.go b/vendor/github.com/pborman/uuid/time.go index eedf24219..7286824d8 100644 --- a/vendor/github.com/pborman/uuid/time.go +++ b/vendor/github.com/pborman/uuid/time.go @@ -6,65 +6,18 @@ package uuid import ( "encoding/binary" - "sync" - "time" + + guuid "github.com/google/uuid" ) // A Time represents a time as the number of 100's of nanoseconds since 15 Oct // 1582. -type Time int64 - -const ( - lillian = 2299160 // Julian day of 15 Oct 1582 - unix = 2440587 // Julian day of 1 Jan 1970 - epoch = unix - lillian // Days between epochs - g1582 = epoch * 86400 // seconds between epochs - g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs -) - -var ( - timeMu sync.Mutex - lasttime uint64 // last time we returned - clock_seq uint16 // clock sequence for this run - - timeNow = time.Now // for testing -) - -// UnixTime converts t the number of seconds and nanoseconds using the Unix -// epoch of 1 Jan 1970. -func (t Time) UnixTime() (sec, nsec int64) { - sec = int64(t - g1582ns100) - nsec = (sec % 10000000) * 100 - sec /= 10000000 - return sec, nsec -} +type Time = guuid.Time // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and // clock sequence as well as adjusting the clock sequence as needed. An error // is returned if the current time cannot be determined. -func GetTime() (Time, uint16, error) { - defer timeMu.Unlock() - timeMu.Lock() - return getTime() -} - -func getTime() (Time, uint16, error) { - t := timeNow() - - // If we don't have a clock sequence already, set one. - if clock_seq == 0 { - setClockSequence(-1) - } - now := uint64(t.UnixNano()/100) + g1582ns100 - - // If time has gone backwards with this clock sequence then we - // increment the clock sequence - if now <= lasttime { - clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000 - } - lasttime = now - return Time(now), clock_seq, nil -} +func GetTime() (Time, uint16, error) { return guuid.GetTime() } // ClockSequence returns the current clock sequence, generating one if not // already set. The clock sequence is only used for Version 1 UUIDs. @@ -74,39 +27,11 @@ func getTime() (Time, uint16, error) { // clock sequence is generated the first time a clock sequence is requested by // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated // for -func ClockSequence() int { - defer timeMu.Unlock() - timeMu.Lock() - return clockSequence() -} - -func clockSequence() int { - if clock_seq == 0 { - setClockSequence(-1) - } - return int(clock_seq & 0x3fff) -} +func ClockSequence() int { return guuid.ClockSequence() } -// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to +// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to // -1 causes a new sequence to be generated. -func SetClockSequence(seq int) { - defer timeMu.Unlock() - timeMu.Lock() - setClockSequence(seq) -} - -func setClockSequence(seq int) { - if seq == -1 { - var b [2]byte - randomBits(b[:]) // clock sequence - seq = int(b[0])<<8 | int(b[1]) - } - old_seq := clock_seq - clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant - if old_seq != clock_seq { - lasttime = 0 - } -} +func SetClockSequence(seq int) { guuid.SetClockSequence(seq) } // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in // uuid. It returns false if uuid is not valid. The time is only well defined diff --git a/vendor/github.com/pborman/uuid/util.go b/vendor/github.com/pborman/uuid/util.go index fc8e052c7..255b5e248 100644 --- a/vendor/github.com/pborman/uuid/util.go +++ b/vendor/github.com/pborman/uuid/util.go @@ -4,17 +4,6 @@ package uuid -import ( - "io" -) - -// randomBits completely fills slice b with random data. -func randomBits(b []byte) { - if _, err := io.ReadFull(rander, b); err != nil { - panic(err.Error()) // rand should never fail - } -} - // xvalues returns the value of a byte as a hexadecimal digit or 255. var xvalues = [256]byte{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, diff --git a/vendor/github.com/pborman/uuid/uuid.go b/vendor/github.com/pborman/uuid/uuid.go index 82c9e7ee7..337000420 100644 --- a/vendor/github.com/pborman/uuid/uuid.go +++ b/vendor/github.com/pborman/uuid/uuid.go @@ -8,9 +8,9 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "fmt" "io" - "strings" + + guuid "github.com/google/uuid" ) // Array is a pass-by-value UUID that can be used as an effecient key in a map. @@ -24,7 +24,7 @@ func (uuid Array) UUID() UUID { // String returns the string representation of uuid, // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. func (uuid Array) String() string { - return uuid.UUID().String() + return guuid.UUID(uuid).String() } // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -32,18 +32,18 @@ func (uuid Array) String() string { type UUID []byte // A Version represents a UUIDs version. -type Version byte +type Version = guuid.Version // A Variant represents a UUIDs variant. -type Variant byte +type Variant = guuid.Variant // Constants returned by Variant. const ( - Invalid = Variant(iota) // Invalid UUID - RFC4122 // The variant specified in RFC4122 - Reserved // Reserved, NCS backward compatibility. - Microsoft // Reserved, Microsoft Corporation backward compatibility. - Future // Reserved for future definition. + Invalid = guuid.Invalid // Invalid UUID + RFC4122 = guuid.RFC4122 // The variant specified in RFC4122 + Reserved = guuid.Reserved // Reserved, NCS backward compatibility. + Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future = guuid.Future // Reserved for future definition. ) var rander = rand.Reader // random function @@ -54,35 +54,23 @@ func New() string { return NewRandom().String() } -// Parse decodes s into a UUID or returns nil. Both the UUID form of -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. +// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for +// the formats parsed. func Parse(s string) UUID { - if len(s) == 36+9 { - if strings.ToLower(s[:9]) != "urn:uuid:" { - return nil - } - s = s[9:] - } else if len(s) != 36 { - return nil - } - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return nil + gu, err := guuid.Parse(s) + if err == nil { + return gu[:] } - var uuid [16]byte - for i, x := range [16]int{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34} { - if v, ok := xtob(s[x:]); !ok { - return nil - } else { - uuid[i] = v - } + return nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + gu, err := guuid.ParseBytes(b) + if err == nil { + return gu[:], nil } - return uuid[:] + return nil, err } // Equal returns true if uuid1 and uuid2 are equal. @@ -163,39 +151,12 @@ func (uuid UUID) Version() (Version, bool) { return Version(uuid[6] >> 4), true } -func (v Version) String() string { - if v > 15 { - return fmt.Sprintf("BAD_VERSION_%d", v) - } - return fmt.Sprintf("VERSION_%d", v) -} - -func (v Variant) String() string { - switch v { - case RFC4122: - return "RFC4122" - case Reserved: - return "Reserved" - case Microsoft: - return "Microsoft" - case Future: - return "Future" - case Invalid: - return "Invalid" - } - return fmt.Sprintf("BadVariant%d", int(v)) -} - -// SetRand sets the random number generator to r, which implents io.Reader. +// SetRand sets the random number generator to r, which implements io.Reader. // If r.Read returns an error when the package requests random data then // a panic will be issued. // // Calling SetRand with nil sets the random number generator to the default // generator. func SetRand(r io.Reader) { - if r == nil { - rander = rand.Reader - return - } - rander = r + guuid.SetRand(r) } diff --git a/vendor/github.com/pborman/uuid/version1.go b/vendor/github.com/pborman/uuid/version1.go index 0127eacfa..7af948da7 100644 --- a/vendor/github.com/pborman/uuid/version1.go +++ b/vendor/github.com/pborman/uuid/version1.go @@ -5,7 +5,7 @@ package uuid import ( - "encoding/binary" + guuid "github.com/google/uuid" ) // NewUUID returns a Version 1 UUID based on the current NodeID and clock @@ -15,27 +15,9 @@ import ( // SetClockSequence then it will be set automatically. If GetTime fails to // return the current NewUUID returns nil. func NewUUID() UUID { - if nodeID == nil { - SetNodeInterface("") + gu, err := guuid.NewUUID() + if err == nil { + return UUID(gu[:]) } - - now, seq, err := GetTime() - if err != nil { - return nil - } - - uuid := make([]byte, 16) - - time_low := uint32(now & 0xffffffff) - time_mid := uint16((now >> 32) & 0xffff) - time_hi := uint16((now >> 48) & 0x0fff) - time_hi |= 0x1000 // Version 1 - - binary.BigEndian.PutUint32(uuid[0:], time_low) - binary.BigEndian.PutUint16(uuid[4:], time_mid) - binary.BigEndian.PutUint16(uuid[6:], time_hi) - binary.BigEndian.PutUint16(uuid[8:], seq) - copy(uuid[10:], nodeID) - - return uuid + return nil } diff --git a/vendor/github.com/pborman/uuid/version4.go b/vendor/github.com/pborman/uuid/version4.go index b3d4a368d..767dd0c3a 100644 --- a/vendor/github.com/pborman/uuid/version4.go +++ b/vendor/github.com/pborman/uuid/version4.go @@ -4,12 +4,14 @@ package uuid -// Random returns a Random (Version 4) UUID or panics. +import guuid "github.com/google/uuid" + +// NewRandom returns a Random (Version 4) UUID or panics. // // The strength of the UUIDs is based on the strength of the crypto/rand // package. // -// A note about uniqueness derived from from the UUID Wikipedia entry: +// A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being // hit by a meteorite is estimated to be one chance in 17 billion, that @@ -17,9 +19,8 @@ package uuid // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() UUID { - uuid := make([]byte, 16) - randomBits([]byte(uuid)) - uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid + if gu, err := guuid.NewRandom(); err == nil { + return UUID(gu[:]) + } + return nil } diff --git a/vendor/github.com/phayes/freeport/README.md b/vendor/github.com/phayes/freeport/README.md index 36171cf31..1665ccf4d 100644 --- a/vendor/github.com/phayes/freeport/README.md +++ b/vendor/github.com/phayes/freeport/README.md @@ -1,8 +1,9 @@ FreePort ======== -Get a free open TCP port that is ready to use +Get a free open TCP port that is ready to use. +## Command Line Example: ```bash # Ask the kernel to give us an open port. export port=$(freeport) @@ -14,14 +15,44 @@ httpd -X -c "Listen $port" & curl localhost:$port ``` -#### Binary Downloads - - Mac: https://phayes.github.io/bin/current/freeport/mac/freeport.gz - - Linux: https://phayes.github.io/bin/current/freeport/linux/freeport.gz +## Golang example: +```go +package main + +import "github.com/phayes/freeport" + +func main() { + port, err := freeport.GetFreePort() + if err != nil { + log.Fatal(err) + } + // port is ready to listen on +} + +``` + +## Installation + +#### Mac OSX +```bash +brew install phayes/repo/freeport +``` + + +#### CentOS and other RPM based systems +```bash +wget https://github.com/phayes/freeport/releases/download/1.0.2/freeport_1.0.2_linux_386.rpm +rpm -Uvh freeport_1.0.2_linux_386.rpm +``` + +#### Ubuntu and other DEB based systems +```bash +wget wget https://github.com/phayes/freeport/releases/download/1.0.2/freeport_1.0.2_linux_amd64.deb +dpkg -i freeport_1.0.2_linux_amd64.deb +``` #### Building From Source ```bash sudo apt-get install golang # Download go. Alternativly build from source: https://golang.org/doc/install/source -mkdir ~/.gopath && export GOPATH=~/.gopath # Replace with desired GOPATH -export PATH=$PATH:$GOPATH/bin # For convenience, add go's bin dir to your PATH -go get github.com/phayes/freeport/cmd/freeport +go get github.com/phayes/freeport ``` diff --git a/vendor/github.com/phayes/freeport/freeport.go b/vendor/github.com/phayes/freeport/freeport.go index 8ff03c221..fcfb6bab0 100644 --- a/vendor/github.com/phayes/freeport/freeport.go +++ b/vendor/github.com/phayes/freeport/freeport.go @@ -4,17 +4,46 @@ import ( "net" ) -// Ask the kernel for a free open port that is ready to use -func GetPort() int { +// GetFreePort asks the kernel for a free open port that is ready to use. +func GetFreePort() (int, error) { addr, err := net.ResolveTCPAddr("tcp", "localhost:0") if err != nil { - panic(err) + return 0, err } l, err := net.ListenTCP("tcp", addr) if err != nil { - panic(err) + return 0, err } defer l.Close() - return l.Addr().(*net.TCPAddr).Port + return l.Addr().(*net.TCPAddr).Port, nil +} + +// GetPort is deprecated, use GetFreePort instead +// Ask the kernel for a free open port that is ready to use +func GetPort() int { + port, err := GetFreePort() + if err != nil { + panic(err) + } + return port +} + +// GetFreePort asks the kernel for free open ports that are ready to use. +func GetFreePorts(count int) ([]int, error) { + var ports []int + for i := 0; i < count; i++ { + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + return nil, err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil, err + } + defer l.Close() + ports = append(ports, l.Addr().(*net.TCPAddr).Port) + } + return ports, nil } diff --git a/vendor/github.com/rakyll/statik/fs/fs.go b/vendor/github.com/rakyll/statik/fs/fs.go index e328d5a24..5a5b46f2f 100644 --- a/vendor/github.com/rakyll/statik/fs/fs.go +++ b/vendor/github.com/rakyll/statik/fs/fs.go @@ -12,135 +12,227 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package contains an HTTP file system that works with zip contents. +// Package fs contains an HTTP file system that works with zip contents. package fs import ( "archive/zip" "bytes" "errors" + "fmt" "io" "io/ioutil" "net/http" "os" + "path" + "path/filepath" + "sort" "strings" - "sync" + "time" ) -var zipData string +var zipData = map[string]string{} + +// file holds unzipped read-only file contents and file metadata. +type file struct { + os.FileInfo + data []byte + fs *statikFS +} type statikFS struct { - files map[string]*zip.File + files map[string]file + dirs map[string][]string +} + +const defaultNamespace = "default" + +// IsDefaultNamespace returns true if the assetNamespace is +// the default one +func IsDefaultNamespace(assetNamespace string) bool { + return assetNamespace == defaultNamespace } -// Registers zip contents data, later used to initialize +// Register registers zip contents data, later used to initialize // the statik file system. func Register(data string) { - zipData = data + RegisterWithNamespace(defaultNamespace, data) } -// Creates a new file system with the registered zip contents data. +// RegisterWithNamespace registers zip contents data and set asset namespace, +// later used to initialize the statik file system. +func RegisterWithNamespace(assetNamespace string, data string) { + zipData[assetNamespace] = data +} + +// New creates a new file system with the default registered zip contents data. +// It unzips all files and stores them in an in-memory map. func New() (http.FileSystem, error) { - if zipData == "" { - return nil, errors.New("statik/fs: No zip data registered.") + return NewWithNamespace(defaultNamespace) +} + +// NewWithNamespace creates a new file system with the registered zip contents data. +// It unzips all files and stores them in an in-memory map. +func NewWithNamespace(assetNamespace string) (http.FileSystem, error) { + asset, ok := zipData[assetNamespace] + if !ok { + return nil, errors.New("statik/fs: no zip data registered") } - zipReader, err := zip.NewReader(strings.NewReader(zipData), int64(len(zipData))) + zipReader, err := zip.NewReader(strings.NewReader(asset), int64(len(asset))) if err != nil { return nil, err } - files := make(map[string]*zip.File) - for _, file := range zipReader.File { - files["/"+file.Name] = file + files := make(map[string]file, len(zipReader.File)) + dirs := make(map[string][]string) + fs := &statikFS{files: files, dirs: dirs} + for _, zipFile := range zipReader.File { + fi := zipFile.FileInfo() + f := file{FileInfo: fi, fs: fs} + f.data, err = unzip(zipFile) + if err != nil { + return nil, fmt.Errorf("statik/fs: error unzipping file %q: %s", zipFile.Name, err) + } + files["/"+zipFile.Name] = f + } + for fn := range files { + // go up directories recursively in order to care deep directory + for dn := path.Dir(fn); dn != fn; { + if _, ok := files[dn]; !ok { + files[dn] = file{FileInfo: dirInfo{dn}, fs: fs} + } else { + break + } + fn, dn = dn, path.Dir(dn) + } + } + for fn := range files { + dn := path.Dir(fn) + if fn != dn { + fs.dirs[dn] = append(fs.dirs[dn], path.Base(fn)) + } + } + for _, s := range fs.dirs { + sort.Strings(s) } - return &statikFS{files: files}, nil + return fs, nil } -// Opens a file, unzip the contents and initializes -// readers. Returns os.ErrNotExists if file is not -// found in the archive. -func (fs *statikFS) Open(name string) (http.File, error) { - name = strings.Replace(name, "//", "/", -1) - f, ok := fs.files[name] - - // The file doesn't match, but maybe it's a directory, - // thus we should look for index.html - if !ok { - indexName := strings.Replace(name+"/index.html", "//", "/", -1) - f, ok = fs.files[indexName] +var _ = os.FileInfo(dirInfo{}) - if !ok { - return nil, os.ErrNotExist - } +type dirInfo struct { + name string +} - return newFile(f, true) +func (di dirInfo) Name() string { return path.Base(di.name) } +func (di dirInfo) Size() int64 { return 0 } +func (di dirInfo) Mode() os.FileMode { return 0755 | os.ModeDir } +func (di dirInfo) ModTime() time.Time { return time.Time{} } +func (di dirInfo) IsDir() bool { return true } +func (di dirInfo) Sys() interface{} { return nil } + +// Open returns a file matching the given file name, or os.ErrNotExists if +// no file matching the given file name is found in the archive. +// If a directory is requested, Open returns the file named "index.html" +// in the requested directory, if that file exists. +func (fs *statikFS) Open(name string) (http.File, error) { + name = filepath.ToSlash(filepath.Clean(name)) + if f, ok := fs.files[name]; ok { + return newHTTPFile(f), nil } - return newFile(f, false) + return nil, os.ErrNotExist } -var nopCloser = ioutil.NopCloser(nil) - -func newFile(zf *zip.File, isDir bool) (*file, error) { - rc, err := zf.Open() - if err != nil { - return nil, err +func newHTTPFile(file file) *httpFile { + if file.IsDir() { + return &httpFile{file: file, isDir: true} } - defer rc.Close() - all, err := ioutil.ReadAll(rc) - if err != nil { - return nil, err - } - return &file{ - FileInfo: zf.FileInfo(), - data: all, - readerAt: bytes.NewReader(all), - Closer: nopCloser, - isDir: isDir, - }, nil + return &httpFile{file: file, reader: bytes.NewReader(file.data)} } -// Represents an HTTP file, acts as a bridge between -// zip.File and http.File. -type file struct { - os.FileInfo - io.Closer - - data []byte // non-nil if regular file - reader *io.SectionReader - readerAt io.ReaderAt // over data - isDir bool +// httpFile represents an HTTP file and acts as a bridge +// between file and http.File. +type httpFile struct { + file - once sync.Once + reader *bytes.Reader + isDir bool + dirIdx int } -func (f *file) newReader() { - f.reader = io.NewSectionReader(f.readerAt, 0, f.FileInfo.Size()) -} - -// Reads bytes into p, returns the number of read bytes. -func (f *file) Read(p []byte) (n int, err error) { - f.once.Do(f.newReader) +// Read reads bytes into p, returns the number of read bytes. +func (f *httpFile) Read(p []byte) (n int, err error) { + if f.reader == nil && f.isDir { + return 0, io.EOF + } return f.reader.Read(p) } -// Seeks to the offset. -func (f *file) Seek(offset int64, whence int) (ret int64, err error) { - f.once.Do(f.newReader) +// Seek seeks to the offset. +func (f *httpFile) Seek(offset int64, whence int) (ret int64, err error) { return f.reader.Seek(offset, whence) } -// Stats the file. -func (f *file) Stat() (os.FileInfo, error) { +// Stat stats the file. +func (f *httpFile) Stat() (os.FileInfo, error) { return f, nil } // IsDir returns true if the file location represents a directory. -func (f *file) IsDir() bool { +func (f *httpFile) IsDir() bool { return f.isDir } -// Returns an empty slice of files, directory +// Readdir returns an empty slice of files, directory // listing is disabled. -func (f *file) Readdir(count int) ([]os.FileInfo, error) { - // directory listing is disabled. - return make([]os.FileInfo, 0), nil +func (f *httpFile) Readdir(count int) ([]os.FileInfo, error) { + var fis []os.FileInfo + if !f.isDir { + return fis, nil + } + di, ok := f.FileInfo.(dirInfo) + if !ok { + return nil, fmt.Errorf("failed to read directory: %q", f.Name()) + } + + // If count is positive, the specified number of files will be returned, + // and if non-positive, all remaining files will be returned. + // The reading position of which file is returned is held in dirIndex. + fnames := f.file.fs.dirs[di.name] + flen := len(fnames) + + // If dirIdx reaches the end and the count is a positive value, + // an io.EOF error is returned. + // In other cases, no error will be returned even if, for example, + // you specified more counts than the number of remaining files. + start := f.dirIdx + if start >= flen && count > 0 { + return fis, io.EOF + } + var end int + if count <= 0 { + end = flen + } else { + end = start + count + } + if end > flen { + end = flen + } + for i := start; i < end; i++ { + fis = append(fis, f.file.fs.files[path.Join(di.name, fnames[i])].FileInfo) + } + f.dirIdx += len(fis) + return fis, nil +} + +func (f *httpFile) Close() error { + return nil +} + +func unzip(zf *zip.File) ([]byte, error) { + rc, err := zf.Open() + if err != nil { + return nil, err + } + defer rc.Close() + return ioutil.ReadAll(rc) } diff --git a/vendor/github.com/rcrowley/go-metrics/.travis.yml b/vendor/github.com/rcrowley/go-metrics/.travis.yml index 20aa5d042..ce9afeaee 100644 --- a/vendor/github.com/rcrowley/go-metrics/.travis.yml +++ b/vendor/github.com/rcrowley/go-metrics/.travis.yml @@ -1,10 +1,19 @@ language: go go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 + - "1.3" + - "1.4" + - "1.5" + - "1.6" + - "1.7" + - "1.8" + - "1.9" + - "1.10" + - "1.11" + - "1.12" + - "1.13" + - "1.14" + - "1.15" script: - ./validate.sh diff --git a/vendor/github.com/rcrowley/go-metrics/README.md b/vendor/github.com/rcrowley/go-metrics/README.md index 66ba9cab5..27ddfee8b 100644 --- a/vendor/github.com/rcrowley/go-metrics/README.md +++ b/vendor/github.com/rcrowley/go-metrics/README.md @@ -21,6 +21,9 @@ g := metrics.NewGauge() metrics.Register("bar", g) g.Update(47) +r := NewRegistry() +g := metrics.NewRegisteredFunctionalGauge("cache-evictions", r, func() int64 { return cache.getEvictionsCount() }) + s := metrics.NewExpDecaySample(1028, 0.015) // or metrics.NewUniformSample(1028) h := metrics.NewHistogram(s) metrics.Register("baz", h) @@ -36,6 +39,25 @@ t.Time(func() {}) t.Update(47) ``` +Register() is not threadsafe. For threadsafe metric registration use +GetOrRegister: + +```go +t := metrics.GetOrRegisterTimer("account.create.latency", nil) +t.Time(func() {}) +t.Update(47) +``` + +**NOTE:** Be sure to unregister short-lived meters and timers otherwise they will +leak memory: + +```go +// Will call Stop() on the Meter to allow for garbage collection +metrics.Unregister("quux") +// Or similarly for a Timer that embeds a Meter +metrics.Unregister("bang") +``` + Periodically log every metric in human-readable form to standard error: ```go @@ -67,14 +89,15 @@ issues [#121](https://github.com/rcrowley/go-metrics/issues/121) and [#124](https://github.com/rcrowley/go-metrics/issues/124) for progress and details. ```go -import "github.com/rcrowley/go-metrics/influxdb" - -go influxdb.Influxdb(metrics.DefaultRegistry, 10e9, &influxdb.Config{ - Host: "127.0.0.1:8086", - Database: "metrics", - Username: "test", - Password: "test", -}) +import "github.com/vrischmann/go-metrics-influxdb" + +go influxdb.InfluxDB(metrics.DefaultRegistry, + 10e9, + "127.0.0.1:8086", + "database-name", + "username", + "password" +) ``` Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato): @@ -134,6 +157,15 @@ Publishing Metrics Clients are available for the following destinations: -* Librato - [https://github.com/mihasya/go-metrics-librato](https://github.com/mihasya/go-metrics-librato) -* Graphite - [https://github.com/cyberdelia/go-metrics-graphite](https://github.com/cyberdelia/go-metrics-graphite) -* InfluxDB - [https://github.com/vrischmann/go-metrics-influxdb](https://github.com/vrischmann/go-metrics-influxdb) +* AppOptics - https://github.com/ysamlan/go-metrics-appoptics +* Librato - https://github.com/mihasya/go-metrics-librato +* Graphite - https://github.com/cyberdelia/go-metrics-graphite +* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb +* Ganglia - https://github.com/appscode/metlia +* Prometheus - https://github.com/deathowl/go-metrics-prometheus +* DataDog - https://github.com/syntaqx/go-metrics-datadog +* SignalFX - https://github.com/pascallouisperez/go-metrics-signalfx +* Honeycomb - https://github.com/getspine/go-metrics-honeycomb +* Wavefront - https://github.com/wavefrontHQ/go-metrics-wavefront +* Open-Falcon - https://github.com/g4zhuj/go-metrics-falcon +* AWS CloudWatch - [https://github.com/savaki/cloudmetrics](https://github.com/savaki/cloudmetrics) diff --git a/vendor/github.com/rcrowley/go-metrics/debug.go b/vendor/github.com/rcrowley/go-metrics/debug.go index 043ccefab..179e5aae7 100644 --- a/vendor/github.com/rcrowley/go-metrics/debug.go +++ b/vendor/github.com/rcrowley/go-metrics/debug.go @@ -2,6 +2,7 @@ package metrics import ( "runtime/debug" + "sync" "time" ) @@ -16,7 +17,8 @@ var ( } ReadGCStats Timer } - gcStats debug.GCStats + gcStats debug.GCStats + registerDebugMetricsOnce = sync.Once{} ) // Capture new values for the Go garbage collector statistics exported in @@ -54,19 +56,21 @@ func CaptureDebugGCStatsOnce(r Registry) { // debug.GCStats. The metrics are named by their fully-qualified Go symbols, // i.e. debug.GCStats.PauseTotal. func RegisterDebugGCStats(r Registry) { - debugMetrics.GCStats.LastGC = NewGauge() - debugMetrics.GCStats.NumGC = NewGauge() - debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) - //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) - debugMetrics.GCStats.PauseTotal = NewGauge() - debugMetrics.ReadGCStats = NewTimer() + registerDebugMetricsOnce.Do(func() { + debugMetrics.GCStats.LastGC = NewGauge() + debugMetrics.GCStats.NumGC = NewGauge() + debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) + //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) + debugMetrics.GCStats.PauseTotal = NewGauge() + debugMetrics.ReadGCStats = NewTimer() - r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) - r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) - r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) - //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) - r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) - r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) + r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) + r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) + r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) + //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) + r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) + r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) + }) } // Allocate an initial slice for gcStats.Pause to avoid allocations during diff --git a/vendor/github.com/rcrowley/go-metrics/ewma.go b/vendor/github.com/rcrowley/go-metrics/ewma.go index 694a1d033..a8183dd7e 100644 --- a/vendor/github.com/rcrowley/go-metrics/ewma.go +++ b/vendor/github.com/rcrowley/go-metrics/ewma.go @@ -79,16 +79,15 @@ func (NilEWMA) Update(n int64) {} type StandardEWMA struct { uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment alpha float64 - rate float64 - init bool + rate uint64 + init uint32 mutex sync.Mutex } // Rate returns the moving average rate of events per second. func (a *StandardEWMA) Rate() float64 { - a.mutex.Lock() - defer a.mutex.Unlock() - return a.rate * float64(1e9) + currentRate := math.Float64frombits(atomic.LoadUint64(&a.rate)) * float64(1e9) + return currentRate } // Snapshot returns a read-only copy of the EWMA. @@ -99,17 +98,38 @@ func (a *StandardEWMA) Snapshot() EWMA { // Tick ticks the clock to update the moving average. It assumes it is called // every five seconds. func (a *StandardEWMA) Tick() { + // Optimization to avoid mutex locking in the hot-path. + if atomic.LoadUint32(&a.init) == 1 { + a.updateRate(a.fetchInstantRate()) + } else { + // Slow-path: this is only needed on the first Tick() and preserves transactional updating + // of init and rate in the else block. The first conditional is needed below because + // a different thread could have set a.init = 1 between the time of the first atomic load and when + // the lock was acquired. + a.mutex.Lock() + if atomic.LoadUint32(&a.init) == 1 { + // The fetchInstantRate() uses atomic loading, which is unecessary in this critical section + // but again, this section is only invoked on the first successful Tick() operation. + a.updateRate(a.fetchInstantRate()) + } else { + atomic.StoreUint32(&a.init, 1) + atomic.StoreUint64(&a.rate, math.Float64bits(a.fetchInstantRate())) + } + a.mutex.Unlock() + } +} + +func (a *StandardEWMA) fetchInstantRate() float64 { count := atomic.LoadInt64(&a.uncounted) atomic.AddInt64(&a.uncounted, -count) instantRate := float64(count) / float64(5e9) - a.mutex.Lock() - defer a.mutex.Unlock() - if a.init { - a.rate += a.alpha * (instantRate - a.rate) - } else { - a.init = true - a.rate = instantRate - } + return instantRate +} + +func (a *StandardEWMA) updateRate(instantRate float64) { + currentRate := math.Float64frombits(atomic.LoadUint64(&a.rate)) + currentRate += a.alpha * (instantRate - currentRate) + atomic.StoreUint64(&a.rate, math.Float64bits(currentRate)) } // Update adds n uncounted events. diff --git a/vendor/github.com/rcrowley/go-metrics/gauge.go b/vendor/github.com/rcrowley/go-metrics/gauge.go index 807638a31..cb57a9388 100644 --- a/vendor/github.com/rcrowley/go-metrics/gauge.go +++ b/vendor/github.com/rcrowley/go-metrics/gauge.go @@ -36,6 +36,24 @@ func NewRegisteredGauge(name string, r Registry) Gauge { return c } +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGauge(f func() int64) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &FunctionalGauge{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { + c := NewFunctionalGauge(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + // GaugeSnapshot is a read-only copy of another Gauge. type GaugeSnapshot int64 @@ -82,3 +100,21 @@ func (g *StandardGauge) Update(v int64) { func (g *StandardGauge) Value() int64 { return atomic.LoadInt64(&g.value) } + +// FunctionalGauge returns value from given function +type FunctionalGauge struct { + value func() int64 +} + +// Value returns the gauge's current value. +func (g FunctionalGauge) Value() int64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } + +// Update panics. +func (FunctionalGauge) Update(int64) { + panic("Update called on a FunctionalGauge") +} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge_float64.go b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go index 47c3566c2..3962e6db0 100644 --- a/vendor/github.com/rcrowley/go-metrics/gauge_float64.go +++ b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go @@ -1,6 +1,9 @@ package metrics -import "sync" +import ( + "math" + "sync/atomic" +) // GaugeFloat64s hold a float64 value that can be set arbitrarily. type GaugeFloat64 interface { @@ -38,6 +41,24 @@ func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { return c } +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &FunctionalGaugeFloat64{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { + c := NewFunctionalGaugeFloat64(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + // GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. type GaugeFloat64Snapshot float64 @@ -67,8 +88,7 @@ func (NilGaugeFloat64) Value() float64 { return 0.0 } // StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses // sync.Mutex to manage a single float64 value. type StandardGaugeFloat64 struct { - mutex sync.Mutex - value float64 + value uint64 } // Snapshot returns a read-only copy of the gauge. @@ -78,14 +98,28 @@ func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { // Update updates the gauge's value. func (g *StandardGaugeFloat64) Update(v float64) { - g.mutex.Lock() - defer g.mutex.Unlock() - g.value = v + atomic.StoreUint64(&g.value, math.Float64bits(v)) } // Value returns the gauge's current value. func (g *StandardGaugeFloat64) Value() float64 { - g.mutex.Lock() - defer g.mutex.Unlock() - return g.value + return math.Float64frombits(atomic.LoadUint64(&g.value)) +} + +// FunctionalGaugeFloat64 returns value from given function +type FunctionalGaugeFloat64 struct { + value func() float64 +} + +// Value returns the gauge's current value. +func (g FunctionalGaugeFloat64) Value() float64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } + +// Update panics. +func (FunctionalGaugeFloat64) Update(float64) { + panic("Update called on a FunctionalGaugeFloat64") } diff --git a/vendor/github.com/rcrowley/go-metrics/json.go b/vendor/github.com/rcrowley/go-metrics/json.go index 2676aeea5..174b9477e 100644 --- a/vendor/github.com/rcrowley/go-metrics/json.go +++ b/vendor/github.com/rcrowley/go-metrics/json.go @@ -9,63 +9,7 @@ import ( // MarshalJSON returns a byte slice containing a JSON representation of all // the metrics in the Registry. func (r *StandardRegistry) MarshalJSON() ([]byte, error) { - data := make(map[string]map[string]interface{}) - r.Each(func(name string, i interface{}) { - values := make(map[string]interface{}) - switch metric := i.(type) { - case Counter: - values["count"] = metric.Count() - case Gauge: - values["value"] = metric.Value() - case GaugeFloat64: - values["value"] = metric.Value() - case Healthcheck: - values["error"] = nil - metric.Check() - if err := metric.Error(); nil != err { - values["error"] = metric.Error().Error() - } - case Histogram: - h := metric.Snapshot() - ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) - values["count"] = h.Count() - values["min"] = h.Min() - values["max"] = h.Max() - values["mean"] = h.Mean() - values["stddev"] = h.StdDev() - values["median"] = ps[0] - values["75%"] = ps[1] - values["95%"] = ps[2] - values["99%"] = ps[3] - values["99.9%"] = ps[4] - case Meter: - m := metric.Snapshot() - values["count"] = m.Count() - values["1m.rate"] = m.Rate1() - values["5m.rate"] = m.Rate5() - values["15m.rate"] = m.Rate15() - values["mean.rate"] = m.RateMean() - case Timer: - t := metric.Snapshot() - ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) - values["count"] = t.Count() - values["min"] = t.Min() - values["max"] = t.Max() - values["mean"] = t.Mean() - values["stddev"] = t.StdDev() - values["median"] = ps[0] - values["75%"] = ps[1] - values["95%"] = ps[2] - values["99%"] = ps[3] - values["99.9%"] = ps[4] - values["1m.rate"] = t.Rate1() - values["5m.rate"] = t.Rate5() - values["15m.rate"] = t.Rate15() - values["mean.rate"] = t.RateMean() - } - data[name] = values - }) - return json.Marshal(data) + return json.Marshal(r.GetAll()) } // WriteJSON writes metrics from the given registry periodically to the @@ -81,3 +25,7 @@ func WriteJSON(r Registry, d time.Duration, w io.Writer) { func WriteJSONOnce(r Registry, w io.Writer) { json.NewEncoder(w).Encode(r) } + +func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(p.GetAll()) +} diff --git a/vendor/github.com/rcrowley/go-metrics/log.go b/vendor/github.com/rcrowley/go-metrics/log.go index f074eb03d..2614a0a33 100644 --- a/vendor/github.com/rcrowley/go-metrics/log.go +++ b/vendor/github.com/rcrowley/go-metrics/log.go @@ -1,21 +1,44 @@ package metrics import ( - "log" "time" ) -func Log(r Registry, freq time.Duration, l *log.Logger) { +type Logger interface { + Printf(format string, v ...interface{}) +} + +// Log outputs each metric in the given registry periodically using the given logger. +func Log(r Registry, freq time.Duration, l Logger) { LogScaled(r, freq, time.Nanosecond, l) } -// Output each metric in the given registry periodically using the given +// LogOnCue outputs each metric in the given registry on demand through the channel +// using the given logger +func LogOnCue(r Registry, ch chan interface{}, l Logger) { + LogScaledOnCue(r, ch, time.Nanosecond, l) +} + +// LogScaled outputs each metric in the given registry periodically using the given // logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. -func LogScaled(r Registry, freq time.Duration, scale time.Duration, l *log.Logger) { +func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { + ch := make(chan interface{}) + go func(channel chan interface{}) { + for _ = range time.Tick(freq) { + channel <- struct{}{} + } + }(ch) + LogScaledOnCue(r, ch, scale, l) +} + +// LogScaledOnCue outputs each metric in the given registry on demand through the channel +// using the given logger. Print timings in `scale` units (eg time.Millisecond) rather +// than nanos. +func LogScaledOnCue(r Registry, ch chan interface{}, scale time.Duration, l Logger) { du := float64(scale) duSuffix := scale.String()[1:] - for _ = range time.Tick(freq) { + for _ = range ch { r.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: diff --git a/vendor/github.com/rcrowley/go-metrics/meter.go b/vendor/github.com/rcrowley/go-metrics/meter.go index 0389ab0b8..223669bcb 100644 --- a/vendor/github.com/rcrowley/go-metrics/meter.go +++ b/vendor/github.com/rcrowley/go-metrics/meter.go @@ -1,7 +1,9 @@ package metrics import ( + "math" "sync" + "sync/atomic" "time" ) @@ -15,10 +17,13 @@ type Meter interface { Rate15() float64 RateMean() float64 Snapshot() Meter + Stop() } // GetOrRegisterMeter returns an existing Meter or constructs and registers a // new StandardMeter. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func GetOrRegisterMeter(name string, r Registry) Meter { if nil == r { r = DefaultRegistry @@ -27,6 +32,7 @@ func GetOrRegisterMeter(name string, r Registry) Meter { } // NewMeter constructs a new StandardMeter and launches a goroutine. +// Be sure to call Stop() once the meter is of no use to allow for garbage collection. func NewMeter() Meter { if UseNilMetrics { return NilMeter{} @@ -34,7 +40,7 @@ func NewMeter() Meter { m := newStandardMeter() arbiter.Lock() defer arbiter.Unlock() - arbiter.meters = append(arbiter.meters, m) + arbiter.meters[m] = struct{}{} if !arbiter.started { arbiter.started = true go arbiter.tick() @@ -44,6 +50,8 @@ func NewMeter() Meter { // NewMeter constructs and registers a new StandardMeter and launches a // goroutine. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func NewRegisteredMeter(name string, r Registry) Meter { c := NewMeter() if nil == r { @@ -56,7 +64,7 @@ func NewRegisteredMeter(name string, r Registry) Meter { // MeterSnapshot is a read-only copy of another Meter. type MeterSnapshot struct { count int64 - rate1, rate5, rate15, rateMean float64 + rate1, rate5, rate15, rateMean uint64 } // Count returns the count of events at the time the snapshot was taken. @@ -69,23 +77,26 @@ func (*MeterSnapshot) Mark(n int64) { // Rate1 returns the one-minute moving average rate of events per second at the // time the snapshot was taken. -func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } +func (m *MeterSnapshot) Rate1() float64 { return math.Float64frombits(m.rate1) } // Rate5 returns the five-minute moving average rate of events per second at // the time the snapshot was taken. -func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } +func (m *MeterSnapshot) Rate5() float64 { return math.Float64frombits(m.rate5) } // Rate15 returns the fifteen-minute moving average rate of events per second // at the time the snapshot was taken. -func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } +func (m *MeterSnapshot) Rate15() float64 { return math.Float64frombits(m.rate15) } // RateMean returns the meter's mean rate of events per second at the time the // snapshot was taken. -func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } +func (m *MeterSnapshot) RateMean() float64 { return math.Float64frombits(m.rateMean) } // Snapshot returns the snapshot. func (m *MeterSnapshot) Snapshot() Meter { return m } +// Stop is a no-op. +func (m *MeterSnapshot) Stop() {} + // NilMeter is a no-op Meter. type NilMeter struct{} @@ -110,12 +121,15 @@ func (NilMeter) RateMean() float64 { return 0.0 } // Snapshot is a no-op. func (NilMeter) Snapshot() Meter { return NilMeter{} } +// Stop is a no-op. +func (NilMeter) Stop() {} + // StandardMeter is the standard implementation of a Meter. type StandardMeter struct { - lock sync.RWMutex snapshot *MeterSnapshot a1, a5, a15 EWMA startTime time.Time + stopped uint32 } func newStandardMeter() *StandardMeter { @@ -128,19 +142,28 @@ func newStandardMeter() *StandardMeter { } } +// Stop stops the meter, Mark() will be a no-op if you use it after being stopped. +func (m *StandardMeter) Stop() { + if atomic.CompareAndSwapUint32(&m.stopped, 0, 1) { + arbiter.Lock() + delete(arbiter.meters, m) + arbiter.Unlock() + } +} + // Count returns the number of events recorded. func (m *StandardMeter) Count() int64 { - m.lock.RLock() - count := m.snapshot.count - m.lock.RUnlock() - return count + return atomic.LoadInt64(&m.snapshot.count) } // Mark records the occurance of n events. func (m *StandardMeter) Mark(n int64) { - m.lock.Lock() - defer m.lock.Unlock() - m.snapshot.count += n + if atomic.LoadUint32(&m.stopped) == 1 { + return + } + + atomic.AddInt64(&m.snapshot.count, n) + m.a1.Update(n) m.a5.Update(n) m.a15.Update(n) @@ -149,70 +172,65 @@ func (m *StandardMeter) Mark(n int64) { // Rate1 returns the one-minute moving average rate of events per second. func (m *StandardMeter) Rate1() float64 { - m.lock.RLock() - rate1 := m.snapshot.rate1 - m.lock.RUnlock() - return rate1 + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate1)) } // Rate5 returns the five-minute moving average rate of events per second. func (m *StandardMeter) Rate5() float64 { - m.lock.RLock() - rate5 := m.snapshot.rate5 - m.lock.RUnlock() - return rate5 + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate5)) } // Rate15 returns the fifteen-minute moving average rate of events per second. func (m *StandardMeter) Rate15() float64 { - m.lock.RLock() - rate15 := m.snapshot.rate15 - m.lock.RUnlock() - return rate15 + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate15)) } // RateMean returns the meter's mean rate of events per second. func (m *StandardMeter) RateMean() float64 { - m.lock.RLock() - rateMean := m.snapshot.rateMean - m.lock.RUnlock() - return rateMean + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rateMean)) } // Snapshot returns a read-only copy of the meter. func (m *StandardMeter) Snapshot() Meter { - m.lock.RLock() - snapshot := *m.snapshot - m.lock.RUnlock() - return &snapshot + copiedSnapshot := MeterSnapshot{ + count: atomic.LoadInt64(&m.snapshot.count), + rate1: atomic.LoadUint64(&m.snapshot.rate1), + rate5: atomic.LoadUint64(&m.snapshot.rate5), + rate15: atomic.LoadUint64(&m.snapshot.rate15), + rateMean: atomic.LoadUint64(&m.snapshot.rateMean), + } + return &copiedSnapshot } func (m *StandardMeter) updateSnapshot() { - // should run with write lock held on m.lock - snapshot := m.snapshot - snapshot.rate1 = m.a1.Rate() - snapshot.rate5 = m.a5.Rate() - snapshot.rate15 = m.a15.Rate() - snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() + rate1 := math.Float64bits(m.a1.Rate()) + rate5 := math.Float64bits(m.a5.Rate()) + rate15 := math.Float64bits(m.a15.Rate()) + rateMean := math.Float64bits(float64(m.Count()) / time.Since(m.startTime).Seconds()) + + atomic.StoreUint64(&m.snapshot.rate1, rate1) + atomic.StoreUint64(&m.snapshot.rate5, rate5) + atomic.StoreUint64(&m.snapshot.rate15, rate15) + atomic.StoreUint64(&m.snapshot.rateMean, rateMean) } func (m *StandardMeter) tick() { - m.lock.Lock() - defer m.lock.Unlock() m.a1.Tick() m.a5.Tick() m.a15.Tick() m.updateSnapshot() } +// meterArbiter ticks meters every 5s from a single goroutine. +// meters are references in a set for future stopping. type meterArbiter struct { sync.RWMutex started bool - meters []*StandardMeter + meters map[*StandardMeter]struct{} ticker *time.Ticker } -var arbiter = meterArbiter{ticker: time.NewTicker(5e9)} +var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})} // Ticks meters on the scheduled interval func (ma *meterArbiter) tick() { @@ -227,7 +245,7 @@ func (ma *meterArbiter) tick() { func (ma *meterArbiter) tickMeters() { ma.RLock() defer ma.RUnlock() - for _, meter := range ma.meters { + for meter := range ma.meters { meter.tick() } } diff --git a/vendor/github.com/rcrowley/go-metrics/registry.go b/vendor/github.com/rcrowley/go-metrics/registry.go index e1f68a5dc..a8e67228a 100644 --- a/vendor/github.com/rcrowley/go-metrics/registry.go +++ b/vendor/github.com/rcrowley/go-metrics/registry.go @@ -3,6 +3,7 @@ package metrics import ( "fmt" "reflect" + "strings" "sync" ) @@ -28,6 +29,9 @@ type Registry interface { // Get the metric by the given name or nil if none is registered. Get(string) interface{} + // GetAll metrics in the Registry. + GetAll() map[string]map[string]interface{} + // Gets an existing metric or registers the given one. // The interface can be the metric to register if not found in registry, // or a function returning the metric for lazy instantiation. @@ -50,7 +54,7 @@ type Registry interface { // of names to metrics. type StandardRegistry struct { metrics map[string]interface{} - mutex sync.Mutex + mutex sync.RWMutex } // Create a new registry. @@ -60,15 +64,17 @@ func NewRegistry() Registry { // Call the given function for each registered metric. func (r *StandardRegistry) Each(f func(string, interface{})) { - for name, i := range r.registered() { - f(name, i) + metrics := r.registered() + for i := range metrics { + kv := &metrics[i] + f(kv.name, kv.value) } } // Get the metric by the given name or nil if none is registered. func (r *StandardRegistry) Get(name string) interface{} { - r.mutex.Lock() - defer r.mutex.Unlock() + r.mutex.RLock() + defer r.mutex.RUnlock() return r.metrics[name] } @@ -77,6 +83,15 @@ func (r *StandardRegistry) Get(name string) interface{} { // The interface can be the metric to register if not found in registry, // or a function returning the metric for lazy instantiation. func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { + // access the read lock first which should be re-entrant + r.mutex.RLock() + metric, ok := r.metrics[name] + r.mutex.RUnlock() + if ok { + return metric + } + + // only take the write lock if we'll be modifying the metrics map r.mutex.Lock() defer r.mutex.Unlock() if metric, ok := r.metrics[name]; ok { @@ -99,8 +114,8 @@ func (r *StandardRegistry) Register(name string, i interface{}) error { // Run all registered healthchecks. func (r *StandardRegistry) RunHealthchecks() { - r.mutex.Lock() - defer r.mutex.Unlock() + r.mutex.RLock() + defer r.mutex.RUnlock() for _, i := range r.metrics { if h, ok := i.(Healthcheck); ok { h.Check() @@ -108,10 +123,72 @@ func (r *StandardRegistry) RunHealthchecks() { } } +// GetAll metrics in the Registry +func (r *StandardRegistry) GetAll() map[string]map[string]interface{} { + data := make(map[string]map[string]interface{}) + r.Each(func(name string, i interface{}) { + values := make(map[string]interface{}) + switch metric := i.(type) { + case Counter: + values["count"] = metric.Count() + case Gauge: + values["value"] = metric.Value() + case GaugeFloat64: + values["value"] = metric.Value() + case Healthcheck: + values["error"] = nil + metric.Check() + if err := metric.Error(); nil != err { + values["error"] = metric.Error().Error() + } + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = h.Count() + values["min"] = h.Min() + values["max"] = h.Max() + values["mean"] = h.Mean() + values["stddev"] = h.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + case Meter: + m := metric.Snapshot() + values["count"] = m.Count() + values["1m.rate"] = m.Rate1() + values["5m.rate"] = m.Rate5() + values["15m.rate"] = m.Rate15() + values["mean.rate"] = m.RateMean() + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = t.Count() + values["min"] = t.Min() + values["max"] = t.Max() + values["mean"] = t.Mean() + values["stddev"] = t.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + values["1m.rate"] = t.Rate1() + values["5m.rate"] = t.Rate5() + values["15m.rate"] = t.Rate15() + values["mean.rate"] = t.RateMean() + } + data[name] = values + }) + return data +} + // Unregister the metric with the given name. func (r *StandardRegistry) Unregister(name string) { r.mutex.Lock() defer r.mutex.Unlock() + r.stop(name) delete(r.metrics, name) } @@ -120,6 +197,7 @@ func (r *StandardRegistry) UnregisterAll() { r.mutex.Lock() defer r.mutex.Unlock() for name, _ := range r.metrics { + r.stop(name) delete(r.metrics, name) } } @@ -135,16 +213,37 @@ func (r *StandardRegistry) register(name string, i interface{}) error { return nil } -func (r *StandardRegistry) registered() map[string]interface{} { - r.mutex.Lock() - defer r.mutex.Unlock() - metrics := make(map[string]interface{}, len(r.metrics)) +type metricKV struct { + name string + value interface{} +} + +func (r *StandardRegistry) registered() []metricKV { + r.mutex.RLock() + defer r.mutex.RUnlock() + metrics := make([]metricKV, 0, len(r.metrics)) for name, i := range r.metrics { - metrics[name] = i + metrics = append(metrics, metricKV{ + name: name, + value: i, + }) } return metrics } +func (r *StandardRegistry) stop(name string) { + if i, ok := r.metrics[name]; ok { + if s, ok := i.(Stoppable); ok { + s.Stop() + } + } +} + +// Stoppable defines the metrics which has to be stopped. +type Stoppable interface { + Stop() +} + type PrefixedRegistry struct { underlying Registry prefix string @@ -166,12 +265,34 @@ func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { // Call the given function for each registered metric. func (r *PrefixedRegistry) Each(fn func(string, interface{})) { - r.underlying.Each(fn) + wrappedFn := func(prefix string) func(string, interface{}) { + return func(name string, iface interface{}) { + if strings.HasPrefix(name, prefix) { + fn(name, iface) + } else { + return + } + } + } + + baseRegistry, prefix := findPrefix(r, "") + baseRegistry.Each(wrappedFn(prefix)) +} + +func findPrefix(registry Registry, prefix string) (Registry, string) { + switch r := registry.(type) { + case *PrefixedRegistry: + return findPrefix(r.underlying, r.prefix+prefix) + case *StandardRegistry: + return r, prefix + } + return nil, "" } // Get the metric by the given name or nil if none is registered. func (r *PrefixedRegistry) Get(name string) interface{} { - return r.underlying.Get(name) + realName := r.prefix + name + return r.underlying.Get(realName) } // Gets an existing metric or registers the given one. @@ -193,6 +314,11 @@ func (r *PrefixedRegistry) RunHealthchecks() { r.underlying.RunHealthchecks() } +// GetAll metrics in the Registry +func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} { + return r.underlying.GetAll() +} + // Unregister the metric with the given name. The name will be prefixed. func (r *PrefixedRegistry) Unregister(name string) { realName := r.prefix + name diff --git a/vendor/github.com/rcrowley/go-metrics/runtime.go b/vendor/github.com/rcrowley/go-metrics/runtime.go index 11c6b785a..4047ab3d3 100644 --- a/vendor/github.com/rcrowley/go-metrics/runtime.go +++ b/vendor/github.com/rcrowley/go-metrics/runtime.go @@ -3,6 +3,7 @@ package metrics import ( "runtime" "runtime/pprof" + "sync" "time" ) @@ -49,7 +50,8 @@ var ( numGC uint32 numCgoCalls int64 - threadCreateProfile = pprof.Lookup("threadcreate") + threadCreateProfile = pprof.Lookup("threadcreate") + registerRuntimeMetricsOnce = sync.Once{} ) // Capture new values for the Go runtime statistics exported in @@ -146,67 +148,69 @@ func CaptureRuntimeMemStatsOnce(r Registry) { // specifically runtime.MemStats. The runtimeMetrics are named by their // fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. func RegisterRuntimeMemStats(r Registry) { - runtimeMetrics.MemStats.Alloc = NewGauge() - runtimeMetrics.MemStats.BuckHashSys = NewGauge() - runtimeMetrics.MemStats.DebugGC = NewGauge() - runtimeMetrics.MemStats.EnableGC = NewGauge() - runtimeMetrics.MemStats.Frees = NewGauge() - runtimeMetrics.MemStats.HeapAlloc = NewGauge() - runtimeMetrics.MemStats.HeapIdle = NewGauge() - runtimeMetrics.MemStats.HeapInuse = NewGauge() - runtimeMetrics.MemStats.HeapObjects = NewGauge() - runtimeMetrics.MemStats.HeapReleased = NewGauge() - runtimeMetrics.MemStats.HeapSys = NewGauge() - runtimeMetrics.MemStats.LastGC = NewGauge() - runtimeMetrics.MemStats.Lookups = NewGauge() - runtimeMetrics.MemStats.Mallocs = NewGauge() - runtimeMetrics.MemStats.MCacheInuse = NewGauge() - runtimeMetrics.MemStats.MCacheSys = NewGauge() - runtimeMetrics.MemStats.MSpanInuse = NewGauge() - runtimeMetrics.MemStats.MSpanSys = NewGauge() - runtimeMetrics.MemStats.NextGC = NewGauge() - runtimeMetrics.MemStats.NumGC = NewGauge() - runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() - runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) - runtimeMetrics.MemStats.PauseTotalNs = NewGauge() - runtimeMetrics.MemStats.StackInuse = NewGauge() - runtimeMetrics.MemStats.StackSys = NewGauge() - runtimeMetrics.MemStats.Sys = NewGauge() - runtimeMetrics.MemStats.TotalAlloc = NewGauge() - runtimeMetrics.NumCgoCall = NewGauge() - runtimeMetrics.NumGoroutine = NewGauge() - runtimeMetrics.NumThread = NewGauge() - runtimeMetrics.ReadMemStats = NewTimer() + registerRuntimeMetricsOnce.Do(func() { + runtimeMetrics.MemStats.Alloc = NewGauge() + runtimeMetrics.MemStats.BuckHashSys = NewGauge() + runtimeMetrics.MemStats.DebugGC = NewGauge() + runtimeMetrics.MemStats.EnableGC = NewGauge() + runtimeMetrics.MemStats.Frees = NewGauge() + runtimeMetrics.MemStats.HeapAlloc = NewGauge() + runtimeMetrics.MemStats.HeapIdle = NewGauge() + runtimeMetrics.MemStats.HeapInuse = NewGauge() + runtimeMetrics.MemStats.HeapObjects = NewGauge() + runtimeMetrics.MemStats.HeapReleased = NewGauge() + runtimeMetrics.MemStats.HeapSys = NewGauge() + runtimeMetrics.MemStats.LastGC = NewGauge() + runtimeMetrics.MemStats.Lookups = NewGauge() + runtimeMetrics.MemStats.Mallocs = NewGauge() + runtimeMetrics.MemStats.MCacheInuse = NewGauge() + runtimeMetrics.MemStats.MCacheSys = NewGauge() + runtimeMetrics.MemStats.MSpanInuse = NewGauge() + runtimeMetrics.MemStats.MSpanSys = NewGauge() + runtimeMetrics.MemStats.NextGC = NewGauge() + runtimeMetrics.MemStats.NumGC = NewGauge() + runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() + runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) + runtimeMetrics.MemStats.PauseTotalNs = NewGauge() + runtimeMetrics.MemStats.StackInuse = NewGauge() + runtimeMetrics.MemStats.StackSys = NewGauge() + runtimeMetrics.MemStats.Sys = NewGauge() + runtimeMetrics.MemStats.TotalAlloc = NewGauge() + runtimeMetrics.NumCgoCall = NewGauge() + runtimeMetrics.NumGoroutine = NewGauge() + runtimeMetrics.NumThread = NewGauge() + runtimeMetrics.ReadMemStats = NewTimer() - r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) - r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) - r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) - r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) - r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) - r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) - r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) - r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) - r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) - r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) - r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) - r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) - r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) - r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) - r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) - r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) - r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) - r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) - r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) - r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) - r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) - r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) - r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) - r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) - r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) - r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) - r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) - r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) - r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) - r.Register("runtime.NumThread", runtimeMetrics.NumThread) - r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) + r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) + r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) + r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) + r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) + r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) + r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) + r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) + r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) + r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) + r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) + r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) + r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) + r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) + r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) + r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) + r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) + r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) + r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) + r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) + r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) + r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) + r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) + r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) + r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) + r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) + r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) + r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) + r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) + r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) + r.Register("runtime.NumThread", runtimeMetrics.NumThread) + r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) + }) } diff --git a/vendor/github.com/rcrowley/go-metrics/sample.go b/vendor/github.com/rcrowley/go-metrics/sample.go index 5f6a37788..fecee5ef6 100644 --- a/vendor/github.com/rcrowley/go-metrics/sample.go +++ b/vendor/github.com/rcrowley/go-metrics/sample.go @@ -33,7 +33,7 @@ type Sample interface { // priority reservoir. See Cormode et al's "Forward Decay: A Practical Time // Decay Model for Streaming Systems". // -// +// type ExpDecaySample struct { alpha float64 count int64 @@ -302,6 +302,13 @@ type SampleSnapshot struct { values []int64 } +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + // Clear panics. func (*SampleSnapshot) Clear() { panic("Clear called on a SampleSnapshot") diff --git a/vendor/github.com/rcrowley/go-metrics/timer.go b/vendor/github.com/rcrowley/go-metrics/timer.go index 17db8f8d2..d6ec4c626 100644 --- a/vendor/github.com/rcrowley/go-metrics/timer.go +++ b/vendor/github.com/rcrowley/go-metrics/timer.go @@ -19,6 +19,7 @@ type Timer interface { RateMean() float64 Snapshot() Timer StdDev() float64 + Stop() Sum() int64 Time(func()) Update(time.Duration) @@ -28,6 +29,8 @@ type Timer interface { // GetOrRegisterTimer returns an existing Timer or constructs and registers a // new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func GetOrRegisterTimer(name string, r Registry) Timer { if nil == r { r = DefaultRegistry @@ -36,6 +39,7 @@ func GetOrRegisterTimer(name string, r Registry) Timer { } // NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. func NewCustomTimer(h Histogram, m Meter) Timer { if UseNilMetrics { return NilTimer{} @@ -47,6 +51,8 @@ func NewCustomTimer(h Histogram, m Meter) Timer { } // NewRegisteredTimer constructs and registers a new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func NewRegisteredTimer(name string, r Registry) Timer { c := NewTimer() if nil == r { @@ -58,6 +64,7 @@ func NewRegisteredTimer(name string, r Registry) Timer { // NewTimer constructs a new StandardTimer using an exponentially-decaying // sample with the same reservoir size and alpha as UNIX load averages. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. func NewTimer() Timer { if UseNilMetrics { return NilTimer{} @@ -112,6 +119,9 @@ func (NilTimer) Snapshot() Timer { return NilTimer{} } // StdDev is a no-op. func (NilTimer) StdDev() float64 { return 0.0 } +// Stop is a no-op. +func (NilTimer) Stop() {} + // Sum is a no-op. func (NilTimer) Sum() int64 { return 0 } @@ -201,6 +211,11 @@ func (t *StandardTimer) StdDev() float64 { return t.histogram.StdDev() } +// Stop stops the meter. +func (t *StandardTimer) Stop() { + t.meter.Stop() +} + // Sum returns the sum in the sample. func (t *StandardTimer) Sum() int64 { return t.histogram.Sum() @@ -288,6 +303,9 @@ func (t *TimerSnapshot) Snapshot() Timer { return t } // was taken. func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } +// Stop is a no-op. +func (t *TimerSnapshot) Stop() {} + // Sum returns the sum at the time the snapshot was taken. func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } diff --git a/vendor/github.com/rcrowley/go-metrics/validate.sh b/vendor/github.com/rcrowley/go-metrics/validate.sh index f6499982e..c4ae91e64 100644 --- a/vendor/github.com/rcrowley/go-metrics/validate.sh +++ b/vendor/github.com/rcrowley/go-metrics/validate.sh @@ -7,4 +7,4 @@ GOFMT_LINES=`gofmt -l . | wc -l | xargs` test $GOFMT_LINES -eq 0 || echo "gofmt needs to be run, ${GOFMT_LINES} files have issues" # run the tests for the root package -go test . +go test -race . diff --git a/vendor/github.com/robertkrimen/otto/.gitignore b/vendor/github.com/robertkrimen/otto/.gitignore index 8c2a16949..ea050b8b9 100644 --- a/vendor/github.com/robertkrimen/otto/.gitignore +++ b/vendor/github.com/robertkrimen/otto/.gitignore @@ -1,5 +1,10 @@ -/.test -/otto/otto -/otto/otto-* -/test/test-*.js -/test/tester +.test +otto/otto +otto/otto-* +tools/tester/testdata/ +tools/tester/tester +tools/gen-jscore/gen-jscore +tools/gen-tokens/gen-tokens +.idea +dist/ +.vscode/ diff --git a/vendor/github.com/robertkrimen/otto/Makefile b/vendor/github.com/robertkrimen/otto/Makefile deleted file mode 100644 index 9868db3ca..000000000 --- a/vendor/github.com/robertkrimen/otto/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -.PHONY: test test-race test-release release release-check test-262 -.PHONY: parser -.PHONY: otto assets underscore - -TESTS := \ - ~ - -TEST := -v --run -TEST := -v -TEST := -v --run Test\($(subst $(eval) ,\|,$(TESTS))\) -TEST := . - -test: parser inline.go - go test -i - go test $(TEST) - @echo PASS - -parser: - $(MAKE) -C parser - -inline.go: inline.pl - ./$< > $@ - -################# -# release, test # -################# - -release: test-race test-release - for package in . parser token ast file underscore registry; do (cd $$package && godocdown --signature > README.markdown); done - @echo \*\*\* make release-check - @echo PASS - -release-check: .test - $(MAKE) -C test build test - $(MAKE) -C .test/test262 build test - @echo PASS - -test-262: .test - $(MAKE) -C .test/test262 build test - @echo PASS - -test-release: - go test -i - go test - -test-race: - go test -race -i - go test -race - -################################# -# otto, assets, underscore, ... # -################################# - -otto: - $(MAKE) -C otto - -assets: - mkdir -p .assets - for file in underscore/test/*.js; do tr "\`" "_" < $$file > .assets/`basename $$file`; done - -underscore: - $(MAKE) -C $@ - diff --git a/vendor/github.com/robertkrimen/otto/README.markdown b/vendor/github.com/robertkrimen/otto/README.markdown deleted file mode 100644 index 40584d32b..000000000 --- a/vendor/github.com/robertkrimen/otto/README.markdown +++ /dev/null @@ -1,871 +0,0 @@ -# otto --- -```go -import "github.com/robertkrimen/otto" -``` - -Package otto is a JavaScript parser and interpreter written natively in Go. - -http://godoc.org/github.com/robertkrimen/otto - -```go -import ( - "github.com/robertkrimen/otto" -) -``` - -Run something in the VM - -```go -vm := otto.New() -vm.Run(` - abc = 2 + 2; - console.log("The value of abc is " + abc); // 4 -`) -``` - -Get a value out of the VM - -```go -if value, err := vm.Get("abc"); err == nil { - if value_int, err := value.ToInteger(); err == nil { - fmt.Printf("", value_int, err) - } -} -``` - -Set a number - -```go -vm.Set("def", 11) -vm.Run(` - console.log("The value of def is " + def); - // The value of def is 11 -`) -``` - -Set a string - -```go -vm.Set("xyzzy", "Nothing happens.") -vm.Run(` - console.log(xyzzy.length); // 16 -`) -``` - -Get the value of an expression - -```go -value, _ = vm.Run("xyzzy.length") -{ - // value is an int64 with a value of 16 - value, _ := value.ToInteger() -} -``` - -An error happens - -```go -value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") -if err != nil { - // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined - // If there is an error, then value.IsUndefined() is true - ... -} -``` - -Set a Go function - -```go -vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { - fmt.Printf("Hello, %s.\n", call.Argument(0).String()) - return otto.Value{} -}) -``` - -Set a Go function that returns something useful - -```go -vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { - right, _ := call.Argument(0).ToInteger() - result, _ := vm.ToValue(2 + right) - return result -}) -``` - -Use the functions in JavaScript - -```go -result, _ = vm.Run(` - sayHello("Xyzzy"); // Hello, Xyzzy. - sayHello(); // Hello, undefined - - result = twoPlus(2.0); // 4 -`) -``` - -### Parser - -A separate parser is available in the parser package if you're just interested -in building an AST. - -http://godoc.org/github.com/robertkrimen/otto/parser - -Parse and return an AST - -```go -filename := "" // A filename is optional -src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } - - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); -` - -// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList -program, err := parser.ParseFile(nil, filename, src, 0) -``` - -### otto - -You can run (Go) JavaScript from the commandline with: -http://github.com/robertkrimen/otto/tree/master/otto - - $ go get -v github.com/robertkrimen/otto/otto - -Run JavaScript by entering some source on stdin or by giving otto a filename: - - $ otto example.js - -### underscore - -Optionally include the JavaScript utility-belt library, underscore, with this -import: - -```go -import ( - "github.com/robertkrimen/otto" - _ "github.com/robertkrimen/otto/underscore" -) - -// Now every otto runtime will come loaded with underscore -``` - -For more information: http://github.com/robertkrimen/otto/tree/master/underscore - - -### Caveat Emptor - -The following are some limitations with otto: - - * "use strict" will parse, but does nothing. - * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. - * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. - - -### Regular Expression Incompatibility - -Go translates JavaScript-style regular expressions into something that is -"regexp" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires -backtracking for some patterns, and backtracking is not supported by the -standard Go engine: https://code.google.com/p/re2/wiki/Syntax - -Therefore, the following syntax is incompatible: - - (?=) // Lookahead (positive), currently a parsing error - (?!) // Lookahead (backhead), currently a parsing error - \1 // Backreference (\1, \2, \3, ...), currently a parsing error - -A brief discussion of these limitations: "Regexp (?!re)" -https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E - -More information about re2: https://code.google.com/p/re2/ - -In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r -]. The JavaScript definition, on the other hand, also includes \v, Unicode -"Separator, Space", etc. - - -### Halting Problem - -If you want to stop long running executions (like third-party code), you can use -the interrupt channel to do this: - -```go -package main - -import ( - "errors" - "fmt" - "os" - "time" - - "github.com/robertkrimen/otto" -) - -var halt = errors.New("Stahp") - -func main() { - runUnsafe(`var abc = [];`) - runUnsafe(` - while (true) { - // Loop forever - }`) -} - -func runUnsafe(unsafe string) { - start := time.Now() - defer func() { - duration := time.Since(start) - if caught := recover(); caught != nil { - if caught == halt { - fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration) - return - } - panic(caught) // Something else happened, repanic! - } - fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) - }() - - vm := otto.New() - vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking - - go func() { - time.Sleep(2 * time.Second) // Stop after two seconds - vm.Interrupt <- func() { - panic(halt) - } - }() - - vm.Run(unsafe) // Here be dragons (risky code) -} -``` - -Where is setTimeout/setInterval? - -These timing functions are not actually part of the ECMA-262 specification. -Typically, they belong to the `window` object (in the browser). It would not be -difficult to provide something like these via Go, but you probably want to wrap -otto in an event loop in that case. - -For an example of how this could be done in Go with otto, see natto: - -http://github.com/robertkrimen/natto - -Here is some more discussion of the issue: - -* http://book.mixu.net/node/ch2.html - -* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 - -* http://aaroncrane.co.uk/2009/02/perl_safe_signals/ - -## Usage - -```go -var ErrVersion = errors.New("version mismatch") -``` - -#### type Error - -```go -type Error struct { -} -``` - -An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. - -#### func (Error) Error - -```go -func (err Error) Error() string -``` -Error returns a description of the error - - TypeError: 'def' is not a function - -#### func (Error) String - -```go -func (err Error) String() string -``` -String returns a description of the error and a trace of where the error -occurred. - - TypeError: 'def' is not a function - at xyz (:3:9) - at :7:1/ - -#### type FunctionCall - -```go -type FunctionCall struct { - This Value - ArgumentList []Value - Otto *Otto -} -``` - -FunctionCall is an encapsulation of a JavaScript function call. - -#### func (FunctionCall) Argument - -```go -func (self FunctionCall) Argument(index int) Value -``` -Argument will return the value of the argument at the given index. - -If no such argument exists, undefined is returned. - -#### type Object - -```go -type Object struct { -} -``` - -Object is the representation of a JavaScript object. - -#### func (Object) Call - -```go -func (self Object) Call(name string, argumentList ...interface{}) (Value, error) -``` -Call a method on the object. - -It is essentially equivalent to: - - var method, _ := object.Get(name) - method.Call(object, argumentList...) - -An undefined value and an error will result if: - - 1. There is an error during conversion of the argument list - 2. The property is not actually a function - 3. An (uncaught) exception is thrown - -#### func (Object) Class - -```go -func (self Object) Class() string -``` -Class will return the class string of the object. - -The return value will (generally) be one of: - - Object - Function - Array - String - Number - Boolean - Date - RegExp - -#### func (Object) Get - -```go -func (self Object) Get(name string) (Value, error) -``` -Get the value of the property with the given name. - -#### func (Object) Keys - -```go -func (self Object) Keys() []string -``` -Get the keys for the object - -Equivalent to calling Object.keys on the object - -#### func (Object) Set - -```go -func (self Object) Set(name string, value interface{}) error -``` -Set the property of the given name to the given value. - -An error will result if the setting the property triggers an exception (i.e. -read-only), or there is an error during conversion of the given value. - -#### func (Object) Value - -```go -func (self Object) Value() Value -``` -Value will return self as a value. - -#### type Otto - -```go -type Otto struct { - // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. - // See "Halting Problem" for more information. - Interrupt chan func() -} -``` - -Otto is the representation of the JavaScript runtime. Each instance of Otto has -a self-contained namespace. - -#### func New - -```go -func New() *Otto -``` -New will allocate a new JavaScript runtime - -#### func Run - -```go -func Run(src interface{}) (*Otto, Value, error) -``` -Run will allocate a new JavaScript runtime, run the given source on the -allocated runtime, and return the runtime, resulting value, and error (if any). - -src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST -always be in UTF-8. - -src may also be a Script. - -src may also be a Program, but if the AST has been modified, then runtime -behavior is undefined. - -#### func (Otto) Call - -```go -func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) -``` -Call the given JavaScript with a given this and arguments. - -If this is nil, then some special handling takes place to determine the proper -this value, falling back to a "standard" invocation if necessary (where this is -undefined). - -If source begins with "new " (A lowercase new followed by a space), then Call -will invoke the function constructor rather than performing a function call. In -this case, the this argument has no effect. - -```go -// value is a String object -value, _ := vm.Call("Object", nil, "Hello, World.") - -// Likewise... -value, _ := vm.Call("new Object", nil, "Hello, World.") - -// This will perform a concat on the given array and return the result -// value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] -value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") -``` - -#### func (*Otto) Compile - -```go -func (self *Otto) Compile(filename string, src interface{}) (*Script, error) -``` -Compile will parse the given source and return a Script value or nil and an -error if there was a problem during compilation. - -```go -script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) -vm.Run(script) -``` - -#### func (*Otto) Copy - -```go -func (in *Otto) Copy() *Otto -``` -Copy will create a copy/clone of the runtime. - -Copy is useful for saving some time when creating many similar runtimes. - -This method works by walking the original runtime and cloning each object, -scope, stash, etc. into a new runtime. - -Be on the lookout for memory leaks or inadvertent sharing of resources. - -#### func (Otto) Get - -```go -func (self Otto) Get(name string) (Value, error) -``` -Get the value of the top-level binding of the given name. - -If there is an error (like the binding does not exist), then the value will be -undefined. - -#### func (Otto) Object - -```go -func (self Otto) Object(source string) (*Object, error) -``` -Object will run the given source and return the result as an object. - -For example, accessing an existing object: - -```go -object, _ := vm.Object(`Number`) -``` - -Or, creating a new object: - -```go -object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`) -``` - -Or, creating and assigning an object: - -```go -object, _ := vm.Object(`xyzzy = {}`) -object.Set("volume", 11) -``` - -If there is an error (like the source does not result in an object), then nil -and an error is returned. - -#### func (Otto) Run - -```go -func (self Otto) Run(src interface{}) (Value, error) -``` -Run will run the given source (parsing it first if necessary), returning the -resulting value and error (if any) - -src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST -always be in UTF-8. - -If the runtime is unable to parse source, then this function will return -undefined and the parse error (nothing will be evaluated in this case). - -src may also be a Script. - -src may also be a Program, but if the AST has been modified, then runtime -behavior is undefined. - -#### func (Otto) Set - -```go -func (self Otto) Set(name string, value interface{}) error -``` -Set the top-level binding of the given name to the given value. - -Set will automatically apply ToValue to the given value in order to convert it -to a JavaScript value (type Value). - -If there is an error (like the binding is read-only, or the ToValue conversion -fails), then an error is returned. - -If the top-level binding does not exist, it will be created. - -#### func (Otto) ToValue - -```go -func (self Otto) ToValue(value interface{}) (Value, error) -``` -ToValue will convert an interface{} value to a value digestible by -otto/JavaScript. - -#### type Script - -```go -type Script struct { -} -``` - -Script is a handle for some (reusable) JavaScript. Passing a Script value to a -run method will evaluate the JavaScript. - -#### func (*Script) String - -```go -func (self *Script) String() string -``` - -#### type Value - -```go -type Value struct { -} -``` - -Value is the representation of a JavaScript value. - -#### func FalseValue - -```go -func FalseValue() Value -``` -FalseValue will return a value representing false. - -It is equivalent to: - -```go -ToValue(false) -``` - -#### func NaNValue - -```go -func NaNValue() Value -``` -NaNValue will return a value representing NaN. - -It is equivalent to: - -```go -ToValue(math.NaN()) -``` - -#### func NullValue - -```go -func NullValue() Value -``` -NullValue will return a Value representing null. - -#### func ToValue - -```go -func ToValue(value interface{}) (Value, error) -``` -ToValue will convert an interface{} value to a value digestible by -otto/JavaScript - -This function will not work for advanced types (struct, map, slice/array, etc.) -and you should use Otto.ToValue instead. - -#### func TrueValue - -```go -func TrueValue() Value -``` -TrueValue will return a value representing true. - -It is equivalent to: - -```go -ToValue(true) -``` - -#### func UndefinedValue - -```go -func UndefinedValue() Value -``` -UndefinedValue will return a Value representing undefined. - -#### func (Value) Call - -```go -func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) -``` -Call the value as a function with the given this value and argument list and -return the result of invocation. It is essentially equivalent to: - - value.apply(thisValue, argumentList) - -An undefined value and an error will result if: - - 1. There is an error during conversion of the argument list - 2. The value is not actually a function - 3. An (uncaught) exception is thrown - -#### func (Value) Class - -```go -func (value Value) Class() string -``` -Class will return the class string of the value or the empty string if value is -not an object. - -The return value will (generally) be one of: - - Object - Function - Array - String - Number - Boolean - Date - RegExp - -#### func (Value) Export - -```go -func (self Value) Export() (interface{}, error) -``` -Export will attempt to convert the value to a Go representation and return it -via an interface{} kind. - -Export returns an error, but it will always be nil. It is present for backwards -compatibility. - -If a reasonable conversion is not possible, then the original value is returned. - - undefined -> nil (FIXME?: Should be Value{}) - null -> nil - boolean -> bool - number -> A number type (int, float32, uint64, ...) - string -> string - Array -> []interface{} - Object -> map[string]interface{} - -#### func (Value) IsBoolean - -```go -func (value Value) IsBoolean() bool -``` -IsBoolean will return true if value is a boolean (primitive). - -#### func (Value) IsDefined - -```go -func (value Value) IsDefined() bool -``` -IsDefined will return false if the value is undefined, and true otherwise. - -#### func (Value) IsFunction - -```go -func (value Value) IsFunction() bool -``` -IsFunction will return true if value is a function. - -#### func (Value) IsNaN - -```go -func (value Value) IsNaN() bool -``` -IsNaN will return true if value is NaN (or would convert to NaN). - -#### func (Value) IsNull - -```go -func (value Value) IsNull() bool -``` -IsNull will return true if the value is null, and false otherwise. - -#### func (Value) IsNumber - -```go -func (value Value) IsNumber() bool -``` -IsNumber will return true if value is a number (primitive). - -#### func (Value) IsObject - -```go -func (value Value) IsObject() bool -``` -IsObject will return true if value is an object. - -#### func (Value) IsPrimitive - -```go -func (value Value) IsPrimitive() bool -``` -IsPrimitive will return true if value is a primitive (any kind of primitive). - -#### func (Value) IsString - -```go -func (value Value) IsString() bool -``` -IsString will return true if value is a string (primitive). - -#### func (Value) IsUndefined - -```go -func (value Value) IsUndefined() bool -``` -IsUndefined will return true if the value is undefined, and false otherwise. - -#### func (Value) Object - -```go -func (value Value) Object() *Object -``` -Object will return the object of the value, or nil if value is not an object. - -This method will not do any implicit conversion. For example, calling this -method on a string primitive value will not return a String object. - -#### func (Value) String - -```go -func (value Value) String() string -``` -String will return the value as a string. - -This method will make return the empty string if there is an error. - -#### func (Value) ToBoolean - -```go -func (value Value) ToBoolean() (bool, error) -``` -ToBoolean will convert the value to a boolean (bool). - - ToValue(0).ToBoolean() => false - ToValue("").ToBoolean() => false - ToValue(true).ToBoolean() => true - ToValue(1).ToBoolean() => true - ToValue("Nothing happens").ToBoolean() => true - -If there is an error during the conversion process (like an uncaught exception), -then the result will be false and an error. - -#### func (Value) ToFloat - -```go -func (value Value) ToFloat() (float64, error) -``` -ToFloat will convert the value to a number (float64). - - ToValue(0).ToFloat() => 0. - ToValue(1.1).ToFloat() => 1.1 - ToValue("11").ToFloat() => 11. - -If there is an error during the conversion process (like an uncaught exception), -then the result will be 0 and an error. - -#### func (Value) ToInteger - -```go -func (value Value) ToInteger() (int64, error) -``` -ToInteger will convert the value to a number (int64). - - ToValue(0).ToInteger() => 0 - ToValue(1.1).ToInteger() => 1 - ToValue("11").ToInteger() => 11 - -If there is an error during the conversion process (like an uncaught exception), -then the result will be 0 and an error. - -#### func (Value) ToString - -```go -func (value Value) ToString() (string, error) -``` -ToString will convert the value to a string (string). - - ToValue(0).ToString() => "0" - ToValue(false).ToString() => "false" - ToValue(1.1).ToString() => "1.1" - ToValue("11").ToString() => "11" - ToValue('Nothing happens.').ToString() => "Nothing happens." - -If there is an error during the conversion process (like an uncaught exception), -then the result will be the empty string ("") and an error. - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/ast/README.markdown b/vendor/github.com/robertkrimen/otto/ast/README.markdown deleted file mode 100644 index a785da911..000000000 --- a/vendor/github.com/robertkrimen/otto/ast/README.markdown +++ /dev/null @@ -1,1068 +0,0 @@ -# ast --- - import "github.com/robertkrimen/otto/ast" - -Package ast declares types representing a JavaScript AST. - - -### Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -## Usage - -#### type ArrayLiteral - -```go -type ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression -} -``` - - -#### func (*ArrayLiteral) Idx0 - -```go -func (self *ArrayLiteral) Idx0() file.Idx -``` - -#### func (*ArrayLiteral) Idx1 - -```go -func (self *ArrayLiteral) Idx1() file.Idx -``` - -#### type AssignExpression - -```go -type AssignExpression struct { - Operator token.Token - Left Expression - Right Expression -} -``` - - -#### func (*AssignExpression) Idx0 - -```go -func (self *AssignExpression) Idx0() file.Idx -``` - -#### func (*AssignExpression) Idx1 - -```go -func (self *AssignExpression) Idx1() file.Idx -``` - -#### type BadExpression - -```go -type BadExpression struct { - From file.Idx - To file.Idx -} -``` - - -#### func (*BadExpression) Idx0 - -```go -func (self *BadExpression) Idx0() file.Idx -``` - -#### func (*BadExpression) Idx1 - -```go -func (self *BadExpression) Idx1() file.Idx -``` - -#### type BadStatement - -```go -type BadStatement struct { - From file.Idx - To file.Idx -} -``` - - -#### func (*BadStatement) Idx0 - -```go -func (self *BadStatement) Idx0() file.Idx -``` - -#### func (*BadStatement) Idx1 - -```go -func (self *BadStatement) Idx1() file.Idx -``` - -#### type BinaryExpression - -```go -type BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool -} -``` - - -#### func (*BinaryExpression) Idx0 - -```go -func (self *BinaryExpression) Idx0() file.Idx -``` - -#### func (*BinaryExpression) Idx1 - -```go -func (self *BinaryExpression) Idx1() file.Idx -``` - -#### type BlockStatement - -```go -type BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx -} -``` - - -#### func (*BlockStatement) Idx0 - -```go -func (self *BlockStatement) Idx0() file.Idx -``` - -#### func (*BlockStatement) Idx1 - -```go -func (self *BlockStatement) Idx1() file.Idx -``` - -#### type BooleanLiteral - -```go -type BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool -} -``` - - -#### func (*BooleanLiteral) Idx0 - -```go -func (self *BooleanLiteral) Idx0() file.Idx -``` - -#### func (*BooleanLiteral) Idx1 - -```go -func (self *BooleanLiteral) Idx1() file.Idx -``` - -#### type BracketExpression - -```go -type BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx -} -``` - - -#### func (*BracketExpression) Idx0 - -```go -func (self *BracketExpression) Idx0() file.Idx -``` - -#### func (*BracketExpression) Idx1 - -```go -func (self *BracketExpression) Idx1() file.Idx -``` - -#### type BranchStatement - -```go -type BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier -} -``` - - -#### func (*BranchStatement) Idx0 - -```go -func (self *BranchStatement) Idx0() file.Idx -``` - -#### func (*BranchStatement) Idx1 - -```go -func (self *BranchStatement) Idx1() file.Idx -``` - -#### type CallExpression - -```go -type CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx -} -``` - - -#### func (*CallExpression) Idx0 - -```go -func (self *CallExpression) Idx0() file.Idx -``` - -#### func (*CallExpression) Idx1 - -```go -func (self *CallExpression) Idx1() file.Idx -``` - -#### type CaseStatement - -```go -type CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement -} -``` - - -#### func (*CaseStatement) Idx0 - -```go -func (self *CaseStatement) Idx0() file.Idx -``` - -#### func (*CaseStatement) Idx1 - -```go -func (self *CaseStatement) Idx1() file.Idx -``` - -#### type CatchStatement - -```go -type CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement -} -``` - - -#### func (*CatchStatement) Idx0 - -```go -func (self *CatchStatement) Idx0() file.Idx -``` - -#### func (*CatchStatement) Idx1 - -```go -func (self *CatchStatement) Idx1() file.Idx -``` - -#### type ConditionalExpression - -```go -type ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression -} -``` - - -#### func (*ConditionalExpression) Idx0 - -```go -func (self *ConditionalExpression) Idx0() file.Idx -``` - -#### func (*ConditionalExpression) Idx1 - -```go -func (self *ConditionalExpression) Idx1() file.Idx -``` - -#### type DebuggerStatement - -```go -type DebuggerStatement struct { - Debugger file.Idx -} -``` - - -#### func (*DebuggerStatement) Idx0 - -```go -func (self *DebuggerStatement) Idx0() file.Idx -``` - -#### func (*DebuggerStatement) Idx1 - -```go -func (self *DebuggerStatement) Idx1() file.Idx -``` - -#### type Declaration - -```go -type Declaration interface { - // contains filtered or unexported methods -} -``` - -All declaration nodes implement the Declaration interface. - -#### type DoWhileStatement - -```go -type DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement -} -``` - - -#### func (*DoWhileStatement) Idx0 - -```go -func (self *DoWhileStatement) Idx0() file.Idx -``` - -#### func (*DoWhileStatement) Idx1 - -```go -func (self *DoWhileStatement) Idx1() file.Idx -``` - -#### type DotExpression - -```go -type DotExpression struct { - Left Expression - Identifier Identifier -} -``` - - -#### func (*DotExpression) Idx0 - -```go -func (self *DotExpression) Idx0() file.Idx -``` - -#### func (*DotExpression) Idx1 - -```go -func (self *DotExpression) Idx1() file.Idx -``` - -#### type EmptyStatement - -```go -type EmptyStatement struct { - Semicolon file.Idx -} -``` - - -#### func (*EmptyStatement) Idx0 - -```go -func (self *EmptyStatement) Idx0() file.Idx -``` - -#### func (*EmptyStatement) Idx1 - -```go -func (self *EmptyStatement) Idx1() file.Idx -``` - -#### type Expression - -```go -type Expression interface { - Node - // contains filtered or unexported methods -} -``` - -All expression nodes implement the Expression interface. - -#### type ExpressionStatement - -```go -type ExpressionStatement struct { - Expression Expression -} -``` - - -#### func (*ExpressionStatement) Idx0 - -```go -func (self *ExpressionStatement) Idx0() file.Idx -``` - -#### func (*ExpressionStatement) Idx1 - -```go -func (self *ExpressionStatement) Idx1() file.Idx -``` - -#### type ForInStatement - -```go -type ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement -} -``` - - -#### func (*ForInStatement) Idx0 - -```go -func (self *ForInStatement) Idx0() file.Idx -``` - -#### func (*ForInStatement) Idx1 - -```go -func (self *ForInStatement) Idx1() file.Idx -``` - -#### type ForStatement - -```go -type ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement -} -``` - - -#### func (*ForStatement) Idx0 - -```go -func (self *ForStatement) Idx0() file.Idx -``` - -#### func (*ForStatement) Idx1 - -```go -func (self *ForStatement) Idx1() file.Idx -``` - -#### type FunctionDeclaration - -```go -type FunctionDeclaration struct { - Function *FunctionLiteral -} -``` - - -#### type FunctionLiteral - -```go -type FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string - - DeclarationList []Declaration -} -``` - - -#### func (*FunctionLiteral) Idx0 - -```go -func (self *FunctionLiteral) Idx0() file.Idx -``` - -#### func (*FunctionLiteral) Idx1 - -```go -func (self *FunctionLiteral) Idx1() file.Idx -``` - -#### type Identifier - -```go -type Identifier struct { - Name string - Idx file.Idx -} -``` - - -#### func (*Identifier) Idx0 - -```go -func (self *Identifier) Idx0() file.Idx -``` - -#### func (*Identifier) Idx1 - -```go -func (self *Identifier) Idx1() file.Idx -``` - -#### type IfStatement - -```go -type IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement -} -``` - - -#### func (*IfStatement) Idx0 - -```go -func (self *IfStatement) Idx0() file.Idx -``` - -#### func (*IfStatement) Idx1 - -```go -func (self *IfStatement) Idx1() file.Idx -``` - -#### type LabelledStatement - -```go -type LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement -} -``` - - -#### func (*LabelledStatement) Idx0 - -```go -func (self *LabelledStatement) Idx0() file.Idx -``` - -#### func (*LabelledStatement) Idx1 - -```go -func (self *LabelledStatement) Idx1() file.Idx -``` - -#### type NewExpression - -```go -type NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx -} -``` - - -#### func (*NewExpression) Idx0 - -```go -func (self *NewExpression) Idx0() file.Idx -``` - -#### func (*NewExpression) Idx1 - -```go -func (self *NewExpression) Idx1() file.Idx -``` - -#### type Node - -```go -type Node interface { - Idx0() file.Idx // The index of the first character belonging to the node - Idx1() file.Idx // The index of the first character immediately after the node -} -``` - -All nodes implement the Node interface. - -#### type NullLiteral - -```go -type NullLiteral struct { - Idx file.Idx - Literal string -} -``` - - -#### func (*NullLiteral) Idx0 - -```go -func (self *NullLiteral) Idx0() file.Idx -``` - -#### func (*NullLiteral) Idx1 - -```go -func (self *NullLiteral) Idx1() file.Idx -``` - -#### type NumberLiteral - -```go -type NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} -} -``` - - -#### func (*NumberLiteral) Idx0 - -```go -func (self *NumberLiteral) Idx0() file.Idx -``` - -#### func (*NumberLiteral) Idx1 - -```go -func (self *NumberLiteral) Idx1() file.Idx -``` - -#### type ObjectLiteral - -```go -type ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property -} -``` - - -#### func (*ObjectLiteral) Idx0 - -```go -func (self *ObjectLiteral) Idx0() file.Idx -``` - -#### func (*ObjectLiteral) Idx1 - -```go -func (self *ObjectLiteral) Idx1() file.Idx -``` - -#### type ParameterList - -```go -type ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx -} -``` - - -#### type Program - -```go -type Program struct { - Body []Statement - - DeclarationList []Declaration - - File *file.File -} -``` - - -#### func (*Program) Idx0 - -```go -func (self *Program) Idx0() file.Idx -``` - -#### func (*Program) Idx1 - -```go -func (self *Program) Idx1() file.Idx -``` - -#### type Property - -```go -type Property struct { - Key string - Kind string - Value Expression -} -``` - - -#### type RegExpLiteral - -```go -type RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string -} -``` - - -#### func (*RegExpLiteral) Idx0 - -```go -func (self *RegExpLiteral) Idx0() file.Idx -``` - -#### func (*RegExpLiteral) Idx1 - -```go -func (self *RegExpLiteral) Idx1() file.Idx -``` - -#### type ReturnStatement - -```go -type ReturnStatement struct { - Return file.Idx - Argument Expression -} -``` - - -#### func (*ReturnStatement) Idx0 - -```go -func (self *ReturnStatement) Idx0() file.Idx -``` - -#### func (*ReturnStatement) Idx1 - -```go -func (self *ReturnStatement) Idx1() file.Idx -``` - -#### type SequenceExpression - -```go -type SequenceExpression struct { - Sequence []Expression -} -``` - - -#### func (*SequenceExpression) Idx0 - -```go -func (self *SequenceExpression) Idx0() file.Idx -``` - -#### func (*SequenceExpression) Idx1 - -```go -func (self *SequenceExpression) Idx1() file.Idx -``` - -#### type Statement - -```go -type Statement interface { - Node - // contains filtered or unexported methods -} -``` - -All statement nodes implement the Statement interface. - -#### type StringLiteral - -```go -type StringLiteral struct { - Idx file.Idx - Literal string - Value string -} -``` - - -#### func (*StringLiteral) Idx0 - -```go -func (self *StringLiteral) Idx0() file.Idx -``` - -#### func (*StringLiteral) Idx1 - -```go -func (self *StringLiteral) Idx1() file.Idx -``` - -#### type SwitchStatement - -```go -type SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement -} -``` - - -#### func (*SwitchStatement) Idx0 - -```go -func (self *SwitchStatement) Idx0() file.Idx -``` - -#### func (*SwitchStatement) Idx1 - -```go -func (self *SwitchStatement) Idx1() file.Idx -``` - -#### type ThisExpression - -```go -type ThisExpression struct { - Idx file.Idx -} -``` - - -#### func (*ThisExpression) Idx0 - -```go -func (self *ThisExpression) Idx0() file.Idx -``` - -#### func (*ThisExpression) Idx1 - -```go -func (self *ThisExpression) Idx1() file.Idx -``` - -#### type ThrowStatement - -```go -type ThrowStatement struct { - Throw file.Idx - Argument Expression -} -``` - - -#### func (*ThrowStatement) Idx0 - -```go -func (self *ThrowStatement) Idx0() file.Idx -``` - -#### func (*ThrowStatement) Idx1 - -```go -func (self *ThrowStatement) Idx1() file.Idx -``` - -#### type TryStatement - -```go -type TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement -} -``` - - -#### func (*TryStatement) Idx0 - -```go -func (self *TryStatement) Idx0() file.Idx -``` - -#### func (*TryStatement) Idx1 - -```go -func (self *TryStatement) Idx1() file.Idx -``` - -#### type UnaryExpression - -```go -type UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool -} -``` - - -#### func (*UnaryExpression) Idx0 - -```go -func (self *UnaryExpression) Idx0() file.Idx -``` - -#### func (*UnaryExpression) Idx1 - -```go -func (self *UnaryExpression) Idx1() file.Idx -``` - -#### type VariableDeclaration - -```go -type VariableDeclaration struct { - Var file.Idx - List []*VariableExpression -} -``` - - -#### type VariableExpression - -```go -type VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression -} -``` - - -#### func (*VariableExpression) Idx0 - -```go -func (self *VariableExpression) Idx0() file.Idx -``` - -#### func (*VariableExpression) Idx1 - -```go -func (self *VariableExpression) Idx1() file.Idx -``` - -#### type VariableStatement - -```go -type VariableStatement struct { - Var file.Idx - List []Expression -} -``` - - -#### func (*VariableStatement) Idx0 - -```go -func (self *VariableStatement) Idx0() file.Idx -``` - -#### func (*VariableStatement) Idx1 - -```go -func (self *VariableStatement) Idx1() file.Idx -``` - -#### type WhileStatement - -```go -type WhileStatement struct { - While file.Idx - Test Expression - Body Statement -} -``` - - -#### func (*WhileStatement) Idx0 - -```go -func (self *WhileStatement) Idx0() file.Idx -``` - -#### func (*WhileStatement) Idx1 - -```go -func (self *WhileStatement) Idx1() file.Idx -``` - -#### type WithStatement - -```go -type WithStatement struct { - With file.Idx - Object Expression - Body Statement -} -``` - - -#### func (*WithStatement) Idx0 - -```go -func (self *WithStatement) Idx0() file.Idx -``` - -#### func (*WithStatement) Idx1 - -```go -func (self *WithStatement) Idx1() file.Idx -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/ast/comments.go b/vendor/github.com/robertkrimen/otto/ast/comments.go index ef2cc3d89..81dc594eb 100644 --- a/vendor/github.com/robertkrimen/otto/ast/comments.go +++ b/vendor/github.com/robertkrimen/otto/ast/comments.go @@ -2,35 +2,48 @@ package ast import ( "fmt" + "github.com/robertkrimen/otto/file" ) -// CommentPosition determines where the comment is in a given context +// CommentPosition determines where the comment is in a given context. type CommentPosition int +// Available comment positions. const ( - _ CommentPosition = iota - LEADING // Before the pertinent expression - TRAILING // After the pertinent expression - KEY // Before a key in an object - COLON // After a colon in a field declaration - FINAL // Final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal - IF // After an if keyword - WHILE // After a while keyword - DO // After do keyword - FOR // After a for keyword - WITH // After a with keyword + _ CommentPosition = iota + // LEADING is before the pertinent expression. + LEADING + // TRAILING is after the pertinent expression. + TRAILING + // KEY is before a key in an object. + KEY + // COLON is after a colon in a field declaration. + COLON + // FINAL is the final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal. + FINAL + // IF is after an if keyword. + IF + // WHILE is after a while keyword. + WHILE + // DO is after do keyword. + DO + // FOR is after a for keyword. + FOR + // WITH is after a with keyword. + WITH + // TBD is unknown. TBD ) -// Comment contains the data of the comment +// Comment contains the data of the comment. type Comment struct { - Begin file.Idx Text string + Begin file.Idx Position CommentPosition } -// NewComment creates a new comment +// NewComment creates a new comment. func NewComment(text string, idx file.Idx) *Comment { comment := &Comment{ Begin: idx, @@ -41,7 +54,7 @@ func NewComment(text string, idx file.Idx) *Comment { return comment } -// String returns a stringified version of the position +// String returns a stringified version of the position. func (cp CommentPosition) String() string { switch cp { case LEADING: @@ -69,23 +82,23 @@ func (cp CommentPosition) String() string { } } -// String returns a stringified version of the comment +// String returns a stringified version of the comment. func (c Comment) String() string { return fmt.Sprintf("Comment: %v", c.Text) } -// Comments defines the current view of comments from the parser +// Comments defines the current view of comments from the parser. type Comments struct { // CommentMap is a reference to the parser comment map CommentMap CommentMap // Comments lists the comments scanned, not linked to a node yet Comments []*Comment - // future lists the comments after a line break during a sequence of comments - future []*Comment // Current is node for which comments are linked to Current Expression - // wasLineBreak determines if a line break occured while scanning for comments + // future lists the comments after a line break during a sequence of comments + future []*Comment + // wasLineBreak determines if a line break occurred while scanning for comments wasLineBreak bool // primary determines whether or not processing a primary expression primary bool @@ -93,6 +106,7 @@ type Comments struct { afterBlock bool } +// NewComments returns a new Comments. func NewComments() *Comments { comments := &Comments{ CommentMap: CommentMap{}, @@ -106,7 +120,7 @@ func (c *Comments) String() string { } // FetchAll returns all the currently scanned comments, -// including those from the next line +// including those from the next line. func (c *Comments) FetchAll() []*Comment { defer func() { c.Comments = nil @@ -116,7 +130,7 @@ func (c *Comments) FetchAll() []*Comment { return append(c.Comments, c.future...) } -// Fetch returns all the currently scanned comments +// Fetch returns all the currently scanned comments. func (c *Comments) Fetch() []*Comment { defer func() { c.Comments = nil @@ -125,12 +139,12 @@ func (c *Comments) Fetch() []*Comment { return c.Comments } -// ResetLineBreak marks the beginning of a new statement +// ResetLineBreak marks the beginning of a new statement. func (c *Comments) ResetLineBreak() { c.wasLineBreak = false } -// MarkPrimary will mark the context as processing a primary expression +// MarkPrimary will mark the context as processing a primary expression. func (c *Comments) MarkPrimary() { c.primary = true c.wasLineBreak = false @@ -204,7 +218,7 @@ func (c *Comments) SetExpression(node Expression) { c.applyComments(node, previous, TRAILING) } -// PostProcessNode applies all found comments to the given node +// PostProcessNode applies all found comments to the given node. func (c *Comments) PostProcessNode(node Node) { c.applyComments(node, nil, TRAILING) } @@ -227,15 +241,15 @@ func (c *Comments) applyComments(node, previous Node, position CommentPosition) } } -// AtLineBreak will mark a line break +// AtLineBreak will mark a line break. func (c *Comments) AtLineBreak() { c.wasLineBreak = true } -// CommentMap is the data structure where all found comments are stored +// CommentMap is the data structure where all found comments are stored. type CommentMap map[Node][]*Comment -// AddComment adds a single comment to the map +// AddComment adds a single comment to the map. func (cm CommentMap) AddComment(node Node, comment *Comment) { list := cm[node] list = append(list, comment) @@ -243,7 +257,7 @@ func (cm CommentMap) AddComment(node Node, comment *Comment) { cm[node] = list } -// AddComments adds a slice of comments, given a node and an updated position +// AddComments adds a slice of comments, given a node and an updated position. func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) { for _, comment := range comments { if comment.Position == TBD { @@ -253,7 +267,7 @@ func (cm CommentMap) AddComments(node Node, comments []*Comment, position Commen } } -// Size returns the size of the map +// Size returns the size of the map. func (cm CommentMap) Size() int { size := 0 for _, comments := range cm { @@ -263,7 +277,7 @@ func (cm CommentMap) Size() int { return size } -// MoveComments moves comments with a given position from a node to another +// MoveComments moves comments with a given position from a node to another. func (cm CommentMap) MoveComments(from, to Node, position CommentPosition) { for i, c := range cm[from] { if c.Position == position { diff --git a/vendor/github.com/robertkrimen/otto/ast/node.go b/vendor/github.com/robertkrimen/otto/ast/node.go index 7e45abe97..ae9e63b87 100644 --- a/vendor/github.com/robertkrimen/otto/ast/node.go +++ b/vendor/github.com/robertkrimen/otto/ast/node.go @@ -1,12 +1,8 @@ -/* -Package ast declares types representing a JavaScript AST. - -Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -*/ +// Package ast declares types representing a JavaScript AST. +// +// # Warning +// The parser and AST interfaces are still works-in-progress (particularly where +// node types are concerned) and may change in the future. package ast import ( @@ -14,502 +10,955 @@ import ( "github.com/robertkrimen/otto/token" ) -// All nodes implement the Node interface. +// Node is implemented by types that represent a node. type Node interface { Idx0() file.Idx // The index of the first character belonging to the node Idx1() file.Idx // The index of the first character immediately after the node } -// ========== // -// Expression // -// ========== // +// Expression is implemented by types that represent an Expression. +type Expression interface { + Node + expression() +} -type ( - // All expression nodes implement the Expression interface. - Expression interface { - Node - _expressionNode() - } +// ArrayLiteral represents an array literal. +type ArrayLiteral struct { + Value []Expression + LeftBracket file.Idx + RightBracket file.Idx +} - ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression - } +// Idx0 implements Node. +func (al *ArrayLiteral) Idx0() file.Idx { + return al.LeftBracket +} - AssignExpression struct { - Operator token.Token - Left Expression - Right Expression - } +// Idx1 implements Node. +func (al *ArrayLiteral) Idx1() file.Idx { + return al.RightBracket + 1 +} - BadExpression struct { - From file.Idx - To file.Idx - } +// expression implements Expression. +func (*ArrayLiteral) expression() {} - BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool - } +// AssignExpression represents an assignment expression. +type AssignExpression struct { + Left Expression + Right Expression + Operator token.Token +} - BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool - } +// Idx0 implements Node. +func (ae *AssignExpression) Idx0() file.Idx { + return ae.Left.Idx0() +} - BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx - } +// Idx1 implements Node. +func (ae *AssignExpression) Idx1() file.Idx { + return ae.Right.Idx1() +} - CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } +// expression implements Expression. +func (*AssignExpression) expression() {} - ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression - } +// BadExpression represents a bad expression. +type BadExpression struct { + From file.Idx + To file.Idx +} - DotExpression struct { - Left Expression - Identifier *Identifier - } +// Idx0 implements Node. +func (be *BadExpression) Idx0() file.Idx { + return be.From +} - EmptyExpression struct { - Begin file.Idx - End file.Idx - } +// Idx1 implements Node. +func (be *BadExpression) Idx1() file.Idx { + return be.To +} - FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string +// expression implements Expression. +func (*BadExpression) expression() {} - DeclarationList []Declaration - } +// BinaryExpression represents a binary expression. +type BinaryExpression struct { + Left Expression + Right Expression + Operator token.Token + Comparison bool +} - Identifier struct { - Name string - Idx file.Idx - } +// Idx0 implements Node. +func (be *BinaryExpression) Idx0() file.Idx { + return be.Left.Idx0() +} - NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } +// Idx1 implements Node. +func (be *BinaryExpression) Idx1() file.Idx { + return be.Right.Idx1() +} - NullLiteral struct { - Idx file.Idx - Literal string - } +// expression implements Expression. +func (*BinaryExpression) expression() {} - NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} - } +// BooleanLiteral represents a boolean expression. +type BooleanLiteral struct { + Literal string + Idx file.Idx + Value bool +} - ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property - } +// Idx0 implements Node. +func (bl *BooleanLiteral) Idx0() file.Idx { + return bl.Idx +} - ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx - } +// Idx1 implements Node. +func (bl *BooleanLiteral) Idx1() file.Idx { + return file.Idx(int(bl.Idx) + len(bl.Literal)) +} - Property struct { - Key string - Kind string - Value Expression - } +// expression implements Expression. +func (*BooleanLiteral) expression() {} - RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string - } +// BracketExpression represents a bracketed expression. +type BracketExpression struct { + Left Expression + Member Expression + LeftBracket file.Idx + RightBracket file.Idx +} - SequenceExpression struct { - Sequence []Expression - } +// Idx0 implements Node. +func (be *BracketExpression) Idx0() file.Idx { + return be.Left.Idx0() +} - StringLiteral struct { - Idx file.Idx - Literal string - Value string - } +// Idx1 implements Node. +func (be *BracketExpression) Idx1() file.Idx { + return be.RightBracket + 1 +} - ThisExpression struct { - Idx file.Idx - } +// expression implements Expression. +func (*BracketExpression) expression() {} - UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool - } +// CallExpression represents a call expression. +type CallExpression struct { + Callee Expression + ArgumentList []Expression + LeftParenthesis file.Idx + RightParenthesis file.Idx +} - VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression - } -) +// Idx0 implements Node. +func (ce *CallExpression) Idx0() file.Idx { + return ce.Callee.Idx0() +} -// _expressionNode - -func (*ArrayLiteral) _expressionNode() {} -func (*AssignExpression) _expressionNode() {} -func (*BadExpression) _expressionNode() {} -func (*BinaryExpression) _expressionNode() {} -func (*BooleanLiteral) _expressionNode() {} -func (*BracketExpression) _expressionNode() {} -func (*CallExpression) _expressionNode() {} -func (*ConditionalExpression) _expressionNode() {} -func (*DotExpression) _expressionNode() {} -func (*EmptyExpression) _expressionNode() {} -func (*FunctionLiteral) _expressionNode() {} -func (*Identifier) _expressionNode() {} -func (*NewExpression) _expressionNode() {} -func (*NullLiteral) _expressionNode() {} -func (*NumberLiteral) _expressionNode() {} -func (*ObjectLiteral) _expressionNode() {} -func (*RegExpLiteral) _expressionNode() {} -func (*SequenceExpression) _expressionNode() {} -func (*StringLiteral) _expressionNode() {} -func (*ThisExpression) _expressionNode() {} -func (*UnaryExpression) _expressionNode() {} -func (*VariableExpression) _expressionNode() {} - -// ========= // -// Statement // -// ========= // - -type ( - // All statement nodes implement the Statement interface. - Statement interface { - Node - _statementNode() - } +// Idx1 implements Node. +func (ce *CallExpression) Idx1() file.Idx { + return ce.RightParenthesis + 1 +} - BadStatement struct { - From file.Idx - To file.Idx - } +// expression implements Expression. +func (*CallExpression) expression() {} - BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx - } +// ConditionalExpression represents a conditional expression. +type ConditionalExpression struct { + Test Expression + Consequent Expression + Alternate Expression +} - BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier - } +// Idx0 implements Node. +func (ce *ConditionalExpression) Idx0() file.Idx { + return ce.Test.Idx0() +} - CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement - } +// Idx1 implements Node. +func (ce *ConditionalExpression) Idx1() file.Idx { + return ce.Alternate.Idx1() +} - CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement - } +// expression implements Expression. +func (*ConditionalExpression) expression() {} - DebuggerStatement struct { - Debugger file.Idx - } +// DotExpression represents a dot expression. +type DotExpression struct { + Left Expression + Identifier *Identifier +} - DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement - } +// Idx0 implements Node. +func (de *DotExpression) Idx0() file.Idx { + return de.Left.Idx0() +} - EmptyStatement struct { - Semicolon file.Idx - } +// Idx1 implements Node. +func (de *DotExpression) Idx1() file.Idx { + return de.Identifier.Idx1() +} - ExpressionStatement struct { - Expression Expression - } +// expression implements Expression. +func (*DotExpression) expression() {} - ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement - } +// EmptyExpression represents an empty expression. +type EmptyExpression struct { + Begin file.Idx + End file.Idx +} - ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement - } +// Idx0 implements Node. +func (ee *EmptyExpression) Idx0() file.Idx { + return ee.Begin +} - FunctionStatement struct { - Function *FunctionLiteral - } +// Idx1 implements Node. +func (ee *EmptyExpression) Idx1() file.Idx { + return ee.End +} - IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement - } +// expression implements Expression. +func (*EmptyExpression) expression() {} - LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement - } +// FunctionLiteral represents a function literal. +type FunctionLiteral struct { + Body Statement + Name *Identifier + ParameterList *ParameterList + Source string + DeclarationList []Declaration + Function file.Idx +} - ReturnStatement struct { - Return file.Idx - Argument Expression - } +// Idx0 implements Node. +func (fl *FunctionLiteral) Idx0() file.Idx { + return fl.Function +} - SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement - } +// Idx1 implements Node. +func (fl *FunctionLiteral) Idx1() file.Idx { + return fl.Body.Idx1() +} + +// expression implements Expression. +func (*FunctionLiteral) expression() {} + +// Identifier represents an identifier. +type Identifier struct { + Name string + Idx file.Idx +} + +// Idx0 implements Node. +func (i *Identifier) Idx0() file.Idx { + return i.Idx +} + +// Idx1 implements Node. +func (i *Identifier) Idx1() file.Idx { + return file.Idx(int(i.Idx) + len(i.Name)) +} + +// expression implements Expression. +func (*Identifier) expression() {} + +// NewExpression represents a new expression. +type NewExpression struct { + Callee Expression + ArgumentList []Expression + New file.Idx + LeftParenthesis file.Idx + RightParenthesis file.Idx +} + +// Idx0 implements Node. +func (ne *NewExpression) Idx0() file.Idx { + return ne.New +} - ThrowStatement struct { - Throw file.Idx - Argument Expression +// Idx1 implements Node. +func (ne *NewExpression) Idx1() file.Idx { + if ne.RightParenthesis > 0 { + return ne.RightParenthesis + 1 } + return ne.Callee.Idx1() +} + +// expression implements Expression. +func (*NewExpression) expression() {} + +// NullLiteral represents a null literal. +type NullLiteral struct { + Literal string + Idx file.Idx +} + +// Idx0 implements Node. +func (nl *NullLiteral) Idx0() file.Idx { + return nl.Idx +} + +// Idx1 implements Node. +func (nl *NullLiteral) Idx1() file.Idx { + return file.Idx(int(nl.Idx) + 4) +} + +// expression implements Expression. +func (*NullLiteral) expression() {} + +// NumberLiteral represents a number literal. +type NumberLiteral struct { + Value interface{} + Literal string + Idx file.Idx +} + +// Idx0 implements Node. +func (nl *NumberLiteral) Idx0() file.Idx { + return nl.Idx +} + +// Idx1 implements Node. +func (nl *NumberLiteral) Idx1() file.Idx { + return file.Idx(int(nl.Idx) + len(nl.Literal)) +} + +// expression implements Expression. +func (*NumberLiteral) expression() {} + +// ObjectLiteral represents an object literal. +type ObjectLiteral struct { + Value []Property + LeftBrace file.Idx + RightBrace file.Idx +} + +// Idx0 implements Node. +func (ol *ObjectLiteral) Idx0() file.Idx { + return ol.LeftBrace +} + +// Idx1 implements Node. +func (ol *ObjectLiteral) Idx1() file.Idx { + return ol.RightBrace + 1 +} + +// expression implements Expression. +func (*ObjectLiteral) expression() {} + +// ParameterList represents a parameter list. +type ParameterList struct { + List []*Identifier + Opening file.Idx + Closing file.Idx +} + +// Property represents a property. +type Property struct { + Value Expression + Key string + Kind string +} - TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement +// RegExpLiteral represents a regular expression literal. +type RegExpLiteral struct { + Literal string + Pattern string + Flags string + Value string + Idx file.Idx +} + +// Idx0 implements Node. +func (rl *RegExpLiteral) Idx0() file.Idx { + return rl.Idx +} + +// Idx1 implements Node. +func (rl *RegExpLiteral) Idx1() file.Idx { + return file.Idx(int(rl.Idx) + len(rl.Literal)) +} + +// expression implements Expression. +func (*RegExpLiteral) expression() {} + +// SequenceExpression represents a sequence literal. +type SequenceExpression struct { + Sequence []Expression +} + +// Idx0 implements Node. +func (se *SequenceExpression) Idx0() file.Idx { + return se.Sequence[0].Idx0() +} + +// Idx1 implements Node. +func (se *SequenceExpression) Idx1() file.Idx { + return se.Sequence[len(se.Sequence)-1].Idx1() +} + +// expression implements Expression. +func (*SequenceExpression) expression() {} + +// StringLiteral represents a string literal. +type StringLiteral struct { + Literal string + Value string + Idx file.Idx +} + +// Idx0 implements Node. +func (sl *StringLiteral) Idx0() file.Idx { + return sl.Idx +} + +// Idx1 implements Node. +func (sl *StringLiteral) Idx1() file.Idx { + return file.Idx(int(sl.Idx) + len(sl.Literal)) +} + +// expression implements Expression. +func (*StringLiteral) expression() {} + +// ThisExpression represents a this expression. +type ThisExpression struct { + Idx file.Idx +} + +// Idx0 implements Node. +func (te *ThisExpression) Idx0() file.Idx { + return te.Idx +} + +// Idx1 implements Node. +func (te *ThisExpression) Idx1() file.Idx { + return te.Idx + 4 +} + +// expression implements Expression. +func (*ThisExpression) expression() {} + +// UnaryExpression represents a unary expression. +type UnaryExpression struct { + Operand Expression + Operator token.Token + Idx file.Idx + Postfix bool +} + +// Idx0 implements Node. +func (ue *UnaryExpression) Idx0() file.Idx { + if ue.Postfix { + return ue.Operand.Idx0() } + return ue.Idx +} - VariableStatement struct { - Var file.Idx - List []Expression +// Idx1 implements Node. +func (ue *UnaryExpression) Idx1() file.Idx { + if ue.Postfix { + return ue.Operand.Idx1() + 2 // ++ -- } + return ue.Operand.Idx1() +} + +// expression implements Expression. +func (*UnaryExpression) expression() {} + +// VariableExpression represents a variable expression. +type VariableExpression struct { + Initializer Expression + Name string + Idx file.Idx +} - WhileStatement struct { - While file.Idx - Test Expression - Body Statement +// Idx0 implements Node. +func (ve *VariableExpression) Idx0() file.Idx { + return ve.Idx +} + +// Idx1 implements Node. +func (ve *VariableExpression) Idx1() file.Idx { + if ve.Initializer == nil { + return file.Idx(int(ve.Idx) + len(ve.Name)) } + return ve.Initializer.Idx1() +} + +// expression implements Expression. +func (*VariableExpression) expression() {} - WithStatement struct { - With file.Idx - Object Expression - Body Statement +// Statement is implemented by types which represent a statement. +type Statement interface { + Node + statement() +} + +// BadStatement represents a bad statement. +type BadStatement struct { + From file.Idx + To file.Idx +} + +// Idx0 implements Node. +func (bs *BadStatement) Idx0() file.Idx { + return bs.From +} + +// Idx1 implements Node. +func (bs *BadStatement) Idx1() file.Idx { + return bs.To +} + +// expression implements Statement. +func (*BadStatement) statement() {} + +// BlockStatement represents a block statement. +type BlockStatement struct { + List []Statement + LeftBrace file.Idx + RightBrace file.Idx +} + +// Idx0 implements Node. +func (bs *BlockStatement) Idx0() file.Idx { + return bs.LeftBrace +} + +// Idx1 implements Node. +func (bs *BlockStatement) Idx1() file.Idx { + return bs.RightBrace + 1 +} + +// expression implements Statement. +func (*BlockStatement) statement() {} + +// BranchStatement represents a branch statement. +type BranchStatement struct { + Label *Identifier + Idx file.Idx + Token token.Token +} + +// Idx0 implements Node. +func (bs *BranchStatement) Idx0() file.Idx { + return bs.Idx +} + +// Idx1 implements Node. +func (bs *BranchStatement) Idx1() file.Idx { + if bs.Label == nil { + return file.Idx(int(bs.Idx) + len(bs.Token.String())) } -) + return bs.Label.Idx1() +} + +// expression implements Statement. +func (*BranchStatement) statement() {} + +// CaseStatement represents a case statement. +type CaseStatement struct { + Test Expression + Consequent []Statement + Case file.Idx +} + +// Idx0 implements Node. +func (cs *CaseStatement) Idx0() file.Idx { + return cs.Case +} + +// Idx1 implements Node. +func (cs *CaseStatement) Idx1() file.Idx { + return cs.Consequent[len(cs.Consequent)-1].Idx1() +} + +// expression implements Statement. +func (*CaseStatement) statement() {} + +// CatchStatement represents a catch statement. +type CatchStatement struct { + Body Statement + Parameter *Identifier + Catch file.Idx +} + +// Idx0 implements Node. +func (cs *CatchStatement) Idx0() file.Idx { + return cs.Catch +} + +// Idx1 implements Node. +func (cs *CatchStatement) Idx1() file.Idx { + return cs.Body.Idx1() +} + +// expression implements Statement. +func (*CatchStatement) statement() {} + +// DebuggerStatement represents a debugger statement. +type DebuggerStatement struct { + Debugger file.Idx +} + +// Idx0 implements Node. +func (ds *DebuggerStatement) Idx0() file.Idx { + return ds.Debugger +} + +// Idx1 implements Node. +func (ds *DebuggerStatement) Idx1() file.Idx { + return ds.Debugger + 8 +} + +// expression implements Statement. +func (*DebuggerStatement) statement() {} + +// DoWhileStatement represents a do while statement. +type DoWhileStatement struct { + Test Expression + Body Statement + Do file.Idx + RightParenthesis file.Idx +} + +// Idx0 implements Node. +func (dws *DoWhileStatement) Idx0() file.Idx { + return dws.Do +} + +// Idx1 implements Node. +func (dws *DoWhileStatement) Idx1() file.Idx { + return dws.RightParenthesis + 1 +} + +// expression implements Statement. +func (*DoWhileStatement) statement() {} + +// EmptyStatement represents a empty statement. +type EmptyStatement struct { + Semicolon file.Idx +} + +// Idx0 implements Node. +func (es *EmptyStatement) Idx0() file.Idx { + return es.Semicolon +} + +// Idx1 implements Node. +func (es *EmptyStatement) Idx1() file.Idx { + return es.Semicolon + 1 +} + +// expression implements Statement. +func (*EmptyStatement) statement() {} + +// ExpressionStatement represents a expression statement. +type ExpressionStatement struct { + Expression Expression +} -// _statementNode - -func (*BadStatement) _statementNode() {} -func (*BlockStatement) _statementNode() {} -func (*BranchStatement) _statementNode() {} -func (*CaseStatement) _statementNode() {} -func (*CatchStatement) _statementNode() {} -func (*DebuggerStatement) _statementNode() {} -func (*DoWhileStatement) _statementNode() {} -func (*EmptyStatement) _statementNode() {} -func (*ExpressionStatement) _statementNode() {} -func (*ForInStatement) _statementNode() {} -func (*ForStatement) _statementNode() {} -func (*FunctionStatement) _statementNode() {} -func (*IfStatement) _statementNode() {} -func (*LabelledStatement) _statementNode() {} -func (*ReturnStatement) _statementNode() {} -func (*SwitchStatement) _statementNode() {} -func (*ThrowStatement) _statementNode() {} -func (*TryStatement) _statementNode() {} -func (*VariableStatement) _statementNode() {} -func (*WhileStatement) _statementNode() {} -func (*WithStatement) _statementNode() {} - -// =========== // -// Declaration // -// =========== // - -type ( - // All declaration nodes implement the Declaration interface. - Declaration interface { - _declarationNode() +// Idx0 implements Node. +func (es *ExpressionStatement) Idx0() file.Idx { + return es.Expression.Idx0() +} + +// Idx1 implements Node. +func (es *ExpressionStatement) Idx1() file.Idx { + return es.Expression.Idx1() +} + +// expression implements Statement. +func (*ExpressionStatement) statement() {} + +// ForInStatement represents a for in statement. +type ForInStatement struct { + Into Expression + Source Expression + Body Statement + For file.Idx +} + +// Idx0 implements Node. +func (fis *ForInStatement) Idx0() file.Idx { + return fis.For +} + +// Idx1 implements Node. +func (fis *ForInStatement) Idx1() file.Idx { + return fis.Body.Idx1() +} + +// expression implements Statement. +func (*ForInStatement) statement() {} + +// ForStatement represents a for statement. +type ForStatement struct { + Initializer Expression + Update Expression + Test Expression + Body Statement + For file.Idx +} + +// Idx0 implements Node. +func (fs *ForStatement) Idx0() file.Idx { + return fs.For +} + +// Idx1 implements Node. +func (fs *ForStatement) Idx1() file.Idx { + return fs.Body.Idx1() +} + +// expression implements Statement. +func (*ForStatement) statement() {} + +// FunctionStatement represents a function statement. +type FunctionStatement struct { + Function *FunctionLiteral +} + +// Idx0 implements Node. +func (fs *FunctionStatement) Idx0() file.Idx { + return fs.Function.Idx0() +} + +// Idx1 implements Node. +func (fs *FunctionStatement) Idx1() file.Idx { + return fs.Function.Idx1() +} + +// expression implements Statement. +func (*FunctionStatement) statement() {} + +// IfStatement represents a if statement. +type IfStatement struct { + Test Expression + Consequent Statement + Alternate Statement + If file.Idx +} + +// Idx0 implements Node. +func (is *IfStatement) Idx0() file.Idx { + return is.If +} + +// Idx1 implements Node. +func (is *IfStatement) Idx1() file.Idx { + if is.Alternate != nil { + return is.Alternate.Idx1() } + return is.Consequent.Idx1() +} + +// expression implements Statement. +func (*IfStatement) statement() {} + +// LabelledStatement represents a labelled statement. +type LabelledStatement struct { + Statement Statement + Label *Identifier + Colon file.Idx +} + +// Idx0 implements Node. +func (ls *LabelledStatement) Idx0() file.Idx { + return ls.Label.Idx0() +} + +// Idx1 implements Node. +func (ls *LabelledStatement) Idx1() file.Idx { + return ls.Statement.Idx1() +} + +// expression implements Statement. +func (*LabelledStatement) statement() {} + +// ReturnStatement represents a return statement. +type ReturnStatement struct { + Argument Expression + Return file.Idx +} + +// Idx0 implements Node. +func (rs *ReturnStatement) Idx0() file.Idx { + return rs.Return +} - FunctionDeclaration struct { - Function *FunctionLiteral +// Idx1 implements Node. +func (rs *ReturnStatement) Idx1() file.Idx { + if rs.Argument != nil { + return rs.Argument.Idx1() } + return rs.Return + 6 +} + +// expression implements Statement. +func (*ReturnStatement) statement() {} + +// SwitchStatement represents a switch statement. +type SwitchStatement struct { + Discriminant Expression + Body []*CaseStatement + Switch file.Idx + Default int + RightBrace file.Idx +} + +// Idx0 implements Node. +func (ss *SwitchStatement) Idx0() file.Idx { + return ss.Switch +} + +// Idx1 implements Node. +func (ss *SwitchStatement) Idx1() file.Idx { + return ss.RightBrace + 1 +} + +// expression implements Statement. +func (*SwitchStatement) statement() {} + +// ThrowStatement represents a throw statement. +type ThrowStatement struct { + Argument Expression + Throw file.Idx +} + +// Idx0 implements Node. +func (ts *ThrowStatement) Idx0() file.Idx { + return ts.Throw +} + +// Idx1 implements Node. +func (ts *ThrowStatement) Idx1() file.Idx { + return ts.Argument.Idx1() +} - VariableDeclaration struct { - Var file.Idx - List []*VariableExpression +// expression implements Statement. +func (*ThrowStatement) statement() {} + +// TryStatement represents a try statement. +type TryStatement struct { + Body Statement + Finally Statement + Catch *CatchStatement + Try file.Idx +} + +// Idx0 implements Node. +func (ts *TryStatement) Idx0() file.Idx { + return ts.Try +} + +// Idx1 implements Node. +func (ts *TryStatement) Idx1() file.Idx { + if ts.Finally != nil { + return ts.Finally.Idx1() } -) + return ts.Catch.Idx1() +} -// _declarationNode +// expression implements Statement. +func (*TryStatement) statement() {} -func (*FunctionDeclaration) _declarationNode() {} -func (*VariableDeclaration) _declarationNode() {} +// VariableStatement represents a variable statement. +type VariableStatement struct { + List []Expression + Var file.Idx +} -// ==== // -// Node // -// ==== // +// Idx0 implements Node. +func (vs *VariableStatement) Idx0() file.Idx { + return vs.Var +} -type Program struct { - Body []Statement +// Idx1 implements Node. +func (vs *VariableStatement) Idx1() file.Idx { + return vs.List[len(vs.List)-1].Idx1() +} + +// expression implements Statement. +func (*VariableStatement) statement() {} +// WhileStatement represents a while statement. +type WhileStatement struct { + Test Expression + Body Statement + While file.Idx +} + +// Idx0 implements Node. +func (ws *WhileStatement) Idx0() file.Idx { + return ws.While +} + +// Idx1 implements Node. +func (ws *WhileStatement) Idx1() file.Idx { + return ws.Body.Idx1() +} + +// expression implements Statement. +func (*WhileStatement) statement() {} + +// WithStatement represents a with statement. +type WithStatement struct { + Object Expression + Body Statement + With file.Idx +} + +// Idx0 implements Node. +func (ws *WithStatement) Idx0() file.Idx { + return ws.With +} + +// Idx1 implements Node. +func (ws *WithStatement) Idx1() file.Idx { + return ws.Body.Idx1() +} + +// expression implements Statement. +func (*WithStatement) statement() {} + +// Declaration is implemented by type which represent declarations. +type Declaration interface { + declaration() +} + +// FunctionDeclaration represents a function declaration. +type FunctionDeclaration struct { + Function *FunctionLiteral +} + +func (*FunctionDeclaration) declaration() {} + +// VariableDeclaration represents a variable declaration. +type VariableDeclaration struct { + List []*VariableExpression + Var file.Idx +} + +// declaration implements Declaration. +func (*VariableDeclaration) declaration() {} + +// Program represents a full program. +type Program struct { + File *file.File + Comments CommentMap + Body []Statement DeclarationList []Declaration +} - File *file.File - - Comments CommentMap -} - -// ==== // -// Idx0 // -// ==== // - -func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket } -func (self *AssignExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *BadExpression) Idx0() file.Idx { return self.From } -func (self *BinaryExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *BooleanLiteral) Idx0() file.Idx { return self.Idx } -func (self *BracketExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() } -func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() } -func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *EmptyExpression) Idx0() file.Idx { return self.Begin } -func (self *FunctionLiteral) Idx0() file.Idx { return self.Function } -func (self *Identifier) Idx0() file.Idx { return self.Idx } -func (self *NewExpression) Idx0() file.Idx { return self.New } -func (self *NullLiteral) Idx0() file.Idx { return self.Idx } -func (self *NumberLiteral) Idx0() file.Idx { return self.Idx } -func (self *ObjectLiteral) Idx0() file.Idx { return self.LeftBrace } -func (self *RegExpLiteral) Idx0() file.Idx { return self.Idx } -func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx0() } -func (self *StringLiteral) Idx0() file.Idx { return self.Idx } -func (self *ThisExpression) Idx0() file.Idx { return self.Idx } -func (self *UnaryExpression) Idx0() file.Idx { return self.Idx } -func (self *VariableExpression) Idx0() file.Idx { return self.Idx } - -func (self *BadStatement) Idx0() file.Idx { return self.From } -func (self *BlockStatement) Idx0() file.Idx { return self.LeftBrace } -func (self *BranchStatement) Idx0() file.Idx { return self.Idx } -func (self *CaseStatement) Idx0() file.Idx { return self.Case } -func (self *CatchStatement) Idx0() file.Idx { return self.Catch } -func (self *DebuggerStatement) Idx0() file.Idx { return self.Debugger } -func (self *DoWhileStatement) Idx0() file.Idx { return self.Do } -func (self *EmptyStatement) Idx0() file.Idx { return self.Semicolon } -func (self *ExpressionStatement) Idx0() file.Idx { return self.Expression.Idx0() } -func (self *ForInStatement) Idx0() file.Idx { return self.For } -func (self *ForStatement) Idx0() file.Idx { return self.For } -func (self *FunctionStatement) Idx0() file.Idx { return self.Function.Idx0() } -func (self *IfStatement) Idx0() file.Idx { return self.If } -func (self *LabelledStatement) Idx0() file.Idx { return self.Label.Idx0() } -func (self *Program) Idx0() file.Idx { return self.Body[0].Idx0() } -func (self *ReturnStatement) Idx0() file.Idx { return self.Return } -func (self *SwitchStatement) Idx0() file.Idx { return self.Switch } -func (self *ThrowStatement) Idx0() file.Idx { return self.Throw } -func (self *TryStatement) Idx0() file.Idx { return self.Try } -func (self *VariableStatement) Idx0() file.Idx { return self.Var } -func (self *WhileStatement) Idx0() file.Idx { return self.While } -func (self *WithStatement) Idx0() file.Idx { return self.With } - -// ==== // -// Idx1 // -// ==== // - -func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket } -func (self *AssignExpression) Idx1() file.Idx { return self.Right.Idx1() } -func (self *BadExpression) Idx1() file.Idx { return self.To } -func (self *BinaryExpression) Idx1() file.Idx { return self.Right.Idx1() } -func (self *BooleanLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket + 1 } -func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() } -func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() } -func (self *EmptyExpression) Idx1() file.Idx { return self.End } -func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() } -func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) } -func (self *NewExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null" -func (self *NumberLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace } -func (self *RegExpLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *SequenceExpression) Idx1() file.Idx { return self.Sequence[0].Idx1() } -func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *ThisExpression) Idx1() file.Idx { return self.Idx + 4 } -func (self *UnaryExpression) Idx1() file.Idx { - if self.Postfix { - return self.Operand.Idx1() + 2 // ++ -- - } - return self.Operand.Idx1() +// Idx0 implements Node. +func (p *Program) Idx0() file.Idx { + return p.Body[0].Idx0() +} + +// Idx1 implements Node. +func (p *Program) Idx1() file.Idx { + return p.Body[len(p.Body)-1].Idx1() } -func (self *VariableExpression) Idx1() file.Idx { - if self.Initializer == nil { - return file.Idx(int(self.Idx) + len(self.Name) + 1) - } - return self.Initializer.Idx1() -} - -func (self *BadStatement) Idx1() file.Idx { return self.To } -func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 } -func (self *BranchStatement) Idx1() file.Idx { return self.Idx } -func (self *CaseStatement) Idx1() file.Idx { return self.Consequent[len(self.Consequent)-1].Idx1() } -func (self *CatchStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *DebuggerStatement) Idx1() file.Idx { return self.Debugger + 8 } -func (self *DoWhileStatement) Idx1() file.Idx { return self.Test.Idx1() } -func (self *EmptyStatement) Idx1() file.Idx { return self.Semicolon + 1 } -func (self *ExpressionStatement) Idx1() file.Idx { return self.Expression.Idx1() } -func (self *ForInStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *ForStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *FunctionStatement) Idx1() file.Idx { return self.Function.Idx1() } -func (self *IfStatement) Idx1() file.Idx { - if self.Alternate != nil { - return self.Alternate.Idx1() - } - return self.Consequent.Idx1() -} -func (self *LabelledStatement) Idx1() file.Idx { return self.Colon + 1 } -func (self *Program) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ReturnStatement) Idx1() file.Idx { return self.Return } -func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ThrowStatement) Idx1() file.Idx { return self.Throw } -func (self *TryStatement) Idx1() file.Idx { return self.Try } -func (self *VariableStatement) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() } -func (self *WhileStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *WithStatement) Idx1() file.Idx { return self.Body.Idx1() } diff --git a/vendor/github.com/robertkrimen/otto/ast/walk.go b/vendor/github.com/robertkrimen/otto/ast/walk.go index 7580a82b5..442293027 100644 --- a/vendor/github.com/robertkrimen/otto/ast/walk.go +++ b/vendor/github.com/robertkrimen/otto/ast/walk.go @@ -38,6 +38,7 @@ func Walk(v Visitor, n Node) { Walk(v, n.Right) } case *BadExpression: + case *BadStatement: case *BinaryExpression: if n != nil { Walk(v, n.Left) @@ -93,6 +94,7 @@ func Walk(v Visitor, n Node) { case *DotExpression: if n != nil { Walk(v, n.Left) + Walk(v, n.Identifier) } case *EmptyExpression: case *EmptyStatement: @@ -134,6 +136,7 @@ func Walk(v Visitor, n Node) { } case *LabelledStatement: if n != nil { + Walk(v, n.Label) Walk(v, n.Statement) } case *NewExpression: diff --git a/vendor/github.com/robertkrimen/otto/builtin.go b/vendor/github.com/robertkrimen/otto/builtin.go index 256ee3c55..bfb15621a 100644 --- a/vendor/github.com/robertkrimen/otto/builtin.go +++ b/vendor/github.com/robertkrimen/otto/builtin.go @@ -2,6 +2,7 @@ package otto import ( "encoding/hex" + "errors" "math" "net/url" "regexp" @@ -11,52 +12,36 @@ import ( "unicode/utf8" ) -// Global -func builtinGlobal_eval(call FunctionCall) Value { +// Global. +func builtinGlobalEval(call FunctionCall) Value { src := call.Argument(0) if !src.IsString() { return src } - runtime := call.runtime - program := runtime.cmpl_parseOrThrow(src.string(), nil) + rt := call.runtime + program := rt.cmplParseOrThrow(src.string(), nil) if !call.eval { // Not a direct call to eval, so we enter the global ExecutionContext - runtime.enterGlobalScope() - defer runtime.leaveScope() + rt.enterGlobalScope() + defer rt.leaveScope() } - returnValue := runtime.cmpl_evaluate_nodeProgram(program, true) + returnValue := rt.cmplEvaluateNodeProgram(program, true) if returnValue.isEmpty() { return Value{} } return returnValue } -func builtinGlobal_isNaN(call FunctionCall) Value { +func builtinGlobalIsNaN(call FunctionCall) Value { value := call.Argument(0).float64() - return toValue_bool(math.IsNaN(value)) + return boolValue(math.IsNaN(value)) } -func builtinGlobal_isFinite(call FunctionCall) Value { +func builtinGlobalIsFinite(call FunctionCall) Value { value := call.Argument(0).float64() - return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0)) + return boolValue(!math.IsNaN(value) && !math.IsInf(value, 0)) } -// radix 3 => 2 (ASCII 50) +47 -// radix 11 => A/a (ASCII 65/97) +54/+86 -var parseInt_alphabetTable = func() []string { - table := []string{"", "", "01"} - for radix := 3; radix <= 36; radix += 1 { - alphabet := table[radix-1] - if radix <= 10 { - alphabet += string(radix + 47) - } else { - alphabet += string(radix+54) + string(radix+86) - } - table = append(table, alphabet) - } - return table -}() - func digitValue(chr rune) int { switch { case '0' <= chr && chr <= '9': @@ -69,8 +54,8 @@ func digitValue(chr rune) int { return 36 // Larger than any legal digit value } -func builtinGlobal_parseInt(call FunctionCall) Value { - input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace) +func builtinGlobalParseInt(call FunctionCall) Value { + input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace) if len(input) == 0 { return NaNValue() } @@ -122,50 +107,51 @@ func builtinGlobal_parseInt(call FunctionCall) Value { value, err := strconv.ParseInt(input, radix, 64) if err != nil { - if err.(*strconv.NumError).Err == strconv.ErrRange { + if errors.Is(err, strconv.ErrRange) { base := float64(base) // Could just be a very large number (e.g. 0x8000000000000000) var value float64 for _, chr := range input { digit := float64(digitValue(chr)) if digit >= base { - goto error + return NaNValue() } value = value*base + digit } if negative { value *= -1 } - return toValue_float64(value) + return float64Value(value) } - error: return NaNValue() } if negative { value *= -1 } - return toValue_int64(value) + return int64Value(value) } -var parseFloat_matchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`) -var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) +var ( + parseFloatMatchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`) + parseFloatMatchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) +) -func builtinGlobal_parseFloat(call FunctionCall) Value { +func builtinGlobalParseFloat(call FunctionCall) Value { // Caveat emptor: This implementation does NOT match the specification - input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace) + input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace) - if parseFloat_matchBadSpecial.MatchString(input) { + if parseFloatMatchBadSpecial.MatchString(input) { return NaNValue() } value, err := strconv.ParseFloat(input, 64) if err != nil { for end := len(input); end > 0; end-- { - input := input[0:end] - if !parseFloat_matchValid.MatchString(input) { + val := input[0:end] + if !parseFloatMatchValid.MatchString(val) { return NaNValue() } - value, err = strconv.ParseFloat(input, 64) + value, err = strconv.ParseFloat(val, 64) if err == nil { break } @@ -174,12 +160,12 @@ func builtinGlobal_parseFloat(call FunctionCall) Value { return NaNValue() } } - return toValue_float64(value) + return float64Value(value) } // encodeURI/decodeURI -func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { +func encodeDecodeURI(call FunctionCall, escape *regexp.Regexp) Value { value := call.Argument(0) var input []uint16 switch vl := value.value.(type) { @@ -189,7 +175,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { input = utf16.Encode([]rune(value.string())) } if len(input) == 0 { - return toValue_string("") + return stringValue("") } output := []byte{} length := len(input) @@ -201,7 +187,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { panic(call.runtime.panicURIError("URI malformed")) } if value >= 0xD800 && value <= 0xDBFF { - index += 1 + index++ if index >= length { panic(call.runtime.panicURIError("URI malformed")) } @@ -212,43 +198,41 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { } decode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000} } - index += 1 + index++ size := utf8.EncodeRune(encode, decode[0]) - encode := encode[0:size] - output = append(output, encode...) - } - { - value := escape.ReplaceAllFunc(output, func(target []byte) []byte { - // Probably a better way of doing this - if target[0] == ' ' { - return []byte("%20") - } - return []byte(url.QueryEscape(string(target))) - }) - return toValue_string(string(value)) + output = append(output, encode[0:size]...) } + + bytes := escape.ReplaceAllFunc(output, func(target []byte) []byte { + // Probably a better way of doing this + if target[0] == ' ' { + return []byte("%20") + } + return []byte(url.QueryEscape(string(target))) + }) + return stringValue(string(bytes)) } -var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) +var encodeURIRegexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) -func builtinGlobal_encodeURI(call FunctionCall) Value { - return _builtinGlobal_encodeURI(call, encodeURI_Regexp) +func builtinGlobalEncodeURI(call FunctionCall) Value { + return encodeDecodeURI(call, encodeURIRegexp) } -var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`) +var encodeURIComponentRegexp = regexp.MustCompile(`([^~!*()'])`) -func builtinGlobal_encodeURIComponent(call FunctionCall) Value { - return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp) +func builtinGlobalEncodeURIComponent(call FunctionCall) Value { + return encodeDecodeURI(call, encodeURIComponentRegexp) } -// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23 -var decodeURI_guard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) +// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23. +var decodeURIGuard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) -func _decodeURI(input string, reserve bool) (string, bool) { +func decodeURI(input string, reserve bool) (string, bool) { if reserve { - input = decodeURI_guard.ReplaceAllString(input, "%25$1") + input = decodeURIGuard.ReplaceAllString(input, "%25$1") } - input = strings.Replace(input, "+", "%2B", -1) // Ugly hack to make QueryUnescape work with our use case + input = strings.ReplaceAll(input, "+", "%2B") // Ugly hack to make QueryUnescape work with our use case output, err := url.QueryUnescape(input) if err != nil || !utf8.ValidString(output) { return "", true @@ -256,25 +240,25 @@ func _decodeURI(input string, reserve bool) (string, bool) { return output, false } -func builtinGlobal_decodeURI(call FunctionCall) Value { - output, err := _decodeURI(call.Argument(0).string(), true) +func builtinGlobalDecodeURI(call FunctionCall) Value { + output, err := decodeURI(call.Argument(0).string(), true) if err { panic(call.runtime.panicURIError("URI malformed")) } - return toValue_string(output) + return stringValue(output) } -func builtinGlobal_decodeURIComponent(call FunctionCall) Value { - output, err := _decodeURI(call.Argument(0).string(), false) +func builtinGlobalDecodeURIComponent(call FunctionCall) Value { + output, err := decodeURI(call.Argument(0).string(), false) if err { panic(call.runtime.panicURIError("URI malformed")) } - return toValue_string(output) + return stringValue(output) } // escape/unescape -func builtin_shouldEscape(chr byte) bool { +func builtinShouldEscape(chr byte) bool { if 'A' <= chr && chr <= 'Z' || 'a' <= chr && chr <= 'z' || '0' <= chr && chr <= '9' { return false } @@ -283,11 +267,11 @@ func builtin_shouldEscape(chr byte) bool { const escapeBase16 = "0123456789ABCDEF" -func builtin_escape(input string) string { +func builtinEscape(input string) string { output := make([]byte, 0, len(input)) length := len(input) for index := 0; index < length; { - if builtin_shouldEscape(input[index]) { + if builtinShouldEscape(input[index]) { chr, width := utf8.DecodeRuneInString(input[index:]) chr16 := utf16.Encode([]rune{chr})[0] if 256 > chr16 { @@ -304,16 +288,15 @@ func builtin_escape(input string) string { ) } index += width - } else { output = append(output, input[index]) - index += 1 + index++ } } return string(output) } -func builtin_unescape(input string) string { +func builtinUnescape(input string) string { output := make([]rune, 0, len(input)) length := len(input) for index := 0; index < length; { @@ -340,15 +323,15 @@ func builtin_unescape(input string) string { } } output = append(output, rune(input[index])) - index += 1 + index++ } return string(output) } -func builtinGlobal_escape(call FunctionCall) Value { - return toValue_string(builtin_escape(call.Argument(0).string())) +func builtinGlobalEscape(call FunctionCall) Value { + return stringValue(builtinEscape(call.Argument(0).string())) } -func builtinGlobal_unescape(call FunctionCall) Value { - return toValue_string(builtin_unescape(call.Argument(0).string())) +func builtinGlobalUnescape(call FunctionCall) Value { + return stringValue(builtinUnescape(call.Argument(0).string())) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_array.go b/vendor/github.com/robertkrimen/otto/builtin_array.go index 56dd95ab6..c4c30e1b7 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_array.go +++ b/vendor/github.com/robertkrimen/otto/builtin_array.go @@ -8,92 +8,93 @@ import ( // Array func builtinArray(call FunctionCall) Value { - return toValue_object(builtinNewArrayNative(call.runtime, call.ArgumentList)) + return objectValue(builtinNewArrayNative(call.runtime, call.ArgumentList)) } -func builtinNewArray(self *_object, argumentList []Value) Value { - return toValue_object(builtinNewArrayNative(self.runtime, argumentList)) +func builtinNewArray(obj *object, argumentList []Value) Value { + return objectValue(builtinNewArrayNative(obj.runtime, argumentList)) } -func builtinNewArrayNative(runtime *_runtime, argumentList []Value) *_object { +func builtinNewArrayNative(rt *runtime, argumentList []Value) *object { if len(argumentList) == 1 { firstArgument := argumentList[0] if firstArgument.IsNumber() { - return runtime.newArray(arrayUint32(runtime, firstArgument)) + return rt.newArray(arrayUint32(rt, firstArgument)) } } - return runtime.newArrayOf(argumentList) + return rt.newArrayOf(argumentList) } -func builtinArray_toString(call FunctionCall) Value { +func builtinArrayToString(call FunctionCall) Value { thisObject := call.thisObject() join := thisObject.get("join") if join.isCallable() { - join := join._object() + join := join.object() return join.call(call.This, call.ArgumentList, false, nativeFrame) } - return builtinObject_toString(call) + return builtinObjectToString(call) } -func builtinArray_toLocaleString(call FunctionCall) Value { +func builtinArrayToLocaleString(call FunctionCall) Value { separator := "," thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) if length == 0 { - return toValue_string("") + return stringValue("") } stringList := make([]string, 0, length) - for index := int64(0); index < length; index += 1 { + for index := range length { value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value.kind { case valueEmpty, valueUndefined, valueNull: default: - object := call.runtime.toObject(value) - toLocaleString := object.get("toLocaleString") + obj := call.runtime.toObject(value) + toLocaleString := obj.get("toLocaleString") if !toLocaleString.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.toLocaleString index[%d] %q is not callable", index, toLocaleString)) } - stringValue = toLocaleString.call(call.runtime, toValue_object(object)).string() + stringValue = toLocaleString.call(call.runtime, objectValue(obj)).string() } stringList = append(stringList, stringValue) } - return toValue_string(strings.Join(stringList, separator)) + return stringValue(strings.Join(stringList, separator)) } -func builtinArray_concat(call FunctionCall) Value { +func builtinArrayConcat(call FunctionCall) Value { thisObject := call.thisObject() valueArray := []Value{} - source := append([]Value{toValue_object(thisObject)}, call.ArgumentList...) + source := append([]Value{objectValue(thisObject)}, call.ArgumentList...) for _, item := range source { switch item.kind { case valueObject: - object := item._object() - if isArray(object) { - length := object.get("length").number().int64 - for index := int64(0); index < length; index += 1 { + obj := item.object() + if isArray(obj) { + length := obj.get(propertyLength).number().int64 + for index := range length { name := strconv.FormatInt(index, 10) - if object.hasProperty(name) { - valueArray = append(valueArray, object.get(name)) + if obj.hasProperty(name) { + valueArray = append(valueArray, obj.get(name)) } else { valueArray = append(valueArray, Value{}) } } continue } + fallthrough default: valueArray = append(valueArray, item) } } - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } -func builtinArray_shift(call FunctionCall) Value { +func builtinArrayShift(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) - if 0 == length { - thisObject.put("length", toValue_int64(0), true) + length := int64(toUint32(thisObject.get(propertyLength))) + if length == 0 { + thisObject.put(propertyLength, int64Value(0), true) return Value{} } first := thisObject.get("0") @@ -107,52 +108,50 @@ func builtinArray_shift(call FunctionCall) Value { } } thisObject.delete(arrayIndexToString(length-1), true) - thisObject.put("length", toValue_int64(length-1), true) + thisObject.put(propertyLength, int64Value(length-1), true) return first } -func builtinArray_push(call FunctionCall) Value { +func builtinArrayPush(call FunctionCall) Value { thisObject := call.thisObject() itemList := call.ArgumentList - index := int64(toUint32(thisObject.get("length"))) + index := int64(toUint32(thisObject.get(propertyLength))) for len(itemList) > 0 { thisObject.put(arrayIndexToString(index), itemList[0], true) itemList = itemList[1:] - index += 1 + index++ } - length := toValue_int64(index) - thisObject.put("length", length, true) + length := int64Value(index) + thisObject.put(propertyLength, length, true) return length } -func builtinArray_pop(call FunctionCall) Value { +func builtinArrayPop(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) - if 0 == length { - thisObject.put("length", toValue_uint32(0), true) + length := int64(toUint32(thisObject.get(propertyLength))) + if length == 0 { + thisObject.put(propertyLength, uint32Value(0), true) return Value{} } last := thisObject.get(arrayIndexToString(length - 1)) thisObject.delete(arrayIndexToString(length-1), true) - thisObject.put("length", toValue_int64(length-1), true) + thisObject.put(propertyLength, int64Value(length-1), true) return last } -func builtinArray_join(call FunctionCall) Value { +func builtinArrayJoin(call FunctionCall) Value { separator := "," - { - argument := call.Argument(0) - if argument.IsDefined() { - separator = argument.string() - } + argument := call.Argument(0) + if argument.IsDefined() { + separator = argument.string() } thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) if length == 0 { - return toValue_string("") + return stringValue("") } stringList := make([]string, 0, length) - for index := int64(0); index < length; index += 1 { + for index := range length { value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value.kind { @@ -162,12 +161,12 @@ func builtinArray_join(call FunctionCall) Value { } stringList = append(stringList, stringValue) } - return toValue_string(strings.Join(stringList, separator)) + return stringValue(strings.Join(stringList, separator)) } -func builtinArray_splice(call FunctionCall) Value { +func builtinArraySplice(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) start := valueToRangeIndex(call.Argument(0), length, false) deleteCount := length - start @@ -176,8 +175,8 @@ func builtinArray_splice(call FunctionCall) Value { } valueArray := make([]Value, deleteCount) - for index := int64(0); index < deleteCount; index++ { - indexString := arrayIndexToString(int64(start + index)) + for index := range deleteCount { + indexString := arrayIndexToString(start + index) if thisObject.hasProperty(indexString) { valueArray[index] = thisObject.get(indexString) } @@ -197,7 +196,7 @@ func builtinArray_splice(call FunctionCall) Value { } if itemCount < deleteCount { // The Object/Array is shrinking - stop := int64(length) - deleteCount + stop := length - deleteCount // The new length of the Object/Array before // appending the itemList remainder // Stopping at the lower bound of the insertion: @@ -215,7 +214,7 @@ func builtinArray_splice(call FunctionCall) Value { // Delete off the end // We don't bother to delete below (if any) since those // will be overwritten anyway - for index := int64(length); index > (stop + itemCount); index-- { + for index := length; index > (stop + itemCount); index-- { thisObject.delete(arrayIndexToString(index-1), true) } } else if itemCount > deleteCount { @@ -226,7 +225,7 @@ func builtinArray_splice(call FunctionCall) Value { // Starting from the upper bound of the deletion: // Move an item from the after the deleted portion // to a position after the inserted portion - for index := int64(length) - deleteCount; index > start; index-- { + for index := length - deleteCount; index > start; index-- { from := arrayIndexToString(index + deleteCount - 1) to := arrayIndexToString(index + itemCount - 1) if thisObject.hasProperty(from) { @@ -237,40 +236,40 @@ func builtinArray_splice(call FunctionCall) Value { } } - for index := int64(0); index < itemCount; index++ { + for index := range itemCount { thisObject.put(arrayIndexToString(index+start), itemList[index], true) } - thisObject.put("length", toValue_int64(int64(length)+itemCount-deleteCount), true) + thisObject.put(propertyLength, int64Value(length+itemCount-deleteCount), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } -func builtinArray_slice(call FunctionCall) Value { +func builtinArraySlice(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) start, end := rangeStartEnd(call.ArgumentList, length, false) if start >= end { // Always an empty array - return toValue_object(call.runtime.newArray(0)) + return objectValue(call.runtime.newArray(0)) } sliceLength := end - start sliceValueArray := make([]Value, sliceLength) - for index := int64(0); index < sliceLength; index++ { + for index := range sliceLength { from := arrayIndexToString(index + start) if thisObject.hasProperty(from) { sliceValueArray[index] = thisObject.get(from) } } - return toValue_object(call.runtime.newArrayOf(sliceValueArray)) + return objectValue(call.runtime.newArrayOf(sliceValueArray)) } -func builtinArray_unshift(call FunctionCall) Value { +func builtinArrayUnshift(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) itemList := call.ArgumentList itemCount := int64(len(itemList)) @@ -284,18 +283,18 @@ func builtinArray_unshift(call FunctionCall) Value { } } - for index := int64(0); index < itemCount; index++ { + for index := range itemCount { thisObject.put(arrayIndexToString(index), itemList[index], true) } - newLength := toValue_int64(length + itemCount) - thisObject.put("length", newLength, true) + newLength := int64Value(length + itemCount) + thisObject.put(propertyLength, newLength, true) return newLength } -func builtinArray_reverse(call FunctionCall) Value { +func builtinArrayReverse(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) lower := struct { name string @@ -315,35 +314,34 @@ func builtinArray_reverse(call FunctionCall) Value { lower.exists = thisObject.hasProperty(lower.name) upper.exists = thisObject.hasProperty(upper.name) - if lower.exists && upper.exists { + switch { + case lower.exists && upper.exists: lowerValue := thisObject.get(lower.name) upperValue := thisObject.get(upper.name) thisObject.put(lower.name, upperValue, true) thisObject.put(upper.name, lowerValue, true) - } else if !lower.exists && upper.exists { + case !lower.exists && upper.exists: value := thisObject.get(upper.name) thisObject.delete(upper.name, true) thisObject.put(lower.name, value, true) - } else if lower.exists && !upper.exists { + case lower.exists && !upper.exists: value := thisObject.get(lower.name) thisObject.delete(lower.name, true) thisObject.put(upper.name, value, true) - } else { - // Nothing happens. } - lower.index += 1 + lower.index++ } return call.This } -func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int { +func sortCompare(thisObject *object, index0, index1 uint, compare *object) int { j := struct { name string + value string exists bool defined bool - value string }{} k := j j.name = arrayIndexToString(int64(index0)) @@ -351,11 +349,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int k.name = arrayIndexToString(int64(index1)) k.exists = thisObject.hasProperty(k.name) - if !j.exists && !k.exists { + switch { + case !j.exists && !k.exists: return 0 - } else if !j.exists { + case !j.exists: return 1 - } else if !k.exists { + case !k.exists: return -1 } @@ -364,11 +363,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int j.defined = x.IsDefined() k.defined = y.IsDefined() - if !j.defined && !k.defined { + switch { + case !j.defined && !k.defined: return 0 - } else if !j.defined { + case !j.defined: return 1 - } else if !k.defined { + case !k.defined: return -1 } @@ -385,11 +385,10 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int return 1 } - return int(toInt32(compare.call(Value{}, []Value{x, y}, false, nativeFrame))) + return toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame)) } -func arraySortSwap(thisObject *_object, index0, index1 uint) { - +func arraySortSwap(thisObject *object, index0, index1 uint) { j := struct { name string exists bool @@ -401,25 +400,24 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) { k.name = arrayIndexToString(int64(index1)) k.exists = thisObject.hasProperty(k.name) - if j.exists && k.exists { - jValue := thisObject.get(j.name) - kValue := thisObject.get(k.name) - thisObject.put(j.name, kValue, true) - thisObject.put(k.name, jValue, true) - } else if !j.exists && k.exists { + switch { + case j.exists && k.exists: + jv := thisObject.get(j.name) + kv := thisObject.get(k.name) + thisObject.put(j.name, kv, true) + thisObject.put(k.name, jv, true) + case !j.exists && k.exists: value := thisObject.get(k.name) thisObject.delete(k.name, true) thisObject.put(j.name, value, true) - } else if j.exists && !k.exists { + case j.exists && !k.exists: value := thisObject.get(j.name) thisObject.delete(j.name, true) thisObject.put(k.name, value, true) - } else { - // Nothing happens. } } -func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compare *_object) (uint, uint) { +func arraySortQuickPartition(thisObject *object, left, right, pivot uint, compare *object) (uint, uint) { arraySortSwap(thisObject, pivot, right) // Right is now the pivot value cursor := left cursor2 := left @@ -430,18 +428,18 @@ func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compa if cursor < cursor2 { arraySortSwap(thisObject, index, cursor2) } - cursor += 1 - cursor2 += 1 + cursor++ + cursor2++ } else if comparison == 0 { arraySortSwap(thisObject, index, cursor2) - cursor2 += 1 + cursor2++ } } arraySortSwap(thisObject, cursor2, right) return cursor, cursor2 } -func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) { +func arraySortQuickSort(thisObject *object, left, right uint, compare *object) { if left < right { middle := left + (right-left)/2 pivot, pivot2 := arraySortQuickPartition(thisObject, left, right, middle, compare) @@ -452,14 +450,14 @@ func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) } } -func builtinArray_sort(call FunctionCall) Value { +func builtinArraySort(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUint32(thisObject.get("length"))) + length := uint(toUint32(thisObject.get(propertyLength))) compareValue := call.Argument(0) - compare := compareValue._object() + compare := compareValue.object() if compareValue.IsUndefined() { } else if !compareValue.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.sort value %q is not callable", compareValue)) } if length > 1 { arraySortQuickSort(thisObject, 0, length-1, compare) @@ -467,13 +465,13 @@ func builtinArray_sort(call FunctionCall) Value { return call.This } -func builtinArray_isArray(call FunctionCall) Value { - return toValue_bool(isArray(call.Argument(0)._object())) +func builtinArrayIsArray(call FunctionCall) Value { + return boolValue(isArray(call.Argument(0).object())) } -func builtinArray_indexOf(call FunctionCall) Value { +func builtinArrayIndexOf(call FunctionCall) Value { thisObject, matchValue := call.thisObject(), call.Argument(0) - if length := int64(toUint32(thisObject.get("length"))); length > 0 { + if length := int64(toUint32(thisObject.get(propertyLength))); length > 0 { index := int64(0) if len(call.ArgumentList) > 1 { index = call.Argument(1).number().int64 @@ -486,22 +484,22 @@ func builtinArray_indexOf(call FunctionCall) Value { index = -1 } for ; index >= 0 && index < length; index++ { - name := arrayIndexToString(int64(index)) + name := arrayIndexToString(index) if !thisObject.hasProperty(name) { continue } value := thisObject.get(name) if strictEqualityComparison(matchValue, value) { - return toValue_uint32(uint32(index)) + return uint32Value(uint32(index)) } } } - return toValue_int(-1) + return intValue(-1) } -func builtinArray_lastIndexOf(call FunctionCall) Value { +func builtinArrayLastIndexOf(call FunctionCall) Value { thisObject, matchValue := call.thisObject(), call.Argument(0) - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) index := length - 1 if len(call.ArgumentList) > 1 { index = call.Argument(1).number().int64 @@ -512,30 +510,30 @@ func builtinArray_lastIndexOf(call FunctionCall) Value { if index > length { index = length - 1 } else if 0 > index { - return toValue_int(-1) + return intValue(-1) } for ; index >= 0; index-- { - name := arrayIndexToString(int64(index)) + name := arrayIndexToString(index) if !thisObject.hasProperty(name) { continue } value := thisObject.get(name) if strictEqualityComparison(matchValue, value) { - return toValue_uint32(uint32(index)) + return uint32Value(uint32(index)) } } - return toValue_int(-1) + return intValue(-1) } -func builtinArray_every(call FunctionCall) Value { +func builtinArrayEvery(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() { continue } return falseValue @@ -543,70 +541,70 @@ func builtinArray_every(call FunctionCall) Value { } return trueValue } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.every argument %q is not callable", call.Argument(0))) } -func builtinArray_some(call FunctionCall) Value { +func builtinArraySome(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() { return trueValue } } } return falseValue } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.some %q if not callable", call.Argument(0))) } -func builtinArray_forEach(call FunctionCall) Value { +func builtinArrayForEach(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - iterator.call(call.runtime, callThis, thisObject.get(key), toValue_int64(index), this) + iterator.call(call.runtime, callThis, thisObject.get(key), int64Value(index), this) } } return Value{} } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.foreach %q if not callable", call.Argument(0))) } -func builtinArray_map(call FunctionCall) Value { +func builtinArrayMap(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) values := make([]Value, length) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { values[index] = iterator.call(call.runtime, callThis, thisObject.get(key), index, this) } else { values[index] = Value{} } } - return toValue_object(call.runtime.newArrayOf(values)) + return objectValue(call.runtime.newArrayOf(values)) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.foreach %q if not callable", call.Argument(0))) } -func builtinArray_filter(call FunctionCall) Value { +func builtinArrayFilter(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) values := make([]Value, 0) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { value := thisObject.get(key) if iterator.call(call.runtime, callThis, value, index, this).bool() { @@ -614,18 +612,18 @@ func builtinArray_filter(call FunctionCall) Value { } } } - return toValue_object(call.runtime.newArrayOf(values)) + return objectValue(call.runtime.newArrayOf(values)) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.filter %q if not callable", call.Argument(0))) } -func builtinArray_reduce(call FunctionCall) Value { +func builtinArrayReduce(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { initial := len(call.ArgumentList) > 1 start := call.Argument(1) - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) index := int64(0) if length > 0 || initial { var accumulator Value @@ -634,6 +632,7 @@ func builtinArray_reduce(call FunctionCall) Value { if key := arrayIndexToString(index); thisObject.hasProperty(key) { accumulator = thisObject.get(key) index++ + break } } @@ -642,22 +641,22 @@ func builtinArray_reduce(call FunctionCall) Value { } for ; index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - accumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), key, this) + accumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), index, this) } } return accumulator } } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.reduce %q if not callable", call.Argument(0))) } -func builtinArray_reduceRight(call FunctionCall) Value { +func builtinArrayReduceRight(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { initial := len(call.ArgumentList) > 1 start := call.Argument(1) - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) if length > 0 || initial { index := length - 1 var accumulator Value @@ -680,5 +679,5 @@ func builtinArray_reduceRight(call FunctionCall) Value { return accumulator } } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.reduceRight %q if not callable", call.Argument(0))) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_boolean.go b/vendor/github.com/robertkrimen/otto/builtin_boolean.go index 59b8e789b..54f02028f 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_boolean.go +++ b/vendor/github.com/robertkrimen/otto/builtin_boolean.go @@ -3,26 +3,26 @@ package otto // Boolean func builtinBoolean(call FunctionCall) Value { - return toValue_bool(call.Argument(0).bool()) + return boolValue(call.Argument(0).bool()) } -func builtinNewBoolean(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) +func builtinNewBoolean(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) } -func builtinBoolean_toString(call FunctionCall) Value { +func builtinBooleanToString(call FunctionCall) Value { value := call.This if !value.IsBoolean() { // Will throw a TypeError if ThisObject is not a Boolean - value = call.thisClassObject("Boolean").primitiveValue() + value = call.thisClassObject(classBooleanName).primitiveValue() } - return toValue_string(value.string()) + return stringValue(value.string()) } -func builtinBoolean_valueOf(call FunctionCall) Value { +func builtinBooleanValueOf(call FunctionCall) Value { value := call.This if !value.IsBoolean() { - value = call.thisClassObject("Boolean").primitiveValue() + value = call.thisClassObject(classBooleanName).primitiveValue() } return value } diff --git a/vendor/github.com/robertkrimen/otto/builtin_date.go b/vendor/github.com/robertkrimen/otto/builtin_date.go index f20bf8e3f..01822edaf 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_date.go +++ b/vendor/github.com/robertkrimen/otto/builtin_date.go @@ -2,114 +2,118 @@ package otto import ( "math" - Time "time" + "time" ) // Date const ( // TODO Be like V8? - // builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)" - builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" - builtinDate_goDateLayout = "Mon, 02 Jan 2006" - builtinDate_goTimeLayout = "15:04:05 MST" + // builtinDateDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)". + builtinDateDateTimeLayout = time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" + builtinDateDateLayout = "Mon, 02 Jan 2006" + builtinDateTimeLayout = "15:04:05 MST" ) +// utcTimeZone is the time zone used for UTC calculations. +// It is GMT not UTC as that's what Javascript does because toUTCString is +// actually an alias to toGMTString. +var utcTimeZone = time.FixedZone("GMT", 0) + func builtinDate(call FunctionCall) Value { - date := &_dateObject{} - date.Set(newDateTime([]Value{}, Time.Local)) - return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) + date := &dateObject{} + date.Set(newDateTime([]Value{}, time.Local)) //nolint:gosmopolitan + return stringValue(date.Time().Format(builtinDateDateTimeLayout)) } -func builtinNewDate(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local))) +func builtinNewDate(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newDate(newDateTime(argumentList, time.Local))) //nolint:gosmopolitan } -func builtinDate_toString(call FunctionCall) Value { +func builtinDateToString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().Local().Format(builtinDateDateTimeLayout)) //nolint:gosmopolitan } -func builtinDate_toDateString(call FunctionCall) Value { +func builtinDateToDateString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goDateLayout)) + return stringValue(date.Time().Local().Format(builtinDateDateLayout)) //nolint:gosmopolitan } -func builtinDate_toTimeString(call FunctionCall) Value { +func builtinDateToTimeString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goTimeLayout)) + return stringValue(date.Time().Local().Format(builtinDateTimeLayout)) //nolint:gosmopolitan } -func builtinDate_toUTCString(call FunctionCall) Value { +func builtinDateToUTCString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().In(utcTimeZone).Format(builtinDateDateTimeLayout)) } -func builtinDate_toISOString(call FunctionCall) Value { +func builtinDateToISOString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format("2006-01-02T15:04:05.000Z")) + return stringValue(date.Time().Format("2006-01-02T15:04:05.000Z")) } -func builtinDate_toJSON(call FunctionCall) Value { - object := call.thisObject() - value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue - { // FIXME value.isFinite - value := value.float64() - if math.IsNaN(value) || math.IsInf(value, 0) { - return nullValue - } +func builtinDateToJSON(call FunctionCall) Value { + obj := call.thisObject() + value := obj.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue + // FIXME fv.isFinite + if fv := value.float64(); math.IsNaN(fv) || math.IsInf(fv, 0) { + return nullValue } - toISOString := object.get("toISOString") + + toISOString := obj.get("toISOString") if !toISOString.isCallable() { // FIXME - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Date.toJSON toISOString %q is not callable", toISOString)) } - return toISOString.call(call.runtime, toValue_object(object), []Value{}) + return toISOString.call(call.runtime, objectValue(obj), []Value{}) } -func builtinDate_toGMTString(call FunctionCall) Value { +func builtinDateToGMTString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) + return stringValue(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) } -func builtinDate_getTime(call FunctionCall) Value { +func builtinDateGetTime(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } // We do this (convert away from a float) so the user // does not get something back in exponential notation - return toValue_int64(int64(date.Epoch())) + return int64Value(date.Epoch()) } -func builtinDate_setTime(call FunctionCall) Value { - object := call.thisObject() +func builtinDateSetTime(call FunctionCall) Value { + obj := call.thisObject() date := dateObjectOf(call.runtime, call.thisObject()) date.Set(call.Argument(0).float64()) - object.value = date + obj.value = date return date.Value() } -func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) { - object := call.thisObject() +func builtinDateBeforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*object, *dateObject, *ecmaTime, []int) { + obj := call.thisObject() date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return nil, nil, nil, nil @@ -120,72 +124,72 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool } if argumentLimit == 0 { - object.value = invalidDateObject + obj.value = invalidDateObject return nil, nil, nil, nil } valueList := make([]int, argumentLimit) - for index := 0; index < argumentLimit; index++ { + for index := range argumentLimit { value := call.ArgumentList[index] nm := value.number() switch nm.kind { case numberInteger, numberFloat: default: - object.value = invalidDateObject + obj.value = invalidDateObject return nil, nil, nil, nil } valueList[index] = int(nm.int64) } baseTime := date.Time() if timeLocal { - baseTime = baseTime.Local() + baseTime = baseTime.Local() //nolint:gosmopolitan } - ecmaTime := ecmaTime(baseTime) - return object, &date, &ecmaTime, valueList + ecmaTime := newEcmaTime(baseTime) + return obj, &date, &ecmaTime, valueList } -func builtinDate_parse(call FunctionCall) Value { +func builtinDateParse(call FunctionCall) Value { date := call.Argument(0).string() - return toValue_float64(dateParse(date)) + return float64Value(dateParse(date)) } -func builtinDate_UTC(call FunctionCall) Value { - return toValue_float64(newDateTime(call.ArgumentList, Time.UTC)) +func builtinDateUTC(call FunctionCall) Value { + return float64Value(newDateTime(call.ArgumentList, time.UTC)) } -func builtinDate_now(call FunctionCall) Value { +func builtinDateNow(call FunctionCall) Value { call.ArgumentList = []Value(nil) - return builtinDate_UTC(call) + return builtinDateUTC(call) } -// This is a placeholder -func builtinDate_toLocaleString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("2006-01-02 15:04:05")) + return stringValue(date.Time().Local().Format("2006-01-02 15:04:05")) //nolint:gosmopolitan } -// This is a placeholder -func builtinDate_toLocaleDateString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleDateString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("2006-01-02")) + return stringValue(date.Time().Local().Format("2006-01-02")) //nolint:gosmopolitan } -// This is a placeholder -func builtinDate_toLocaleTimeString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleTimeString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("15:04:05")) + return stringValue(date.Time().Local().Format("15:04:05")) //nolint:gosmopolitan } -func builtinDate_valueOf(call FunctionCall) Value { +func builtinDateValueOf(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() @@ -193,155 +197,155 @@ func builtinDate_valueOf(call FunctionCall) Value { return date.Value() } -func builtinDate_getYear(call FunctionCall) Value { +func builtinDateGetYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Year() - 1900) + return intValue(date.Time().Local().Year() - 1900) //nolint:gosmopolitan } -func builtinDate_getFullYear(call FunctionCall) Value { +func builtinDateGetFullYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Year()) + return intValue(date.Time().Local().Year()) //nolint:gosmopolitan } -func builtinDate_getUTCFullYear(call FunctionCall) Value { +func builtinDateGetUTCFullYear(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Year()) + return intValue(date.Time().Year()) } -func builtinDate_getMonth(call FunctionCall) Value { +func builtinDateGetMonth(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoMonth(date.Time().Local().Month())) + return intValue(dateFromGoMonth(date.Time().Local().Month())) //nolint:gosmopolitan } -func builtinDate_getUTCMonth(call FunctionCall) Value { +func builtinDateGetUTCMonth(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoMonth(date.Time().Month())) + return intValue(dateFromGoMonth(date.Time().Month())) } -func builtinDate_getDate(call FunctionCall) Value { +func builtinDateGetDate(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Day()) + return intValue(date.Time().Local().Day()) //nolint:gosmopolitan } -func builtinDate_getUTCDate(call FunctionCall) Value { +func builtinDateGetUTCDate(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Day()) + return intValue(date.Time().Day()) } -func builtinDate_getDay(call FunctionCall) Value { +func builtinDateGetDay(call FunctionCall) Value { // Actually day of the week date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoDay(date.Time().Local().Weekday())) + return intValue(dateFromGoDay(date.Time().Local().Weekday())) //nolint:gosmopolitan } -func builtinDate_getUTCDay(call FunctionCall) Value { +func builtinDateGetUTCDay(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoDay(date.Time().Weekday())) + return intValue(dateFromGoDay(date.Time().Weekday())) } -func builtinDate_getHours(call FunctionCall) Value { +func builtinDateGetHours(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Hour()) + return intValue(date.Time().Local().Hour()) //nolint:gosmopolitan } -func builtinDate_getUTCHours(call FunctionCall) Value { +func builtinDateGetUTCHours(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Hour()) + return intValue(date.Time().Hour()) } -func builtinDate_getMinutes(call FunctionCall) Value { +func builtinDateGetMinutes(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Minute()) + return intValue(date.Time().Local().Minute()) //nolint:gosmopolitan } -func builtinDate_getUTCMinutes(call FunctionCall) Value { +func builtinDateGetUTCMinutes(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Minute()) + return intValue(date.Time().Minute()) } -func builtinDate_getSeconds(call FunctionCall) Value { +func builtinDateGetSeconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Second()) + return intValue(date.Time().Local().Second()) //nolint:gosmopolitan } -func builtinDate_getUTCSeconds(call FunctionCall) Value { +func builtinDateGetUTCSeconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Second()) + return intValue(date.Time().Second()) } -func builtinDate_getMilliseconds(call FunctionCall) Value { +func builtinDateGetMilliseconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Nanosecond() / (100 * 100 * 100)) + return intValue(date.Time().Local().Nanosecond() / (100 * 100 * 100)) //nolint:gosmopolitan } -func builtinDate_getUTCMilliseconds(call FunctionCall) Value { +func builtinDateGetUTCMilliseconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Nanosecond() / (100 * 100 * 100)) + return intValue(date.Time().Nanosecond() / (100 * 100 * 100)) } -func builtinDate_getTimezoneOffset(call FunctionCall) Value { +func builtinDateGetTimezoneOffset(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - timeLocal := date.Time().Local() + timeLocal := date.Time().Local() //nolint:gosmopolitan // Is this kosher? - timeLocalAsUTC := Time.Date( + timeLocalAsUTC := time.Date( timeLocal.Year(), timeLocal.Month(), timeLocal.Day(), @@ -349,13 +353,13 @@ func builtinDate_getTimezoneOffset(call FunctionCall) Value { timeLocal.Minute(), timeLocal.Second(), timeLocal.Nanosecond(), - Time.UTC, + time.UTC, ) - return toValue_float64(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) + return float64Value(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) } -func builtinDate_setMilliseconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetMilliseconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -363,12 +367,12 @@ func builtinDate_setMilliseconds(call FunctionCall) Value { ecmaTime.millisecond = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMilliseconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) +func builtinDateSetUTCMilliseconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false) if ecmaTime == nil { return NaNValue() } @@ -376,12 +380,12 @@ func builtinDate_setUTCMilliseconds(call FunctionCall) Value { ecmaTime.millisecond = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setSeconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) +func builtinDateSetSeconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true) if ecmaTime == nil { return NaNValue() } @@ -392,12 +396,12 @@ func builtinDate_setSeconds(call FunctionCall) Value { ecmaTime.second = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCSeconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) +func builtinDateSetUTCSeconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false) if ecmaTime == nil { return NaNValue() } @@ -408,12 +412,12 @@ func builtinDate_setUTCSeconds(call FunctionCall) Value { ecmaTime.second = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setMinutes(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) +func builtinDateSetMinutes(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true) if ecmaTime == nil { return NaNValue() } @@ -427,12 +431,12 @@ func builtinDate_setMinutes(call FunctionCall) Value { ecmaTime.minute = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMinutes(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) +func builtinDateSetUTCMinutes(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false) if ecmaTime == nil { return NaNValue() } @@ -446,58 +450,58 @@ func builtinDate_setUTCMinutes(call FunctionCall) Value { ecmaTime.minute = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setHours(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true) +func builtinDateSetHours(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, true) if ecmaTime == nil { return NaNValue() } - if len(value) > 3 { + switch { + case len(value) > 3: ecmaTime.millisecond = value[3] + fallthrough + case len(value) > 2: ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 2 { - ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 1 { + fallthrough + case len(value) > 1: ecmaTime.minute = value[1] } ecmaTime.hour = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCHours(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false) +func builtinDateSetUTCHours(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, false) if ecmaTime == nil { return NaNValue() } - if len(value) > 3 { + switch { + case len(value) > 3: ecmaTime.millisecond = value[3] + fallthrough + case len(value) > 2: ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 2 { - ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 1 { + fallthrough + case len(value) > 1: ecmaTime.minute = value[1] } ecmaTime.hour = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setDate(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetDate(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -505,12 +509,12 @@ func builtinDate_setDate(call FunctionCall) Value { ecmaTime.day = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCDate(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) +func builtinDateSetUTCDate(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false) if ecmaTime == nil { return NaNValue() } @@ -518,12 +522,12 @@ func builtinDate_setUTCDate(call FunctionCall) Value { ecmaTime.day = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setMonth(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) +func builtinDateSetMonth(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true) if ecmaTime == nil { return NaNValue() } @@ -534,12 +538,12 @@ func builtinDate_setMonth(call FunctionCall) Value { ecmaTime.month = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMonth(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) +func builtinDateSetUTCMonth(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false) if ecmaTime == nil { return NaNValue() } @@ -550,12 +554,12 @@ func builtinDate_setUTCMonth(call FunctionCall) Value { ecmaTime.month = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -567,12 +571,12 @@ func builtinDate_setYear(call FunctionCall) Value { ecmaTime.year = year date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setFullYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) +func builtinDateSetFullYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true) if ecmaTime == nil { return NaNValue() } @@ -586,12 +590,12 @@ func builtinDate_setFullYear(call FunctionCall) Value { ecmaTime.year = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCFullYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) +func builtinDateSetUTCFullYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false) if ecmaTime == nil { return NaNValue() } @@ -605,7 +609,7 @@ func builtinDate_setUTCFullYear(call FunctionCall) Value { ecmaTime.year = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } diff --git a/vendor/github.com/robertkrimen/otto/builtin_error.go b/vendor/github.com/robertkrimen/otto/builtin_error.go index 41da84ef2..9d524f548 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_error.go +++ b/vendor/github.com/robertkrimen/otto/builtin_error.go @@ -5,20 +5,20 @@ import ( ) func builtinError(call FunctionCall) Value { - return toValue_object(call.runtime.newError("Error", call.Argument(0), 1)) + return objectValue(call.runtime.newError(classErrorName, call.Argument(0), 1)) } -func builtinNewError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newError("Error", valueOfArrayIndex(argumentList, 0), 0)) +func builtinNewError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newError(classErrorName, valueOfArrayIndex(argumentList, 0), 0)) } -func builtinError_toString(call FunctionCall) Value { +func builtinErrorToString(call FunctionCall) Value { thisObject := call.thisObject() if thisObject == nil { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Error.toString is nil")) } - name := "Error" + name := classErrorName nameValue := thisObject.get("name") if nameValue.IsDefined() { name = nameValue.string() @@ -31,96 +31,96 @@ func builtinError_toString(call FunctionCall) Value { } if len(name) == 0 { - return toValue_string(message) + return stringValue(message) } if len(message) == 0 { - return toValue_string(name) + return stringValue(name) } - return toValue_string(fmt.Sprintf("%s: %s", name, message)) + return stringValue(fmt.Sprintf("%s: %s", name, message)) } -func (runtime *_runtime) newEvalError(message Value) *_object { - self := runtime.newErrorObject("EvalError", message, 0) - self.prototype = runtime.global.EvalErrorPrototype - return self +func (rt *runtime) newEvalError(message Value) *object { + o := rt.newErrorObject("EvalError", message, 0) + o.prototype = rt.global.EvalErrorPrototype + return o } func builtinEvalError(call FunctionCall) Value { - return toValue_object(call.runtime.newEvalError(call.Argument(0))) + return objectValue(call.runtime.newEvalError(call.Argument(0))) } -func builtinNewEvalError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) +func builtinNewEvalError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newTypeError(message Value) *_object { - self := runtime.newErrorObject("TypeError", message, 0) - self.prototype = runtime.global.TypeErrorPrototype - return self +func (rt *runtime) newTypeError(message Value) *object { + o := rt.newErrorObject("TypeError", message, 0) + o.prototype = rt.global.TypeErrorPrototype + return o } func builtinTypeError(call FunctionCall) Value { - return toValue_object(call.runtime.newTypeError(call.Argument(0))) + return objectValue(call.runtime.newTypeError(call.Argument(0))) } -func builtinNewTypeError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) +func builtinNewTypeError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newRangeError(message Value) *_object { - self := runtime.newErrorObject("RangeError", message, 0) - self.prototype = runtime.global.RangeErrorPrototype - return self +func (rt *runtime) newRangeError(message Value) *object { + o := rt.newErrorObject("RangeError", message, 0) + o.prototype = rt.global.RangeErrorPrototype + return o } func builtinRangeError(call FunctionCall) Value { - return toValue_object(call.runtime.newRangeError(call.Argument(0))) + return objectValue(call.runtime.newRangeError(call.Argument(0))) } -func builtinNewRangeError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) +func builtinNewRangeError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newURIError(message Value) *_object { - self := runtime.newErrorObject("URIError", message, 0) - self.prototype = runtime.global.URIErrorPrototype - return self +func (rt *runtime) newURIError(message Value) *object { + o := rt.newErrorObject("URIError", message, 0) + o.prototype = rt.global.URIErrorPrototype + return o } -func (runtime *_runtime) newReferenceError(message Value) *_object { - self := runtime.newErrorObject("ReferenceError", message, 0) - self.prototype = runtime.global.ReferenceErrorPrototype - return self +func (rt *runtime) newReferenceError(message Value) *object { + o := rt.newErrorObject("ReferenceError", message, 0) + o.prototype = rt.global.ReferenceErrorPrototype + return o } func builtinReferenceError(call FunctionCall) Value { - return toValue_object(call.runtime.newReferenceError(call.Argument(0))) + return objectValue(call.runtime.newReferenceError(call.Argument(0))) } -func builtinNewReferenceError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) +func builtinNewReferenceError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newSyntaxError(message Value) *_object { - self := runtime.newErrorObject("SyntaxError", message, 0) - self.prototype = runtime.global.SyntaxErrorPrototype - return self +func (rt *runtime) newSyntaxError(message Value) *object { + o := rt.newErrorObject("SyntaxError", message, 0) + o.prototype = rt.global.SyntaxErrorPrototype + return o } func builtinSyntaxError(call FunctionCall) Value { - return toValue_object(call.runtime.newSyntaxError(call.Argument(0))) + return objectValue(call.runtime.newSyntaxError(call.Argument(0))) } -func builtinNewSyntaxError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) +func builtinNewSyntaxError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) } func builtinURIError(call FunctionCall) Value { - return toValue_object(call.runtime.newURIError(call.Argument(0))) + return objectValue(call.runtime.newURIError(call.Argument(0))) } -func builtinNewURIError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) +func builtinNewURIError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_function.go b/vendor/github.com/robertkrimen/otto/builtin_function.go index 3d07566c6..4149ce4f2 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_function.go +++ b/vendor/github.com/robertkrimen/otto/builtin_function.go @@ -2,7 +2,6 @@ package otto import ( "fmt" - "regexp" "strings" "unicode" @@ -12,11 +11,11 @@ import ( // Function func builtinFunction(call FunctionCall) Value { - return toValue_object(builtinNewFunctionNative(call.runtime, call.ArgumentList)) + return objectValue(builtinNewFunctionNative(call.runtime, call.ArgumentList)) } -func builtinNewFunction(self *_object, argumentList []Value) Value { - return toValue_object(builtinNewFunctionNative(self.runtime, argumentList)) +func builtinNewFunction(obj *object, argumentList []Value) Value { + return objectValue(builtinNewFunctionNative(obj.runtime, argumentList)) } func argumentList2parameterList(argumentList []Value) []string { @@ -30,12 +29,9 @@ func argumentList2parameterList(argumentList []Value) []string { return parameterList } -var matchIdentifier = regexp.MustCompile(`^[$_\p{L}][$_\p{L}\d}]*$`) - -func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object { +func builtinNewFunctionNative(rt *runtime, argumentList []Value) *object { var parameterList, body string - count := len(argumentList) - if count > 0 { + if count := len(argumentList); count > 0 { tmp := make([]string, 0, count-1) for _, value := range argumentList[0 : count-1] { tmp = append(tmp, value.string()) @@ -46,35 +42,35 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object // FIXME function, err := parser.ParseFunction(parameterList, body) - runtime.parseThrow(err) // Will panic/throw appropriately - cmpl := _compiler{} - cmpl_function := cmpl.parseExpression(function) + rt.parseThrow(err) // Will panic/throw appropriately + cmpl := compiler{} + cmplFunction := cmpl.parseExpression(function) - return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.globalStash) + return rt.newNodeFunction(cmplFunction.(*nodeFunctionLiteral), rt.globalStash) } -func builtinFunction_toString(call FunctionCall) Value { - object := call.thisClassObject("Function") // Should throw a TypeError unless Function - switch fn := object.value.(type) { - case _nativeFunctionObject: - return toValue_string(fmt.Sprintf("function %s() { [native code] }", fn.name)) - case _nodeFunctionObject: - return toValue_string(fn.node.source) - case _bindFunctionObject: - return toValue_string("function () { [native code] }") +func builtinFunctionToString(call FunctionCall) Value { + obj := call.thisClassObject(classFunctionName) // Should throw a TypeError unless Function + switch fn := obj.value.(type) { + case nativeFunctionObject: + return stringValue(fmt.Sprintf("function %s() { [native code] }", fn.name)) + case nodeFunctionObject: + return stringValue(fn.node.source) + case bindFunctionObject: + return stringValue("function () { [native code] }") + default: + panic(call.runtime.panicTypeError("Function.toString unknown type %T", obj.value)) } - - panic(call.runtime.panicTypeError("Function.toString()")) } -func builtinFunction_apply(call FunctionCall) Value { +func builtinFunctionApply(call FunctionCall) Value { if !call.This.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.apply %q is not callable", call.This)) } this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } argumentList := call.Argument(1) switch argumentList.kind { @@ -82,28 +78,28 @@ func builtinFunction_apply(call FunctionCall) Value { return call.thisObject().call(this, nil, false, nativeFrame) case valueObject: default: - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.apply unknown type %T for second argument")) } - arrayObject := argumentList._object() + arrayObject := argumentList.object() thisObject := call.thisObject() - length := int64(toUint32(arrayObject.get("length"))) + length := int64(toUint32(arrayObject.get(propertyLength))) valueArray := make([]Value, length) - for index := int64(0); index < length; index++ { + for index := range length { valueArray[index] = arrayObject.get(arrayIndexToString(index)) } return thisObject.call(this, valueArray, false, nativeFrame) } -func builtinFunction_call(call FunctionCall) Value { +func builtinFunctionCall(call FunctionCall) Value { if !call.This.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.call %q is not callable", call.This)) } thisObject := call.thisObject() this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } if len(call.ArgumentList) >= 1 { return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame) @@ -111,19 +107,19 @@ func builtinFunction_call(call FunctionCall) Value { return thisObject.call(this, nil, false, nativeFrame) } -func builtinFunction_bind(call FunctionCall) Value { +func builtinFunctionBind(call FunctionCall) Value { target := call.This if !target.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.bind %q is not callable", call.This)) } - targetObject := target._object() + targetObject := target.object() this := call.Argument(0) argumentList := call.slice(1) if this.IsUndefined() { // FIXME Do this elsewhere? - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } - return toValue_object(call.runtime.newBoundFunction(targetObject, this, argumentList)) + return objectValue(call.runtime.newBoundFunction(targetObject, this, argumentList)) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_json.go b/vendor/github.com/robertkrimen/otto/builtin_json.go index aed54bf12..f66315d85 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_json.go +++ b/vendor/github.com/robertkrimen/otto/builtin_json.go @@ -7,13 +7,13 @@ import ( "strings" ) -type _builtinJSON_parseContext struct { - call FunctionCall +type builtinJSONParseContext struct { reviver Value + call FunctionCall } -func builtinJSON_parse(call FunctionCall) Value { - ctx := _builtinJSON_parseContext{ +func builtinJSONParse(call FunctionCall) Value { + ctx := builtinJSONParseContext{ call: call, } revive := false @@ -27,109 +27,107 @@ func builtinJSON_parse(call FunctionCall) Value { if err != nil { panic(call.runtime.panicSyntaxError(err.Error())) } - value, exists := builtinJSON_parseWalk(ctx, root) + value, exists := builtinJSONParseWalk(ctx, root) if !exists { value = Value{} } if revive { root := ctx.call.runtime.newObject() root.put("", value, false) - return builtinJSON_reviveWalk(ctx, root, "") + return builtinJSONReviveWalk(ctx, root, "") } return value } -func builtinJSON_reviveWalk(ctx _builtinJSON_parseContext, holder *_object, name string) Value { +func builtinJSONReviveWalk(ctx builtinJSONParseContext, holder *object, name string) Value { value := holder.get(name) - if object := value._object(); object != nil { - if isArray(object) { - length := int64(objectLength(object)) - for index := int64(0); index < length; index += 1 { - name := arrayIndexToString(index) - value := builtinJSON_reviveWalk(ctx, object, name) - if value.IsUndefined() { - object.delete(name, false) + if obj := value.object(); obj != nil { + if isArray(obj) { + length := int64(objectLength(obj)) + for index := range length { + idxName := arrayIndexToString(index) + idxValue := builtinJSONReviveWalk(ctx, obj, idxName) + if idxValue.IsUndefined() { + obj.delete(idxName, false) } else { - object.defineProperty(name, value, 0111, false) + obj.defineProperty(idxName, idxValue, 0o111, false) } } } else { - object.enumerate(false, func(name string) bool { - value := builtinJSON_reviveWalk(ctx, object, name) - if value.IsUndefined() { - object.delete(name, false) + obj.enumerate(false, func(name string) bool { + enumVal := builtinJSONReviveWalk(ctx, obj, name) + if enumVal.IsUndefined() { + obj.delete(name, false) } else { - object.defineProperty(name, value, 0111, false) + obj.defineProperty(name, enumVal, 0o111, false) } return true }) } } - return ctx.reviver.call(ctx.call.runtime, toValue_object(holder), name, value) + return ctx.reviver.call(ctx.call.runtime, objectValue(holder), name, value) } -func builtinJSON_parseWalk(ctx _builtinJSON_parseContext, rawValue interface{}) (Value, bool) { +func builtinJSONParseWalk(ctx builtinJSONParseContext, rawValue interface{}) (Value, bool) { switch value := rawValue.(type) { case nil: return nullValue, true case bool: - return toValue_bool(value), true + return boolValue(value), true case string: - return toValue_string(value), true + return stringValue(value), true case float64: - return toValue_float64(value), true + return float64Value(value), true case []interface{}: arrayValue := make([]Value, len(value)) for index, rawValue := range value { - if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists { + if value, exists := builtinJSONParseWalk(ctx, rawValue); exists { arrayValue[index] = value } } - return toValue_object(ctx.call.runtime.newArrayOf(arrayValue)), true + return objectValue(ctx.call.runtime.newArrayOf(arrayValue)), true case map[string]interface{}: - object := ctx.call.runtime.newObject() + obj := ctx.call.runtime.newObject() for name, rawValue := range value { - if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists { - object.put(name, value, false) + if value, exists := builtinJSONParseWalk(ctx, rawValue); exists { + obj.put(name, value, false) } } - return toValue_object(object), true + return objectValue(obj), true } return Value{}, false } -type _builtinJSON_stringifyContext struct { - call FunctionCall - stack []*_object - propertyList []string +type builtinJSONStringifyContext struct { replacerFunction *Value gap string + stack []*object + propertyList []string + call FunctionCall } -func builtinJSON_stringify(call FunctionCall) Value { - ctx := _builtinJSON_stringifyContext{ +func builtinJSONStringify(call FunctionCall) Value { + ctx := builtinJSONStringifyContext{ call: call, - stack: []*_object{nil}, + stack: []*object{nil}, } - replacer := call.Argument(1)._object() + replacer := call.Argument(1).object() if replacer != nil { if isArray(replacer) { length := objectLength(replacer) seen := map[string]bool{} propertyList := make([]string, length) length = 0 - for index, _ := range propertyList { + for index := range propertyList { value := replacer.get(arrayIndexToString(int64(index))) switch value.kind { case valueObject: - switch value.value.(*_object).class { - case "String": - case "Number": + switch value.value.(*object).class { + case classStringName, classNumberName: default: continue } - case valueString: - case valueNumber: + case valueString, valueNumber: default: continue } @@ -138,21 +136,21 @@ func builtinJSON_stringify(call FunctionCall) Value { continue } seen[name] = true - length += 1 + length++ propertyList[index] = name } ctx.propertyList = propertyList[0:length] - } else if replacer.class == "Function" { - value := toValue_object(replacer) + } else if replacer.class == classFunctionName { + value := objectValue(replacer) ctx.replacerFunction = &value } } if spaceValue, exists := call.getArgument(2); exists { if spaceValue.kind == valueObject { - switch spaceValue.value.(*_object).class { - case "String": - spaceValue = toValue_string(spaceValue.string()) - case "Number": + switch spaceValue.value.(*object).class { + case classStringName: + spaceValue = stringValue(spaceValue.string()) + case classNumberName: spaceValue = spaceValue.numberValue() } } @@ -176,51 +174,51 @@ func builtinJSON_stringify(call FunctionCall) Value { } holder := call.runtime.newObject() holder.put("", call.Argument(0), false) - value, exists := builtinJSON_stringifyWalk(ctx, "", holder) + value, exists := builtinJSONStringifyWalk(ctx, "", holder) if !exists { return Value{} } valueJSON, err := json.Marshal(value) if err != nil { - panic(call.runtime.panicTypeError(err.Error())) + panic(call.runtime.panicTypeError("JSON.stringify marshal: %s", err)) } if ctx.gap != "" { valueJSON1 := bytes.Buffer{} - json.Indent(&valueJSON1, valueJSON, "", ctx.gap) + if err = json.Indent(&valueJSON1, valueJSON, "", ctx.gap); err != nil { + panic(call.runtime.panicTypeError("JSON.stringify indent: %s", err)) + } valueJSON = valueJSON1.Bytes() } - return toValue_string(string(valueJSON)) + return stringValue(string(valueJSON)) } -func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, holder *_object) (interface{}, bool) { +func builtinJSONStringifyWalk(ctx builtinJSONStringifyContext, key string, holder *object) (interface{}, bool) { value := holder.get(key) if value.IsObject() { - object := value._object() - if toJSON := object.get("toJSON"); toJSON.IsFunction() { + obj := value.object() + if toJSON := obj.get("toJSON"); toJSON.IsFunction() { value = toJSON.call(ctx.call.runtime, value, key) - } else { + } else if obj.objectClass.marshalJSON != nil { // If the object is a GoStruct or something that implements json.Marshaler - if object.objectClass.marshalJSON != nil { - marshaler := object.objectClass.marshalJSON(object) - if marshaler != nil { - return marshaler, true - } + marshaler := obj.objectClass.marshalJSON(obj) + if marshaler != nil { + return marshaler, true } } } if ctx.replacerFunction != nil { - value = (*ctx.replacerFunction).call(ctx.call.runtime, toValue_object(holder), key, value) + value = ctx.replacerFunction.call(ctx.call.runtime, objectValue(holder), key, value) } if value.kind == valueObject { - switch value.value.(*_object).class { - case "Boolean": - value = value._object().value.(Value) - case "String": - value = toValue_string(value.string()) - case "Number": + switch value.value.(*object).class { + case classBooleanName: + value = value.object().value.(Value) + case classStringName: + value = stringValue(value.string()) + case classNumberName: value = value.numberValue() } } @@ -243,19 +241,19 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho case valueNull: return nil, true case valueObject: - holder := value._object() - if value := value._object(); nil != value { - for _, object := range ctx.stack { - if holder == object { + objHolder := value.object() + if value := value.object(); nil != value { + for _, obj := range ctx.stack { + if objHolder == obj { panic(ctx.call.runtime.panicTypeError("Converting circular structure to JSON")) } } ctx.stack = append(ctx.stack, value) defer func() { ctx.stack = ctx.stack[:len(ctx.stack)-1] }() } - if isArray(holder) { + if isArray(objHolder) { var length uint32 - switch value := holder.get("length").value.(type) { + switch value := objHolder.get(propertyLength).value.(type) { case uint32: length = value case int: @@ -266,33 +264,33 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho panic(ctx.call.runtime.panicTypeError(fmt.Sprintf("JSON.stringify: invalid length: %v (%[1]T)", value))) } array := make([]interface{}, length) - for index, _ := range array { + for index := range array { name := arrayIndexToString(int64(index)) - value, _ := builtinJSON_stringifyWalk(ctx, name, holder) + value, _ := builtinJSONStringifyWalk(ctx, name, objHolder) array[index] = value } return array, true - } else if holder.class != "Function" { - object := map[string]interface{}{} + } else if objHolder.class != classFunctionName { + obj := map[string]interface{}{} if ctx.propertyList != nil { for _, name := range ctx.propertyList { - value, exists := builtinJSON_stringifyWalk(ctx, name, holder) + value, exists := builtinJSONStringifyWalk(ctx, name, objHolder) if exists { - object[name] = value + obj[name] = value } } } else { // Go maps are without order, so this doesn't conform to the ECMA ordering // standard, but oh well... - holder.enumerate(false, func(name string) bool { - value, exists := builtinJSON_stringifyWalk(ctx, name, holder) + objHolder.enumerate(false, func(name string) bool { + value, exists := builtinJSONStringifyWalk(ctx, name, objHolder) if exists { - object[name] = value + obj[name] = value } return true }) } - return object, true + return obj, true } } return nil, false diff --git a/vendor/github.com/robertkrimen/otto/builtin_math.go b/vendor/github.com/robertkrimen/otto/builtin_math.go index 7ce90c339..6429aa5a5 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_math.go +++ b/vendor/github.com/robertkrimen/otto/builtin_math.go @@ -7,27 +7,37 @@ import ( // Math -func builtinMath_abs(call FunctionCall) Value { +func builtinMathAbs(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Abs(number)) + return float64Value(math.Abs(number)) } -func builtinMath_acos(call FunctionCall) Value { +func builtinMathAcos(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Acos(number)) + return float64Value(math.Acos(number)) } -func builtinMath_asin(call FunctionCall) Value { +func builtinMathAcosh(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Asin(number)) + return float64Value(math.Acosh(number)) } -func builtinMath_atan(call FunctionCall) Value { +func builtinMathAsin(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Atan(number)) + return float64Value(math.Asin(number)) } -func builtinMath_atan2(call FunctionCall) Value { +func builtinMathAsinh(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Asinh(number)) +} + +func builtinMathAtan(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Atan(number)) +} + +func builtinMathAtan2(call FunctionCall) Value { y := call.Argument(0).float64() if math.IsNaN(y) { return NaNValue() @@ -36,40 +46,75 @@ func builtinMath_atan2(call FunctionCall) Value { if math.IsNaN(x) { return NaNValue() } - return toValue_float64(math.Atan2(y, x)) + return float64Value(math.Atan2(y, x)) +} + +func builtinMathAtanh(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Atanh(number)) +} + +func builtinMathCbrt(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Cbrt(number)) +} + +func builtinMathCos(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Cos(number)) +} + +func builtinMathCeil(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Ceil(number)) } -func builtinMath_cos(call FunctionCall) Value { +func builtinMathCosh(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Cos(number)) + return float64Value(math.Cosh(number)) } -func builtinMath_ceil(call FunctionCall) Value { +func builtinMathExp(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Ceil(number)) + return float64Value(math.Exp(number)) } -func builtinMath_exp(call FunctionCall) Value { +func builtinMathExpm1(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Exp(number)) + return float64Value(math.Expm1(number)) } -func builtinMath_floor(call FunctionCall) Value { +func builtinMathFloor(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Floor(number)) + return float64Value(math.Floor(number)) } -func builtinMath_log(call FunctionCall) Value { +func builtinMathLog(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Log(number)) + return float64Value(math.Log(number)) } -func builtinMath_max(call FunctionCall) Value { +func builtinMathLog10(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Log10(number)) +} + +func builtinMathLog1p(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Log1p(number)) +} + +func builtinMathLog2(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Log2(number)) +} + +func builtinMathMax(call FunctionCall) Value { switch len(call.ArgumentList) { case 0: return negativeInfinityValue() case 1: - return toValue_float64(call.ArgumentList[0].float64()) + return float64Value(call.ArgumentList[0].float64()) } result := call.ArgumentList[0].float64() if math.IsNaN(result) { @@ -82,15 +127,15 @@ func builtinMath_max(call FunctionCall) Value { } result = math.Max(result, value) } - return toValue_float64(result) + return float64Value(result) } -func builtinMath_min(call FunctionCall) Value { +func builtinMathMin(call FunctionCall) Value { switch len(call.ArgumentList) { case 0: return positiveInfinityValue() case 1: - return toValue_float64(call.ArgumentList[0].float64()) + return float64Value(call.ArgumentList[0].float64()) } result := call.ArgumentList[0].float64() if math.IsNaN(result) { @@ -103,49 +148,64 @@ func builtinMath_min(call FunctionCall) Value { } result = math.Min(result, value) } - return toValue_float64(result) + return float64Value(result) } -func builtinMath_pow(call FunctionCall) Value { +func builtinMathPow(call FunctionCall) Value { // TODO Make sure this works according to the specification (15.8.2.13) x := call.Argument(0).float64() y := call.Argument(1).float64() if math.Abs(x) == 1 && math.IsInf(y, 0) { return NaNValue() } - return toValue_float64(math.Pow(x, y)) + return float64Value(math.Pow(x, y)) } -func builtinMath_random(call FunctionCall) Value { +func builtinMathRandom(call FunctionCall) Value { var v float64 if call.runtime.random != nil { v = call.runtime.random() } else { - v = rand.Float64() + v = rand.Float64() //nolint:gosec } - return toValue_float64(v) + return float64Value(v) } -func builtinMath_round(call FunctionCall) Value { +func builtinMathRound(call FunctionCall) Value { number := call.Argument(0).float64() value := math.Floor(number + 0.5) if value == 0 { value = math.Copysign(0, number) } - return toValue_float64(value) + return float64Value(value) +} + +func builtinMathSin(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Sin(number)) +} + +func builtinMathSinh(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Sinh(number)) +} + +func builtinMathSqrt(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Sqrt(number)) } -func builtinMath_sin(call FunctionCall) Value { +func builtinMathTan(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Sin(number)) + return float64Value(math.Tan(number)) } -func builtinMath_sqrt(call FunctionCall) Value { +func builtinMathTanh(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Sqrt(number)) + return float64Value(math.Tanh(number)) } -func builtinMath_tan(call FunctionCall) Value { +func builtinMathTrunc(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Tan(number)) + return float64Value(math.Trunc(number)) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_number.go b/vendor/github.com/robertkrimen/otto/builtin_number.go index f99a42a2f..acdeb501b 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_number.go +++ b/vendor/github.com/robertkrimen/otto/builtin_number.go @@ -3,6 +3,10 @@ package otto import ( "math" "strconv" + + "golang.org/x/text/language" + "golang.org/x/text/message" + "golang.org/x/text/number" ) // Number @@ -11,20 +15,20 @@ func numberValueFromNumberArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { return argumentList[0].numberValue() } - return toValue_int(0) + return intValue(0) } func builtinNumber(call FunctionCall) Value { return numberValueFromNumberArgumentList(call.ArgumentList) } -func builtinNewNumber(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) +func builtinNewNumber(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) } -func builtinNumber_toString(call FunctionCall) Value { +func builtinNumberToString(call FunctionCall) Value { // Will throw a TypeError if ThisObject is not a Number - value := call.thisClassObject("Number").primitiveValue() + value := call.thisClassObject(classNumberName).primitiveValue() radix := 10 radixArgument := call.Argument(0) if radixArgument.IsDefined() { @@ -35,33 +39,32 @@ func builtinNumber_toString(call FunctionCall) Value { radix = int(integer) } if radix == 10 { - return toValue_string(value.string()) + return stringValue(value.string()) } - return toValue_string(numberToStringRadix(value, radix)) + return stringValue(numberToStringRadix(value, radix)) } -func builtinNumber_valueOf(call FunctionCall) Value { - return call.thisClassObject("Number").primitiveValue() +func builtinNumberValueOf(call FunctionCall) Value { + return call.thisClassObject(classNumberName).primitiveValue() } -func builtinNumber_toFixed(call FunctionCall) Value { +func builtinNumberToFixed(call FunctionCall) Value { precision := toIntegerFloat(call.Argument(0)) if 20 < precision || 0 > precision { panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20")) } if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } - value := call.This.float64() - if math.Abs(value) >= 1e21 { - return toValue_string(floatToString(value, 64)) + if value := call.This.float64(); math.Abs(value) >= 1e21 { + return stringValue(floatToString(value, 64)) } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) } -func builtinNumber_toExponential(call FunctionCall) Value { +func builtinNumberToExponential(call FunctionCall) Value { if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } precision := float64(-1) if value := call.Argument(0); value.IsDefined() { @@ -70,24 +73,39 @@ func builtinNumber_toExponential(call FunctionCall) Value { panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36")) } } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) } -func builtinNumber_toPrecision(call FunctionCall) Value { +func builtinNumberToPrecision(call FunctionCall) Value { if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } value := call.Argument(0) if value.IsUndefined() { - return toValue_string(call.This.string()) + return stringValue(call.This.string()) } precision := toIntegerFloat(value) if 1 > precision { panic(call.runtime.panicRangeError("toPrecision() precision must be greater than 1")) } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) +} + +func builtinNumberIsNaN(call FunctionCall) Value { + if len(call.ArgumentList) < 1 { + return boolValue(false) + } + return boolValue(call.Argument(0).IsNaN()) } -func builtinNumber_toLocaleString(call FunctionCall) Value { - return builtinNumber_toString(call) +func builtinNumberToLocaleString(call FunctionCall) Value { + value := call.thisClassObject(classNumberName).primitiveValue() + locale := call.Argument(0) + lang := defaultLanguage + if locale.IsDefined() { + lang = language.MustParse(locale.string()) + } + + p := message.NewPrinter(lang) + return stringValue(p.Sprintf("%v", number.Decimal(value.value))) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_object.go b/vendor/github.com/robertkrimen/otto/builtin_object.go index c2433f7be..82da2cf9b 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_object.go +++ b/vendor/github.com/robertkrimen/otto/builtin_object.go @@ -10,36 +10,36 @@ func builtinObject(call FunctionCall) Value { value := call.Argument(0) switch value.kind { case valueUndefined, valueNull: - return toValue_object(call.runtime.newObject()) + return objectValue(call.runtime.newObject()) } - return toValue_object(call.runtime.toObject(value)) + return objectValue(call.runtime.toObject(value)) } -func builtinNewObject(self *_object, argumentList []Value) Value { +func builtinNewObject(obj *object, argumentList []Value) Value { value := valueOfArrayIndex(argumentList, 0) switch value.kind { case valueNull, valueUndefined: case valueNumber, valueString, valueBoolean: - return toValue_object(self.runtime.toObject(value)) + return objectValue(obj.runtime.toObject(value)) case valueObject: return value default: } - return toValue_object(self.runtime.newObject()) + return objectValue(obj.runtime.newObject()) } -func builtinObject_valueOf(call FunctionCall) Value { - return toValue_object(call.thisObject()) +func builtinObjectValueOf(call FunctionCall) Value { + return objectValue(call.thisObject()) } -func builtinObject_hasOwnProperty(call FunctionCall) Value { +func builtinObjectHasOwnProperty(call FunctionCall) Value { propertyName := call.Argument(0).string() thisObject := call.thisObject() - return toValue_bool(thisObject.hasOwnProperty(propertyName)) + return boolValue(thisObject.hasOwnProperty(propertyName)) } -func builtinObject_isPrototypeOf(call FunctionCall) Value { +func builtinObjectIsPrototypeOf(call FunctionCall) Value { value := call.Argument(0) if !value.IsObject() { return falseValue @@ -55,235 +55,246 @@ func builtinObject_isPrototypeOf(call FunctionCall) Value { return falseValue } -func builtinObject_propertyIsEnumerable(call FunctionCall) Value { +func builtinObjectPropertyIsEnumerable(call FunctionCall) Value { propertyName := call.Argument(0).string() thisObject := call.thisObject() - property := thisObject.getOwnProperty(propertyName) - if property != nil && property.enumerable() { + prop := thisObject.getOwnProperty(propertyName) + if prop != nil && prop.enumerable() { return trueValue } return falseValue } -func builtinObject_toString(call FunctionCall) Value { - result := "" - if call.This.IsUndefined() { +func builtinObjectToString(call FunctionCall) Value { + var result string + switch { + case call.This.IsUndefined(): result = "[object Undefined]" - } else if call.This.IsNull() { + case call.This.IsNull(): result = "[object Null]" - } else { + default: result = fmt.Sprintf("[object %s]", call.thisObject().class) } - return toValue_string(result) + return stringValue(result) } -func builtinObject_toLocaleString(call FunctionCall) Value { +func builtinObjectToLocaleString(call FunctionCall) Value { toString := call.thisObject().get("toString") if !toString.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.toLocaleString %q is not callable", toString)) } return toString.call(call.runtime, call.This) } -func builtinObject_getPrototypeOf(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectGetPrototypeOf(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.GetPrototypeOf is nil")) } - if object.prototype == nil { + if obj.prototype == nil { return nullValue } - return toValue_object(object.prototype) + return objectValue(obj.prototype) } -func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.GetOwnPropertyDescriptor is nil")) } name := call.Argument(1).string() - descriptor := object.getOwnProperty(name) + descriptor := obj.getOwnProperty(name) if descriptor == nil { return Value{} } - return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor)) + return objectValue(call.runtime.fromPropertyDescriptor(*descriptor)) } -func builtinObject_defineProperty(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectDefineProperty(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.DefineProperty is nil")) } name := call.Argument(1).string() descriptor := toPropertyDescriptor(call.runtime, call.Argument(2)) - object.defineOwnProperty(name, descriptor, true) - return objectValue + obj.defineOwnProperty(name, descriptor, true) + return val } -func builtinObject_defineProperties(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectDefineProperties(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.DefineProperties is nil")) } properties := call.runtime.toObject(call.Argument(1)) properties.enumerate(false, func(name string) bool { descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) - object.defineOwnProperty(name, descriptor, true) + obj.defineOwnProperty(name, descriptor, true) return true }) - return objectValue + return val } -func builtinObject_create(call FunctionCall) Value { +func builtinObjectCreate(call FunctionCall) Value { prototypeValue := call.Argument(0) if !prototypeValue.IsNull() && !prototypeValue.IsObject() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.Create is nil")) } - object := call.runtime.newObject() - object.prototype = prototypeValue._object() + obj := call.runtime.newObject() + obj.prototype = prototypeValue.object() propertiesValue := call.Argument(1) if propertiesValue.IsDefined() { properties := call.runtime.toObject(propertiesValue) properties.enumerate(false, func(name string) bool { descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) - object.defineOwnProperty(name, descriptor, true) + obj.defineOwnProperty(name, descriptor, true) return true }) } - return toValue_object(object) + return objectValue(obj) } -func builtinObject_isExtensible(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - return toValue_bool(object.extensible) +func builtinObjectIsExtensible(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + return boolValue(obj.extensible) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.IsExtensible is nil")) } -func builtinObject_preventExtensions(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.extensible = false - } else { - panic(call.runtime.panicTypeError()) +func builtinObjectPreventExtensions(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.extensible = false + return val } - return object + panic(call.runtime.panicTypeError("Object.PreventExtensions is nil")) } -func builtinObject_isSealed(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - if object.extensible { - return toValue_bool(false) +func builtinObjectIsSealed(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + if obj.extensible { + return boolValue(false) } result := true - object.enumerate(true, func(name string) bool { - property := object.getProperty(name) - if property.configurable() { + obj.enumerate(true, func(name string) bool { + prop := obj.getProperty(name) + if prop.configurable() { result = false } return true }) - return toValue_bool(result) + return boolValue(result) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.IsSealed is nil")) } -func builtinObject_seal(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.enumerate(true, func(name string) bool { - if property := object.getOwnProperty(name); nil != property && property.configurable() { - property.configureOff() - object.defineOwnProperty(name, *property, true) +func builtinObjectSeal(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.enumerate(true, func(name string) bool { + if prop := obj.getOwnProperty(name); nil != prop && prop.configurable() { + prop.configureOff() + obj.defineOwnProperty(name, *prop, true) } return true }) - object.extensible = false - } else { - panic(call.runtime.panicTypeError()) + obj.extensible = false + return val } - return object + panic(call.runtime.panicTypeError("Object.Seal is nil")) } -func builtinObject_isFrozen(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - if object.extensible { - return toValue_bool(false) +func builtinObjectIsFrozen(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + if obj.extensible { + return boolValue(false) } result := true - object.enumerate(true, func(name string) bool { - property := object.getProperty(name) - if property.configurable() || property.writable() { + obj.enumerate(true, func(name string) bool { + prop := obj.getProperty(name) + if prop.configurable() || prop.writable() { result = false } return true }) - return toValue_bool(result) + return boolValue(result) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.IsFrozen is nil")) } -func builtinObject_freeze(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.enumerate(true, func(name string) bool { - if property, update := object.getOwnProperty(name), false; nil != property { - if property.isDataDescriptor() && property.writable() { - property.writeOff() +func builtinObjectFreeze(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.enumerate(true, func(name string) bool { + if prop, update := obj.getOwnProperty(name), false; nil != prop { + if prop.isDataDescriptor() && prop.writable() { + prop.writeOff() update = true } - if property.configurable() { - property.configureOff() + if prop.configurable() { + prop.configureOff() update = true } if update { - object.defineOwnProperty(name, *property, true) + obj.defineOwnProperty(name, *prop, true) } } return true }) - object.extensible = false - } else { - panic(call.runtime.panicTypeError()) + obj.extensible = false + return val } - return object + panic(call.runtime.panicTypeError("Object.Freeze is nil")) } -func builtinObject_keys(call FunctionCall) Value { - if object, keys := call.Argument(0)._object(), []Value(nil); nil != object { - object.enumerate(false, func(name string) bool { - keys = append(keys, toValue_string(name)) +func builtinObjectKeys(call FunctionCall) Value { + if obj, keys := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(false, func(name string) bool { + keys = append(keys, stringValue(name)) return true }) - return toValue_object(call.runtime.newArrayOf(keys)) + return objectValue(call.runtime.newArrayOf(keys)) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.Keys is nil")) } -func builtinObject_getOwnPropertyNames(call FunctionCall) Value { - if object, propertyNames := call.Argument(0)._object(), []Value(nil); nil != object { - object.enumerate(true, func(name string) bool { - if object.hasOwnProperty(name) { - propertyNames = append(propertyNames, toValue_string(name)) +func builtinObjectValues(call FunctionCall) Value { + if obj, values := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(false, func(name string) bool { + values = append(values, obj.get(name)) + return true + }) + return objectValue(call.runtime.newArrayOf(values)) + } + panic(call.runtime.panicTypeError("Object.Values is nil")) +} + +func builtinObjectGetOwnPropertyNames(call FunctionCall) Value { + if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(true, func(name string) bool { + if obj.hasOwnProperty(name) { + propertyNames = append(propertyNames, stringValue(name)) } return true }) - return toValue_object(call.runtime.newArrayOf(propertyNames)) + return objectValue(call.runtime.newArrayOf(propertyNames)) } - panic(call.runtime.panicTypeError()) + + // Default to empty array for non object types. + return objectValue(call.runtime.newArray(0)) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_regexp.go b/vendor/github.com/robertkrimen/otto/builtin_regexp.go index 99422510d..043034472 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_regexp.go +++ b/vendor/github.com/robertkrimen/otto/builtin_regexp.go @@ -9,22 +9,22 @@ import ( func builtinRegExp(call FunctionCall) Value { pattern := call.Argument(0) flags := call.Argument(1) - if object := pattern._object(); object != nil { - if object.class == "RegExp" && flags.IsUndefined() { + if obj := pattern.object(); obj != nil { + if obj.class == classRegExpName && flags.IsUndefined() { return pattern } } - return toValue_object(call.runtime.newRegExp(pattern, flags)) + return objectValue(call.runtime.newRegExp(pattern, flags)) } -func builtinNewRegExp(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newRegExp( +func builtinNewRegExp(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newRegExp( valueOfArrayIndex(argumentList, 0), valueOfArrayIndex(argumentList, 1), )) } -func builtinRegExp_toString(call FunctionCall) Value { +func builtinRegExpToString(call FunctionCall) Value { thisObject := call.thisObject() source := thisObject.get("source").string() flags := []byte{} @@ -37,27 +37,65 @@ func builtinRegExp_toString(call FunctionCall) Value { if thisObject.get("multiline").bool() { flags = append(flags, 'm') } - return toValue_string(fmt.Sprintf("/%s/%s", source, flags)) + return stringValue(fmt.Sprintf("/%s/%s", source, flags)) } -func builtinRegExp_exec(call FunctionCall) Value { +func builtinRegExpExec(call FunctionCall) Value { thisObject := call.thisObject() target := call.Argument(0).string() match, result := execRegExp(thisObject, target) if !match { return nullValue } - return toValue_object(execResultToArray(call.runtime, target, result)) + return objectValue(execResultToArray(call.runtime, target, result)) } -func builtinRegExp_test(call FunctionCall) Value { +func builtinRegExpTest(call FunctionCall) Value { thisObject := call.thisObject() target := call.Argument(0).string() - match, _ := execRegExp(thisObject, target) - return toValue_bool(match) + match, result := execRegExp(thisObject, target) + + if !match { + return boolValue(match) + } + + // Match extract and assign input, $_ and $1 -> $9 on global RegExp. + input := stringValue(target) + call.runtime.global.RegExp.defineProperty("$_", input, 0o100, false) + call.runtime.global.RegExp.defineProperty("input", input, 0o100, false) + + var start int + n := 1 + re := call.runtime.global.RegExp + empty := stringValue("") + for i, v := range result[2:] { + if i%2 == 0 { + start = v + } else { + if v == -1 { + // No match for this part. + re.defineProperty(fmt.Sprintf("$%d", n), empty, 0o100, false) + } else { + re.defineProperty(fmt.Sprintf("$%d", n), stringValue(target[start:v]), 0o100, false) + } + n++ + if n == 10 { + break + } + } + } + + if n <= 9 { + // Erase remaining. + for i := n; i <= 9; i++ { + re.defineProperty(fmt.Sprintf("$%d", i), empty, 0o100, false) + } + } + + return boolValue(match) } -func builtinRegExp_compile(call FunctionCall) Value { +func builtinRegExpCompile(call FunctionCall) Value { // This (useless) function is deprecated, but is here to provide some // semblance of compatibility. // Caveat emptor: it may not be around for long. diff --git a/vendor/github.com/robertkrimen/otto/builtin_string.go b/vendor/github.com/robertkrimen/otto/builtin_string.go index 6a1718458..48ef20387 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_string.go +++ b/vendor/github.com/robertkrimen/otto/builtin_string.go @@ -5,6 +5,7 @@ import ( "regexp" "strconv" "strings" + "unicode/utf16" "unicode/utf8" ) @@ -12,102 +13,121 @@ import ( func stringValueFromStringArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { - return toValue_string(argumentList[0].string()) + return stringValue(argumentList[0].string()) } - return toValue_string("") + return stringValue("") } func builtinString(call FunctionCall) Value { return stringValueFromStringArgumentList(call.ArgumentList) } -func builtinNewString(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList))) +func builtinNewString(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newString(stringValueFromStringArgumentList(argumentList))) } -func builtinString_toString(call FunctionCall) Value { - return call.thisClassObject("String").primitiveValue() +func builtinStringToString(call FunctionCall) Value { + return call.thisClassObject(classStringName).primitiveValue() } -func builtinString_valueOf(call FunctionCall) Value { - return call.thisClassObject("String").primitiveValue() + +func builtinStringValueOf(call FunctionCall) Value { + return call.thisClassObject(classStringName).primitiveValue() } -func builtinString_fromCharCode(call FunctionCall) Value { +func builtinStringFromCharCode(call FunctionCall) Value { chrList := make([]uint16, len(call.ArgumentList)) for index, value := range call.ArgumentList { chrList[index] = toUint16(value) } - return toValue_string16(chrList) + return string16Value(chrList) } -func builtinString_charAt(call FunctionCall) Value { +func builtinStringCharAt(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) idx := int(call.Argument(0).number().int64) - chr := stringAt(call.This._object().stringValue(), idx) + chr := stringAt(call.This.object().stringValue(), idx) if chr == utf8.RuneError { - return toValue_string("") + return stringValue("") } - return toValue_string(string(chr)) + return stringValue(string(chr)) } -func builtinString_charCodeAt(call FunctionCall) Value { +func builtinStringCharCodeAt(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) idx := int(call.Argument(0).number().int64) - chr := stringAt(call.This._object().stringValue(), idx) + chr := stringAt(call.This.object().stringValue(), idx) if chr == utf8.RuneError { return NaNValue() } - return toValue_uint16(uint16(chr)) + return uint16Value(uint16(chr)) } -func builtinString_concat(call FunctionCall) Value { +func builtinStringConcat(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) var value bytes.Buffer value.WriteString(call.This.string()) for _, item := range call.ArgumentList { value.WriteString(item.string()) } - return toValue_string(value.String()) + return stringValue(value.String()) +} + +func lastIndexRune(s, substr string) int { + if i := strings.LastIndex(s, substr); i >= 0 { + return utf16Length(s[:i]) + } + return -1 +} + +func indexRune(s, substr string) int { + if i := strings.Index(s, substr); i >= 0 { + return utf16Length(s[:i]) + } + return -1 } -func builtinString_indexOf(call FunctionCall) Value { +func utf16Length(s string) int { + return len(utf16.Encode([]rune(s))) +} + +func builtinStringIndexOf(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) value := call.This.string() target := call.Argument(0).string() if 2 > len(call.ArgumentList) { - return toValue_int(strings.Index(value, target)) + return intValue(indexRune(value, target)) } start := toIntegerFloat(call.Argument(1)) if 0 > start { start = 0 } else if start >= float64(len(value)) { if target == "" { - return toValue_int(len(value)) + return intValue(len(value)) } - return toValue_int(-1) + return intValue(-1) } - index := strings.Index(value[int(start):], target) + index := indexRune(value[int(start):], target) if index >= 0 { index += int(start) } - return toValue_int(index) + return intValue(index) } -func builtinString_lastIndexOf(call FunctionCall) Value { +func builtinStringLastIndexOf(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) value := call.This.string() target := call.Argument(0).string() if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() { - return toValue_int(strings.LastIndex(value, target)) + return intValue(lastIndexRune(value, target)) } length := len(value) if length == 0 { - return toValue_int(strings.LastIndex(value, target)) + return intValue(lastIndexRune(value, target)) } start := call.ArgumentList[1].number() if start.kind == numberInfinity { // FIXME // startNumber is infinity, so start is the end of string (start = length) - return toValue_int(strings.LastIndex(value, target)) + return intValue(lastIndexRune(value, target)) } if 0 > start.int64 { start.int64 = 0 @@ -116,15 +136,15 @@ func builtinString_lastIndexOf(call FunctionCall) Value { if end > length { end = length } - return toValue_int(strings.LastIndex(value[:end], target)) + return intValue(lastIndexRune(value[:end], target)) } -func builtinString_match(call FunctionCall) Value { +func builtinStringMatch(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() matcherValue := call.Argument(0) - matcher := matcherValue._object() - if !matcherValue.IsObject() || matcher.class != "RegExp" { + matcher := matcherValue.object() + if !matcherValue.IsObject() || matcher.class != classRegExpName { matcher = call.runtime.newRegExp(matcherValue, Value{}) } global := matcher.get("global").bool() @@ -133,35 +153,32 @@ func builtinString_match(call FunctionCall) Value { if !match { return nullValue } - return toValue_object(execResultToArray(call.runtime, target, result)) + return objectValue(execResultToArray(call.runtime, target, result)) } - { - result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) - matchCount := len(result) - if result == nil { - matcher.put("lastIndex", toValue_int(0), true) - return Value{} // !match - } - matchCount = len(result) - valueArray := make([]Value, matchCount) - for index := 0; index < matchCount; index++ { - valueArray[index] = toValue_string(target[result[index][0]:result[index][1]]) - } - matcher.put("lastIndex", toValue_int(result[matchCount-1][1]), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) + result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) + if result == nil { + matcher.put("lastIndex", intValue(0), true) + return Value{} // !match + } + matchCount := len(result) + valueArray := make([]Value, matchCount) + for index := range matchCount { + valueArray[index] = stringValue(target[result[index][0]:result[index][1]]) } + matcher.put("lastIndex", intValue(result[matchCount-1][1]), true) + return objectValue(call.runtime.newArrayOf(valueArray)) } -var builtinString_replace_Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") +var builtinStringReplaceRegexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") -func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) { +func builtinStringFindAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) []byte { matchCount := len(match) / 2 - output = input + output := input if match[0] != lastIndex { output = append(output, target[lastIndex:match[0]]...) } - replacement := builtinString_replace_Regexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { + replacement := builtinStringReplaceRegexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { // TODO Check if match[0] or match[1] can be -1 in this scenario switch part[1] { case '$': @@ -171,38 +188,42 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int case '`': return target[:match[0]] case '\'': - return target[match[1]:len(target)] + return target[match[1]:] + } + matchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64) + if err != nil { + return nil } - matchNumberParse, error := strconv.ParseInt(string(part[1:]), 10, 64) matchNumber := int(matchNumberParse) - if error != nil || matchNumber >= matchCount { - return []byte{} + if matchNumber >= matchCount { + return nil } offset := 2 * matchNumber if match[offset] != -1 { return target[match[offset]:match[offset+1]] } - return []byte{} // The empty string + return nil // The empty string }) - output = append(output, replacement...) - return output + + return append(output, replacement...) } -func builtinString_replace(call FunctionCall) Value { +func builtinStringReplace(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := []byte(call.This.string()) searchValue := call.Argument(0) - searchObject := searchValue._object() + searchObject := searchValue.object() // TODO If a capture is -1? var search *regexp.Regexp global := false find := 1 - if searchValue.IsObject() && searchObject.class == "RegExp" { + if searchValue.IsObject() && searchObject.class == classRegExpName { regExp := searchObject.regExpValue() search = regExp.regularExpression if regExp.global { find = -1 + global = true } } else { search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string())) @@ -210,85 +231,72 @@ func builtinString_replace(call FunctionCall) Value { found := search.FindAllSubmatchIndex(target, find) if found == nil { - return toValue_string(string(target)) // !match - } - - { - lastIndex := 0 - result := []byte{} - - replaceValue := call.Argument(1) - if replaceValue.isCallable() { - target := string(target) - replace := replaceValue._object() - for _, match := range found { - if match[0] != lastIndex { - result = append(result, target[lastIndex:match[0]]...) - } - matchCount := len(match) / 2 - argumentList := make([]Value, matchCount+2) - for index := 0; index < matchCount; index++ { - offset := 2 * index - if match[offset] != -1 { - argumentList[index] = toValue_string(target[match[offset]:match[offset+1]]) - } else { - argumentList[index] = Value{} - } - } - argumentList[matchCount+0] = toValue_int(match[0]) - argumentList[matchCount+1] = toValue_string(target) - replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() - result = append(result, []byte(replacement)...) - lastIndex = match[1] + return stringValue(string(target)) // !match + } + + lastIndex := 0 + result := []byte{} + replaceValue := call.Argument(1) + if replaceValue.isCallable() { + target := string(target) + replace := replaceValue.object() + for _, match := range found { + if match[0] != lastIndex { + result = append(result, target[lastIndex:match[0]]...) } - - } else { - replace := []byte(replaceValue.string()) - for _, match := range found { - result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace) - lastIndex = match[1] + matchCount := len(match) / 2 + argumentList := make([]Value, matchCount+2) + for index := range matchCount { + offset := 2 * index + if match[offset] != -1 { + argumentList[index] = stringValue(target[match[offset]:match[offset+1]]) + } else { + argumentList[index] = Value{} + } } + // Replace expects rune offsets not byte offsets. + startIndex := utf8.RuneCountInString(target[0:match[0]]) + argumentList[matchCount+0] = intValue(startIndex) + argumentList[matchCount+1] = stringValue(target) + replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() + result = append(result, []byte(replacement)...) + lastIndex = match[1] } - - if lastIndex != len(target) { - result = append(result, target[lastIndex:]...) + } else { + replace := []byte(replaceValue.string()) + for _, match := range found { + result = builtinStringFindAndReplaceString(result, lastIndex, match, target, replace) + lastIndex = match[1] } + } - if global && searchObject != nil { - searchObject.put("lastIndex", toValue_int(lastIndex), true) - } + if lastIndex != len(target) { + result = append(result, target[lastIndex:]...) + } - return toValue_string(string(result)) + if global && searchObject != nil { + searchObject.put("lastIndex", intValue(lastIndex), true) } + + return stringValue(string(result)) } -func builtinString_search(call FunctionCall) Value { +func builtinStringSearch(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() searchValue := call.Argument(0) - search := searchValue._object() - if !searchValue.IsObject() || search.class != "RegExp" { + search := searchValue.object() + if !searchValue.IsObject() || search.class != classRegExpName { search = call.runtime.newRegExp(searchValue, Value{}) } result := search.regExpValue().regularExpression.FindStringIndex(target) if result == nil { - return toValue_int(-1) + return intValue(-1) } - return toValue_int(result[0]) + return intValue(result[0]) } -func stringSplitMatch(target string, targetLength int64, index uint, search string, searchLength int64) (bool, uint) { - if int64(index)+searchLength > searchLength { - return false, 0 - } - found := strings.Index(target[index:], search) - if 0 > found { - return false, 0 - } - return true, uint(found) -} - -func builtinString_split(call FunctionCall) Value { +func builtinStringSplit(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() @@ -300,16 +308,16 @@ func builtinString_split(call FunctionCall) Value { } if limit == 0 { - return toValue_object(call.runtime.newArray(0)) + return objectValue(call.runtime.newArray(0)) } if separatorValue.IsUndefined() { - return toValue_object(call.runtime.newArrayOf([]Value{toValue_string(target)})) + return objectValue(call.runtime.newArrayOf([]Value{stringValue(target)})) } if separatorValue.isRegExp() { targetLength := len(target) - search := separatorValue._object().regExpValue().regularExpression + search := separatorValue.object().regExpValue().regularExpression valueArray := []Value{} result := search.FindAllStringSubmatchIndex(target, -1) lastIndex := 0 @@ -324,11 +332,11 @@ func builtinString_split(call FunctionCall) Value { } if lastIndex != match[0] { - valueArray = append(valueArray, toValue_string(target[lastIndex:match[0]])) + valueArray = append(valueArray, stringValue(target[lastIndex:match[0]])) found++ } else if lastIndex == match[0] { if lastIndex != -1 { - valueArray = append(valueArray, toValue_string("")) + valueArray = append(valueArray, stringValue("")) found++ } } @@ -343,7 +351,7 @@ func builtinString_split(call FunctionCall) Value { offset := index * 2 value := Value{} if match[offset] != -1 { - value = toValue_string(target[match[offset]:match[offset+1]]) + value = stringValue(target[match[offset]:match[offset+1]]) } valueArray = append(valueArray, value) found++ @@ -355,15 +363,14 @@ func builtinString_split(call FunctionCall) Value { if found != limit { if lastIndex != targetLength { - valueArray = append(valueArray, toValue_string(target[lastIndex:targetLength])) + valueArray = append(valueArray, stringValue(target[lastIndex:targetLength])) } else { - valueArray = append(valueArray, toValue_string("")) + valueArray = append(valueArray, stringValue("")) } } RETURN: - return toValue_object(call.runtime.newArrayOf(valueArray)) - + return objectValue(call.runtime.newArrayOf(valueArray)) } else { separator := separatorValue.string() @@ -382,49 +389,51 @@ func builtinString_split(call FunctionCall) Value { valueArray := make([]Value, len(split)) for index, value := range split { - valueArray[index] = toValue_string(value) + valueArray[index] = stringValue(value) } - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } } -func builtinString_slice(call FunctionCall) Value { +// builtinStringSlice returns the string sliced by the given values +// which are rune not byte offsets, as per String.prototype.slice. +func builtinStringSlice(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - target := call.This.string() + target := []rune(call.This.string()) length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, false) if end-start <= 0 { - return toValue_string("") + return stringValue("") } - return toValue_string(target[start:end]) + return stringValue(string(target[start:end])) } -func builtinString_substring(call FunctionCall) Value { +func builtinStringSubstring(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - target := call.This.string() + target := []rune(call.This.string()) length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, true) if start > end { start, end = end, start } - return toValue_string(target[start:end]) + return stringValue(string(target[start:end])) } -func builtinString_substr(call FunctionCall) Value { - target := call.This.string() +func builtinStringSubstr(call FunctionCall) Value { + target := []rune(call.This.string()) size := int64(len(target)) start, length := rangeStartLength(call.ArgumentList, size) if start >= size { - return toValue_string("") + return stringValue("") } if length <= 0 { - return toValue_string("") + return stringValue("") } if start+length >= size { @@ -435,66 +444,77 @@ func builtinString_substr(call FunctionCall) Value { length = size - start } - return toValue_string(target[start : start+length]) + return stringValue(string(target[start : start+length])) +} + +func builtinStringStartsWith(call FunctionCall) Value { + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() + search := call.Argument(0).string() + length := len(search) + if length > len(target) { + return boolValue(false) + } + return boolValue(target[:length] == search) } -func builtinString_toLowerCase(call FunctionCall) Value { +func builtinStringToLowerCase(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - return toValue_string(strings.ToLower(call.This.string())) + return stringValue(strings.ToLower(call.This.string())) } -func builtinString_toUpperCase(call FunctionCall) Value { +func builtinStringToUpperCase(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - return toValue_string(strings.ToUpper(call.This.string())) + return stringValue(strings.ToUpper(call.This.string())) } -// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters -const builtinString_trim_whitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF" +// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters. +const builtinStringTrimWhitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF" -func builtinString_trim(call FunctionCall) Value { +func builtinStringTrim(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.Trim(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -// Mozilla extension, not ECMAScript 5 -func builtinString_trimLeft(call FunctionCall) Value { +func builtinStringTrimStart(call FunctionCall) Value { + return builtinStringTrimLeft(call) +} + +func builtinStringTrimEnd(call FunctionCall) Value { + return builtinStringTrimRight(call) +} + +// Mozilla extension, not ECMAScript 5. +func builtinStringTrimLeft(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.TrimLeft(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -// Mozilla extension, not ECMAScript 5 -func builtinString_trimRight(call FunctionCall) Value { +// Mozilla extension, not ECMAScript 5. +func builtinStringTrimRight(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.TrimRight(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -func builtinString_localeCompare(call FunctionCall) Value { +func builtinStringLocaleCompare(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - this := call.This.string() + this := call.This.string() //nolint:ifshort that := call.Argument(0).string() if this < that { - return toValue_int(-1) + return intValue(-1) } else if this == that { - return toValue_int(0) + return intValue(0) } - return toValue_int(1) -} - -/* -An alternate version of String.trim -func builtinString_trim(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.TrimFunc(call.string(.This), isWhiteSpaceOrLineTerminator)) + return intValue(1) } -*/ -func builtinString_toLocaleLowerCase(call FunctionCall) Value { - return builtinString_toLowerCase(call) +func builtinStringToLocaleLowerCase(call FunctionCall) Value { + return builtinStringToLowerCase(call) } -func builtinString_toLocaleUpperCase(call FunctionCall) Value { - return builtinString_toUpperCase(call) +func builtinStringToLocaleUpperCase(call FunctionCall) Value { + return builtinStringToUpperCase(call) } diff --git a/vendor/github.com/robertkrimen/otto/clone.go b/vendor/github.com/robertkrimen/otto/clone.go index 23b59f8ac..edc284594 100644 --- a/vendor/github.com/robertkrimen/otto/clone.go +++ b/vendor/github.com/robertkrimen/otto/clone.go @@ -4,159 +4,157 @@ import ( "fmt" ) -type _clone struct { - runtime *_runtime - _object map[*_object]*_object - _objectStash map[*_objectStash]*_objectStash - _dclStash map[*_dclStash]*_dclStash - _fnStash map[*_fnStash]*_fnStash +type cloner struct { + runtime *runtime + obj map[*object]*object + objectstash map[*objectStash]*objectStash + dclstash map[*dclStash]*dclStash + fnstash map[*fnStash]*fnStash } -func (in *_runtime) clone() *_runtime { +func (rt *runtime) clone() *runtime { + rt.lck.Lock() + defer rt.lck.Unlock() - in.lck.Lock() - defer in.lck.Unlock() - - out := &_runtime{ - debugger: in.debugger, - random: in.random, - stackLimit: in.stackLimit, - traceLimit: in.traceLimit, + out := &runtime{ + debugger: rt.debugger, + random: rt.random, + stackLimit: rt.stackLimit, + traceLimit: rt.traceLimit, } - clone := _clone{ - runtime: out, - _object: make(map[*_object]*_object), - _objectStash: make(map[*_objectStash]*_objectStash), - _dclStash: make(map[*_dclStash]*_dclStash), - _fnStash: make(map[*_fnStash]*_fnStash), + c := cloner{ + runtime: out, + obj: make(map[*object]*object), + objectstash: make(map[*objectStash]*objectStash), + dclstash: make(map[*dclStash]*dclStash), + fnstash: make(map[*fnStash]*fnStash), } - globalObject := clone.object(in.globalObject) + globalObject := c.object(rt.globalObject) out.globalStash = out.newObjectStash(globalObject, nil) out.globalObject = globalObject - out.global = _global{ - clone.object(in.global.Object), - clone.object(in.global.Function), - clone.object(in.global.Array), - clone.object(in.global.String), - clone.object(in.global.Boolean), - clone.object(in.global.Number), - clone.object(in.global.Math), - clone.object(in.global.Date), - clone.object(in.global.RegExp), - clone.object(in.global.Error), - clone.object(in.global.EvalError), - clone.object(in.global.TypeError), - clone.object(in.global.RangeError), - clone.object(in.global.ReferenceError), - clone.object(in.global.SyntaxError), - clone.object(in.global.URIError), - clone.object(in.global.JSON), - - clone.object(in.global.ObjectPrototype), - clone.object(in.global.FunctionPrototype), - clone.object(in.global.ArrayPrototype), - clone.object(in.global.StringPrototype), - clone.object(in.global.BooleanPrototype), - clone.object(in.global.NumberPrototype), - clone.object(in.global.DatePrototype), - clone.object(in.global.RegExpPrototype), - clone.object(in.global.ErrorPrototype), - clone.object(in.global.EvalErrorPrototype), - clone.object(in.global.TypeErrorPrototype), - clone.object(in.global.RangeErrorPrototype), - clone.object(in.global.ReferenceErrorPrototype), - clone.object(in.global.SyntaxErrorPrototype), - clone.object(in.global.URIErrorPrototype), + out.global = global{ + c.object(rt.global.Object), + c.object(rt.global.Function), + c.object(rt.global.Array), + c.object(rt.global.String), + c.object(rt.global.Boolean), + c.object(rt.global.Number), + c.object(rt.global.Math), + c.object(rt.global.Date), + c.object(rt.global.RegExp), + c.object(rt.global.Error), + c.object(rt.global.EvalError), + c.object(rt.global.TypeError), + c.object(rt.global.RangeError), + c.object(rt.global.ReferenceError), + c.object(rt.global.SyntaxError), + c.object(rt.global.URIError), + c.object(rt.global.JSON), + + c.object(rt.global.ObjectPrototype), + c.object(rt.global.FunctionPrototype), + c.object(rt.global.ArrayPrototype), + c.object(rt.global.StringPrototype), + c.object(rt.global.BooleanPrototype), + c.object(rt.global.NumberPrototype), + c.object(rt.global.DatePrototype), + c.object(rt.global.RegExpPrototype), + c.object(rt.global.ErrorPrototype), + c.object(rt.global.EvalErrorPrototype), + c.object(rt.global.TypeErrorPrototype), + c.object(rt.global.RangeErrorPrototype), + c.object(rt.global.ReferenceErrorPrototype), + c.object(rt.global.SyntaxErrorPrototype), + c.object(rt.global.URIErrorPrototype), } - out.eval = out.globalObject.property["eval"].value.(Value).value.(*_object) + out.eval = out.globalObject.property["eval"].value.(Value).value.(*object) out.globalObject.prototype = out.global.ObjectPrototype // Not sure if this is necessary, but give some help to the GC - clone.runtime = nil - clone._object = nil - clone._objectStash = nil - clone._dclStash = nil - clone._fnStash = nil + c.runtime = nil + c.obj = nil + c.objectstash = nil + c.dclstash = nil + c.fnstash = nil return out } -func (clone *_clone) object(in *_object) *_object { - if out, exists := clone._object[in]; exists { +func (c *cloner) object(in *object) *object { + if out, exists := c.obj[in]; exists { return out } - out := &_object{} - clone._object[in] = out - return in.objectClass.clone(in, out, clone) + out := &object{} + c.obj[in] = out + return in.objectClass.clone(in, out, c) } -func (clone *_clone) dclStash(in *_dclStash) (*_dclStash, bool) { - if out, exists := clone._dclStash[in]; exists { +func (c *cloner) dclStash(in *dclStash) (*dclStash, bool) { + if out, exists := c.dclstash[in]; exists { return out, true } - out := &_dclStash{} - clone._dclStash[in] = out + out := &dclStash{} + c.dclstash[in] = out return out, false } -func (clone *_clone) objectStash(in *_objectStash) (*_objectStash, bool) { - if out, exists := clone._objectStash[in]; exists { +func (c *cloner) objectStash(in *objectStash) (*objectStash, bool) { + if out, exists := c.objectstash[in]; exists { return out, true } - out := &_objectStash{} - clone._objectStash[in] = out + out := &objectStash{} + c.objectstash[in] = out return out, false } -func (clone *_clone) fnStash(in *_fnStash) (*_fnStash, bool) { - if out, exists := clone._fnStash[in]; exists { +func (c *cloner) fnStash(in *fnStash) (*fnStash, bool) { + if out, exists := c.fnstash[in]; exists { return out, true } - out := &_fnStash{} - clone._fnStash[in] = out + out := &fnStash{} + c.fnstash[in] = out return out, false } -func (clone *_clone) value(in Value) Value { +func (c *cloner) value(in Value) Value { out := in - switch value := in.value.(type) { - case *_object: - out.value = clone.object(value) + if value, ok := in.value.(*object); ok { + out.value = c.object(value) } return out } -func (clone *_clone) valueArray(in []Value) []Value { +func (c *cloner) valueArray(in []Value) []Value { out := make([]Value, len(in)) for index, value := range in { - out[index] = clone.value(value) + out[index] = c.value(value) } return out } -func (clone *_clone) stash(in _stash) _stash { +func (c *cloner) stash(in stasher) stasher { if in == nil { return nil } - return in.clone(clone) + return in.clone(c) } -func (clone *_clone) property(in _property) _property { +func (c *cloner) property(in property) property { out := in switch value := in.value.(type) { case Value: - out.value = clone.value(value) - case _propertyGetSet: - p := _propertyGetSet{} + out.value = c.value(value) + case propertyGetSet: + p := propertyGetSet{} if value[0] != nil { - p[0] = clone.object(value[0]) + p[0] = c.object(value[0]) } if value[1] != nil { - p[1] = clone.object(value[1]) + p[1] = c.object(value[1]) } out.value = p default: @@ -166,8 +164,8 @@ func (clone *_clone) property(in _property) _property { return out } -func (clone *_clone) dclProperty(in _dclProperty) _dclProperty { +func (c *cloner) dclProperty(in dclProperty) dclProperty { out := in - out.value = clone.value(in.value) + out.value = c.value(in.value) return out } diff --git a/vendor/github.com/robertkrimen/otto/cmpl.go b/vendor/github.com/robertkrimen/otto/cmpl.go index c191b4527..e81cd50b4 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl.go +++ b/vendor/github.com/robertkrimen/otto/cmpl.go @@ -5,20 +5,7 @@ import ( "github.com/robertkrimen/otto/file" ) -type _file struct { - name string - src string - base int // This will always be 1 or greater -} - -type _compiler struct { +type compiler struct { file *file.File program *ast.Program } - -func (cmpl *_compiler) parse() *_nodeProgram { - if cmpl.program != nil { - cmpl.file = cmpl.program.File - } - return cmpl._parse(cmpl.program) -} diff --git a/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go b/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go index 6741bf394..a29b7d880 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go @@ -4,21 +4,18 @@ import ( "strconv" ) -func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram, eval bool) Value { +func (rt *runtime) cmplEvaluateNodeProgram(node *nodeProgram, eval bool) Value { if !eval { - self.enterGlobalScope() - defer func() { - self.leaveScope() - }() + rt.enterGlobalScope() + defer rt.leaveScope() } - self.cmpl_functionDeclaration(node.functionList) - self.cmpl_variableDeclaration(node.varList) - self.scope.frame.file = node.file - return self.cmpl_evaluate_nodeStatementList(node.body) + rt.cmplFunctionDeclaration(node.functionList) + rt.cmplVariableDeclaration(node.varList) + rt.scope.frame.file = node.file + return rt.cmplEvaluateNodeStatementList(node.body) } -func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, node *_nodeFunctionLiteral, this Value, argumentList []Value) Value { - +func (rt *runtime) cmplCallNodeFunction(function *object, stash *fnStash, node *nodeFunctionLiteral, argumentList []Value) Value { indexOfParameterName := make([]string, len(argumentList)) // function(abc, def, ghi) // indexOfParameterName[0] = "abc" @@ -37,28 +34,28 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, indexOfParameterName[index] = name } // strict = false - self.scope.lexical.setValue(name, value, false) + rt.scope.lexical.setValue(name, value, false) } if !argumentsFound { - arguments := self.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) - arguments.defineProperty("callee", toValue_object(function), 0101, false) + arguments := rt.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) + arguments.defineProperty("callee", objectValue(function), 0o101, false) stash.arguments = arguments // strict = false - self.scope.lexical.setValue("arguments", toValue_object(arguments), false) - for index, _ := range argumentList { + rt.scope.lexical.setValue("arguments", objectValue(arguments), false) + for index := range argumentList { if index < len(node.parameterList) { continue } indexAsString := strconv.FormatInt(int64(index), 10) - arguments.defineProperty(indexAsString, argumentList[index], 0111, false) + arguments.defineProperty(indexAsString, argumentList[index], 0o111, false) } } - self.cmpl_functionDeclaration(node.functionList) - self.cmpl_variableDeclaration(node.varList) + rt.cmplFunctionDeclaration(node.functionList) + rt.cmplVariableDeclaration(node.varList) - result := self.cmpl_evaluate_nodeStatement(node.body) + result := rt.cmplEvaluateNodeStatement(node.body) if result.kind == valueResult { return result } @@ -66,16 +63,16 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, return Value{} } -func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { - executionContext := self.scope +func (rt *runtime) cmplFunctionDeclaration(list []*nodeFunctionLiteral) { + executionContext := rt.scope eval := executionContext.eval stash := executionContext.variable for _, function := range list { name := function.name - value := self.cmpl_evaluate_nodeExpression(function) + value := rt.cmplEvaluateNodeExpression(function) if !stash.hasBinding(name) { - stash.createBinding(name, eval == true, value) + stash.createBinding(name, eval, value) } else { // TODO 10.5.5.e stash.setBinding(name, value, false) // TODO strict @@ -83,14 +80,14 @@ func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { } } -func (self *_runtime) cmpl_variableDeclaration(list []string) { - executionContext := self.scope +func (rt *runtime) cmplVariableDeclaration(list []string) { + executionContext := rt.scope eval := executionContext.eval stash := executionContext.variable for _, name := range list { if !stash.hasBinding(name) { - stash.createBinding(name, eval == true, Value{}) // TODO strict? + stash.createBinding(name, eval, Value{}) // TODO strict? } } } diff --git a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go index 8586a484f..69c673a8a 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go @@ -3,140 +3,135 @@ package otto import ( "fmt" "math" - "runtime" + goruntime "runtime" "github.com/robertkrimen/otto/token" ) -func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { +func (rt *runtime) cmplEvaluateNodeExpression(node nodeExpression) Value { // Allow interpreter interruption // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.otto.Interrupt != nil { - runtime.Gosched() + if rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } switch node := node.(type) { + case *nodeArrayLiteral: + return rt.cmplEvaluateNodeArrayLiteral(node) - case *_nodeArrayLiteral: - return self.cmpl_evaluate_nodeArrayLiteral(node) + case *nodeAssignExpression: + return rt.cmplEvaluateNodeAssignExpression(node) - case *_nodeAssignExpression: - return self.cmpl_evaluate_nodeAssignExpression(node) - - case *_nodeBinaryExpression: + case *nodeBinaryExpression: if node.comparison { - return self.cmpl_evaluate_nodeBinaryExpression_comparison(node) - } else { - return self.cmpl_evaluate_nodeBinaryExpression(node) + return rt.cmplEvaluateNodeBinaryExpressionComparison(node) } + return rt.cmplEvaluateNodeBinaryExpression(node) - case *_nodeBracketExpression: - return self.cmpl_evaluate_nodeBracketExpression(node) + case *nodeBracketExpression: + return rt.cmplEvaluateNodeBracketExpression(node) - case *_nodeCallExpression: - return self.cmpl_evaluate_nodeCallExpression(node, nil) + case *nodeCallExpression: + return rt.cmplEvaluateNodeCallExpression(node, nil) - case *_nodeConditionalExpression: - return self.cmpl_evaluate_nodeConditionalExpression(node) + case *nodeConditionalExpression: + return rt.cmplEvaluateNodeConditionalExpression(node) - case *_nodeDotExpression: - return self.cmpl_evaluate_nodeDotExpression(node) + case *nodeDotExpression: + return rt.cmplEvaluateNodeDotExpression(node) - case *_nodeFunctionLiteral: - var local = self.scope.lexical + case *nodeFunctionLiteral: + local := rt.scope.lexical if node.name != "" { - local = self.newDeclarationStash(local) + local = rt.newDeclarationStash(local) } - value := toValue_object(self.newNodeFunction(node, local)) + value := objectValue(rt.newNodeFunction(node, local)) if node.name != "" { local.createBinding(node.name, false, value) } return value - case *_nodeIdentifier: + case *nodeIdentifier: name := node.name // TODO Should be true or false (strictness) depending on context // getIdentifierReference should not return nil, but we check anyway and panic // so as not to propagate the nil into something else - reference := getIdentifierReference(self, self.scope.lexical, name, false, _at(node.idx)) + reference := getIdentifierReference(rt, rt.scope.lexical, name, false, at(node.idx)) if reference == nil { // Should never get here! panic(hereBeDragons("referenceError == nil: " + name)) } return toValue(reference) - case *_nodeLiteral: + case *nodeLiteral: return node.value - case *_nodeNewExpression: - return self.cmpl_evaluate_nodeNewExpression(node) + case *nodeNewExpression: + return rt.cmplEvaluateNodeNewExpression(node) - case *_nodeObjectLiteral: - return self.cmpl_evaluate_nodeObjectLiteral(node) + case *nodeObjectLiteral: + return rt.cmplEvaluateNodeObjectLiteral(node) - case *_nodeRegExpLiteral: - return toValue_object(self._newRegExp(node.pattern, node.flags)) + case *nodeRegExpLiteral: + return objectValue(rt.newRegExpDirect(node.pattern, node.flags)) - case *_nodeSequenceExpression: - return self.cmpl_evaluate_nodeSequenceExpression(node) + case *nodeSequenceExpression: + return rt.cmplEvaluateNodeSequenceExpression(node) - case *_nodeThisExpression: - return toValue_object(self.scope.this) + case *nodeThisExpression: + return objectValue(rt.scope.this) - case *_nodeUnaryExpression: - return self.cmpl_evaluate_nodeUnaryExpression(node) + case *nodeUnaryExpression: + return rt.cmplEvaluateNodeUnaryExpression(node) - case *_nodeVariableExpression: - return self.cmpl_evaluate_nodeVariableExpression(node) + case *nodeVariableExpression: + return rt.cmplEvaluateNodeVariableExpression(node) + default: + panic(fmt.Sprintf("unknown node type: %T", node)) } - - panic(fmt.Errorf("Here be dragons: evaluate_nodeExpression(%T)", node)) } -func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Value { - +func (rt *runtime) cmplEvaluateNodeArrayLiteral(node *nodeArrayLiteral) Value { valueArray := []Value{} for _, node := range node.value { if node == nil { valueArray = append(valueArray, emptyValue) } else { - valueArray = append(valueArray, self.cmpl_evaluate_nodeExpression(node).resolve()) + valueArray = append(valueArray, rt.cmplEvaluateNodeExpression(node).resolve()) } } - result := self.newArrayOf(valueArray) + result := rt.newArrayOf(valueArray) - return toValue_object(result) + return objectValue(result) } -func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpression) Value { - - left := self.cmpl_evaluate_nodeExpression(node.left) - right := self.cmpl_evaluate_nodeExpression(node.right) +func (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left) + right := rt.cmplEvaluateNodeExpression(node.right) rightValue := right.resolve() result := rightValue if node.operator != token.ASSIGN { - result = self.calculateBinaryExpression(node.operator, left, rightValue) + result = rt.calculateBinaryExpression(node.operator, left, rightValue) } - self.putValue(left.reference(), result) + rt.putValue(left.reference(), result) return result } -func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value { - - left := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left) leftValue := left.resolve() switch node.operator { @@ -145,217 +140,206 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres if !leftValue.bool() { return leftValue } - right := self.cmpl_evaluate_nodeExpression(node.right) + right := rt.cmplEvaluateNodeExpression(node.right) return right.resolve() case token.LOGICAL_OR: if leftValue.bool() { return leftValue } - right := self.cmpl_evaluate_nodeExpression(node.right) + right := rt.cmplEvaluateNodeExpression(node.right) return right.resolve() } - return self.calculateBinaryExpression(node.operator, leftValue, self.cmpl_evaluate_nodeExpression(node.right)) + return rt.calculateBinaryExpression(node.operator, leftValue, rt.cmplEvaluateNodeExpression(node.right)) } -func (self *_runtime) cmpl_evaluate_nodeBinaryExpression_comparison(node *_nodeBinaryExpression) Value { +func (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left).resolve() + right := rt.cmplEvaluateNodeExpression(node.right).resolve() - left := self.cmpl_evaluate_nodeExpression(node.left).resolve() - right := self.cmpl_evaluate_nodeExpression(node.right).resolve() - - return toValue_bool(self.calculateComparison(node.operator, left, right)) + return boolValue(rt.calculateComparison(node.operator, left, right)) } -func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.left) targetValue := target.resolve() - member := self.cmpl_evaluate_nodeExpression(node.member) + member := rt.cmplEvaluateNodeExpression(node.member) memberValue := member.resolve() // TODO Pass in base value as-is, and defer toObject till later? - object, err := self.objectCoerce(targetValue) + obj, err := rt.objectCoerce(targetValue) if err != nil { - panic(self.panicTypeError("Cannot access member '%s' of %s", memberValue.string(), err.Error(), _at(node.idx))) + panic(rt.panicTypeError("Cannot access member %q of %s", memberValue.string(), err, at(node.idx))) } - return toValue(newPropertyReference(self, object, memberValue.string(), false, _at(node.idx))) + return toValue(newPropertyReference(rt, obj, memberValue.string(), false, at(node.idx))) } -func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value { - rt := self +func (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value { this := Value{} - callee := self.cmpl_evaluate_nodeExpression(node.callee) + callee := rt.cmplEvaluateNodeExpression(node.callee) argumentList := []Value{} if withArgumentList != nil { - argumentList = self.toValueArray(withArgumentList...) + argumentList = rt.toValueArray(withArgumentList...) } else { for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) + argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve()) } } - rf := callee.reference() - vl := callee.resolve() - eval := false // Whether this call is a (candidate for) direct call to eval name := "" - if rf != nil { + if rf := callee.reference(); rf != nil { switch rf := rf.(type) { - case *_propertyReference: + case *propertyReference: name = rf.name - object := rf.base - this = toValue_object(object) + this = objectValue(rf.base) eval = rf.name == "eval" // Possible direct eval - case *_stashReference: + case *stashReference: // TODO ImplicitThisValue name = rf.name eval = rf.name == "eval" // Possible direct eval default: // FIXME? - panic(rt.panicTypeError("Here be dragons")) + panic(rt.panicTypeError("unexpected callee type %T to node call expression", rf)) } } - at := _at(-1) + atv := at(-1) switch callee := node.callee.(type) { - case *_nodeIdentifier: - at = _at(callee.idx) - case *_nodeDotExpression: - at = _at(callee.idx) - case *_nodeBracketExpression: - at = _at(callee.idx) + case *nodeIdentifier: + atv = at(callee.idx) + case *nodeDotExpression: + atv = at(callee.idx) + case *nodeBracketExpression: + atv = at(callee.idx) } - frame := _frame{ + frm := frame{ callee: name, - file: self.scope.frame.file, + file: rt.scope.frame.file, } + vl := callee.resolve() if !vl.IsFunction() { if name == "" { // FIXME Maybe typeof? - panic(rt.panicTypeError("%v is not a function", vl, at)) + panic(rt.panicTypeError("%v is not a function", vl, atv)) } - panic(rt.panicTypeError("'%s' is not a function", name, at)) + panic(rt.panicTypeError("%q is not a function", name, atv)) } - self.scope.frame.offset = int(at) + rt.scope.frame.offset = int(atv) - return vl._object().call(this, argumentList, eval, frame) + return vl.object().call(this, argumentList, eval, frm) } -func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value { - test := self.cmpl_evaluate_nodeExpression(node.test) +func (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value { + test := rt.cmplEvaluateNodeExpression(node.test) testValue := test.resolve() if testValue.bool() { - return self.cmpl_evaluate_nodeExpression(node.consequent) + return rt.cmplEvaluateNodeExpression(node.consequent) } - return self.cmpl_evaluate_nodeExpression(node.alternate) + return rt.cmplEvaluateNodeExpression(node.alternate) } -func (self *_runtime) cmpl_evaluate_nodeDotExpression(node *_nodeDotExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.left) targetValue := target.resolve() // TODO Pass in base value as-is, and defer toObject till later? - object, err := self.objectCoerce(targetValue) + obj, err := rt.objectCoerce(targetValue) if err != nil { - panic(self.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error(), _at(node.idx))) + panic(rt.panicTypeError("Cannot access member %q of %s", node.identifier, err, at(node.idx))) } - return toValue(newPropertyReference(self, object, node.identifier, false, _at(node.idx))) + return toValue(newPropertyReference(rt, obj, node.identifier, false, at(node.idx))) } -func (self *_runtime) cmpl_evaluate_nodeNewExpression(node *_nodeNewExpression) Value { - rt := self - callee := self.cmpl_evaluate_nodeExpression(node.callee) +func (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value { + callee := rt.cmplEvaluateNodeExpression(node.callee) argumentList := []Value{} for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) + argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve()) } - rf := callee.reference() - vl := callee.resolve() - - name := "" - if rf != nil { + var name string + if rf := callee.reference(); rf != nil { switch rf := rf.(type) { - case *_propertyReference: + case *propertyReference: name = rf.name - case *_stashReference: + case *stashReference: name = rf.name default: - panic(rt.panicTypeError("Here be dragons")) + panic(rt.panicTypeError("node new expression unexpected callee type %T", rf)) } } - at := _at(-1) + atv := at(-1) switch callee := node.callee.(type) { - case *_nodeIdentifier: - at = _at(callee.idx) - case *_nodeDotExpression: - at = _at(callee.idx) - case *_nodeBracketExpression: - at = _at(callee.idx) + case *nodeIdentifier: + atv = at(callee.idx) + case *nodeDotExpression: + atv = at(callee.idx) + case *nodeBracketExpression: + atv = at(callee.idx) } + vl := callee.resolve() if !vl.IsFunction() { if name == "" { // FIXME Maybe typeof? - panic(rt.panicTypeError("%v is not a function", vl, at)) + panic(rt.panicTypeError("%v is not a function", vl, atv)) } - panic(rt.panicTypeError("'%s' is not a function", name, at)) + panic(rt.panicTypeError("'%s' is not a function", name, atv)) } - self.scope.frame.offset = int(at) + rt.scope.frame.offset = int(atv) - return vl._object().construct(argumentList) + return vl.object().construct(argumentList) } -func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) Value { - - result := self.newObject() - - for _, property := range node.value { - switch property.kind { +func (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value { + result := rt.newObject() + for _, prop := range node.value { + switch prop.kind { case "value": - result.defineProperty(property.key, self.cmpl_evaluate_nodeExpression(property.value).resolve(), 0111, false) + result.defineProperty(prop.key, rt.cmplEvaluateNodeExpression(prop.value).resolve(), 0o111, false) case "get": - getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) - descriptor := _property{} - descriptor.mode = 0211 - descriptor.value = _propertyGetSet{getter, nil} - result.defineOwnProperty(property.key, descriptor, false) + getter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical) + descriptor := property{} + descriptor.mode = 0o211 + descriptor.value = propertyGetSet{getter, nil} + result.defineOwnProperty(prop.key, descriptor, false) case "set": - setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) - descriptor := _property{} - descriptor.mode = 0211 - descriptor.value = _propertyGetSet{nil, setter} - result.defineOwnProperty(property.key, descriptor, false) + setter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical) + descriptor := property{} + descriptor.mode = 0o211 + descriptor.value = propertyGetSet{nil, setter} + result.defineOwnProperty(prop.key, descriptor, false) default: - panic(fmt.Errorf("Here be dragons: evaluate_nodeObjectLiteral: invalid property.Kind: %v", property.kind)) + panic(fmt.Sprintf("unknown node object literal property kind %T", prop.kind)) } } - return toValue_object(result) + return objectValue(result) } -func (self *_runtime) cmpl_evaluate_nodeSequenceExpression(node *_nodeSequenceExpression) Value { +func (rt *runtime) cmplEvaluateNodeSequenceExpression(node *nodeSequenceExpression) Value { var result Value for _, node := range node.sequence { - result = self.cmpl_evaluate_nodeExpression(node) + result = rt.cmplEvaluateNodeExpression(node) result = result.resolve() } return result } -func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpression) Value { - - target := self.cmpl_evaluate_nodeExpression(node.operand) +func (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.operand) switch node.operator { case token.TYPEOF, token.DELETE: if target.kind == valueReference && target.reference().invalid() { if node.operator == token.TYPEOF { - return toValue_string("undefined") + return stringValue("undefined") } return trueValue } @@ -371,10 +355,10 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi case token.BITWISE_NOT: targetValue := target.resolve() integerValue := toInt32(targetValue) - return toValue_int32(^integerValue) + return int32Value(^integerValue) case token.PLUS: targetValue := target.resolve() - return toValue_float64(targetValue.float64()) + return float64Value(targetValue.float64()) case token.MINUS: targetValue := target.resolve() value := targetValue.float64() @@ -383,35 +367,35 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi if math.Signbit(value) { sign = 1 } - return toValue_float64(math.Copysign(value, sign)) + return float64Value(math.Copysign(value, sign)) case token.INCREMENT: targetValue := target.resolve() if node.postfix { // Postfix++ oldValue := targetValue.float64() - newValue := toValue_float64(+1 + oldValue) - self.putValue(target.reference(), newValue) - return toValue_float64(oldValue) - } else { - // ++Prefix - newValue := toValue_float64(+1 + targetValue.float64()) - self.putValue(target.reference(), newValue) - return newValue + newValue := float64Value(+1 + oldValue) + rt.putValue(target.reference(), newValue) + return float64Value(oldValue) } + + // ++Prefix + newValue := float64Value(+1 + targetValue.float64()) + rt.putValue(target.reference(), newValue) + return newValue case token.DECREMENT: targetValue := target.resolve() if node.postfix { // Postfix-- oldValue := targetValue.float64() - newValue := toValue_float64(-1 + oldValue) - self.putValue(target.reference(), newValue) - return toValue_float64(oldValue) - } else { - // --Prefix - newValue := toValue_float64(-1 + targetValue.float64()) - self.putValue(target.reference(), newValue) - return newValue + newValue := float64Value(-1 + oldValue) + rt.putValue(target.reference(), newValue) + return float64Value(oldValue) } + + // --Prefix + newValue := float64Value(-1 + targetValue.float64()) + rt.putValue(target.reference(), newValue) + return newValue case token.VOID: target.resolve() // FIXME Side effect? return Value{} @@ -420,25 +404,25 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi if reference == nil { return trueValue } - return toValue_bool(target.reference().delete()) + return boolValue(target.reference().delete()) case token.TYPEOF: targetValue := target.resolve() switch targetValue.kind { case valueUndefined: - return toValue_string("undefined") + return stringValue("undefined") case valueNull: - return toValue_string("object") + return stringValue("object") case valueBoolean: - return toValue_string("boolean") + return stringValue("boolean") case valueNumber: - return toValue_string("number") + return stringValue("number") case valueString: - return toValue_string("string") + return stringValue("string") case valueObject: - if targetValue._object().isCall() { - return toValue_string("function") + if targetValue.object().isCall() { + return stringValue("function") } - return toValue_string("object") + return stringValue("object") default: // FIXME ? } @@ -447,14 +431,14 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi panic(hereBeDragons()) } -func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value { +func (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value { if node.initializer != nil { // FIXME If reference is nil - left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx)) - right := self.cmpl_evaluate_nodeExpression(node.initializer) + left := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx)) + right := rt.cmplEvaluateNodeExpression(node.initializer) rightValue := right.resolve() - self.putValue(left, rightValue) + rt.putValue(left, rightValue) } - return toValue_string(node.name) + return stringValue(node.name) } diff --git a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go index e16c6ac6c..724120ac3 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go @@ -2,123 +2,121 @@ package otto import ( "fmt" - "runtime" + goruntime "runtime" "github.com/robertkrimen/otto/token" ) -func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { +func (rt *runtime) cmplEvaluateNodeStatement(node nodeStatement) Value { // Allow interpreter interruption // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.otto.Interrupt != nil { - runtime.Gosched() + if rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } switch node := node.(type) { + case *nodeBlockStatement: + labels := rt.labels + rt.labels = nil - case *_nodeBlockStatement: - labels := self.labels - self.labels = nil - - value := self.cmpl_evaluate_nodeStatementList(node.list) - switch value.kind { - case valueResult: - switch value.evaluateBreak(labels) { - case resultBreak: + value := rt.cmplEvaluateNodeStatementList(node.list) + if value.kind == valueResult { + if value.evaluateBreak(labels) == resultBreak { return emptyValue } } return value - case *_nodeBranchStatement: + case *nodeBranchStatement: target := node.label switch node.branch { // FIXME Maybe node.kind? node.operator? case token.BREAK: return toValue(newBreakResult(target)) case token.CONTINUE: return toValue(newContinueResult(target)) + default: + panic(fmt.Errorf("unknown node branch token %T", node)) } - case *_nodeDebuggerStatement: - if self.debugger != nil { - self.debugger(self.otto) + case *nodeDebuggerStatement: + if rt.debugger != nil { + rt.debugger(rt.otto) } return emptyValue // Nothing happens. - case *_nodeDoWhileStatement: - return self.cmpl_evaluate_nodeDoWhileStatement(node) + case *nodeDoWhileStatement: + return rt.cmplEvaluateNodeDoWhileStatement(node) - case *_nodeEmptyStatement: + case *nodeEmptyStatement: return emptyValue - case *_nodeExpressionStatement: - return self.cmpl_evaluate_nodeExpression(node.expression) + case *nodeExpressionStatement: + return rt.cmplEvaluateNodeExpression(node.expression) - case *_nodeForInStatement: - return self.cmpl_evaluate_nodeForInStatement(node) + case *nodeForInStatement: + return rt.cmplEvaluateNodeForInStatement(node) - case *_nodeForStatement: - return self.cmpl_evaluate_nodeForStatement(node) + case *nodeForStatement: + return rt.cmplEvaluateNodeForStatement(node) - case *_nodeIfStatement: - return self.cmpl_evaluate_nodeIfStatement(node) + case *nodeIfStatement: + return rt.cmplEvaluateNodeIfStatement(node) - case *_nodeLabelledStatement: - self.labels = append(self.labels, node.label) + case *nodeLabelledStatement: + rt.labels = append(rt.labels, node.label) defer func() { - if len(self.labels) > 0 { - self.labels = self.labels[:len(self.labels)-1] // Pop the label + if len(rt.labels) > 0 { + rt.labels = rt.labels[:len(rt.labels)-1] // Pop the label } else { - self.labels = nil + rt.labels = nil } }() - return self.cmpl_evaluate_nodeStatement(node.statement) + return rt.cmplEvaluateNodeStatement(node.statement) - case *_nodeReturnStatement: + case *nodeReturnStatement: if node.argument != nil { - return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve())) + return toValue(newReturnResult(rt.cmplEvaluateNodeExpression(node.argument).resolve())) } return toValue(newReturnResult(Value{})) - case *_nodeSwitchStatement: - return self.cmpl_evaluate_nodeSwitchStatement(node) + case *nodeSwitchStatement: + return rt.cmplEvaluateNodeSwitchStatement(node) - case *_nodeThrowStatement: - value := self.cmpl_evaluate_nodeExpression(node.argument).resolve() + case *nodeThrowStatement: + value := rt.cmplEvaluateNodeExpression(node.argument).resolve() panic(newException(value)) - case *_nodeTryStatement: - return self.cmpl_evaluate_nodeTryStatement(node) + case *nodeTryStatement: + return rt.cmplEvaluateNodeTryStatement(node) - case *_nodeVariableStatement: + case *nodeVariableStatement: // Variables are already defined, this is initialization only for _, variable := range node.list { - self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression)) + rt.cmplEvaluateNodeVariableExpression(variable.(*nodeVariableExpression)) } return emptyValue - case *_nodeWhileStatement: - return self.cmpl_evaluate_nodeWhileStatement(node) - - case *_nodeWithStatement: - return self.cmpl_evaluate_nodeWithStatement(node) + case *nodeWhileStatement: + return rt.cmplEvaluateModeWhileStatement(node) + case *nodeWithStatement: + return rt.cmplEvaluateNodeWithStatement(node) + default: + panic(fmt.Errorf("unknown node statement type %T", node)) } - - panic(fmt.Errorf("Here be dragons: evaluate_nodeStatement(%T)", node)) } -func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Value { +func (rt *runtime) cmplEvaluateNodeStatementList(list []nodeStatement) Value { var result Value for _, node := range list { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: return value @@ -135,10 +133,9 @@ func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Val return result } -func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileStatement) Value { - - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeDoWhileStatement(node *nodeDoWhileStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil test := node.test @@ -146,7 +143,7 @@ func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileState resultBreak: for { for _, node := range node.body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -163,7 +160,7 @@ resultBreak: } } resultContinue: - if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { + if !rt.cmplEvaluateNodeExpression(test).resolve().bool() { // Stahp: do ... while (false) break } @@ -171,12 +168,11 @@ resultBreak: return result } -func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement) Value { - - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeForInStatement(node *nodeForInStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil - source := self.cmpl_evaluate_nodeExpression(node.source) + source := rt.cmplEvaluateNodeExpression(node.source) sourceValue := source.resolve() switch sourceValue.kind { @@ -184,26 +180,26 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement return emptyValue } - sourceObject := self.toObject(sourceValue) + sourceObject := rt.toObject(sourceValue) into := node.into body := node.body result := emptyValue - object := sourceObject - for object != nil { + obj := sourceObject + for obj != nil { enumerateValue := emptyValue - object.enumerate(false, func(name string) bool { - into := self.cmpl_evaluate_nodeExpression(into) + obj.enumerate(false, func(name string) bool { + into := rt.cmplEvaluateNodeExpression(into) // In the case of: for (var abc in def) ... if into.reference() == nil { identifier := into.string() // TODO Should be true or false (strictness) depending on context - into = toValue(getIdentifierReference(self, self.scope.lexical, identifier, false, -1)) + into = toValue(getIdentifierReference(rt, rt.scope.lexical, identifier, false, -1)) } - self.putValue(into.reference(), toValue_string(name)) + rt.putValue(into.reference(), stringValue(name)) for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -211,7 +207,7 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement enumerateValue = value return false case resultBreak: - object = nil + obj = nil return false case resultContinue: return true @@ -223,10 +219,10 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement } return true }) - if object == nil { + if obj == nil { break } - object = object.prototype + obj = obj.prototype if !enumerateValue.isEmpty() { result = enumerateValue } @@ -234,10 +230,9 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement return result } -func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Value { - - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeForStatement(node *nodeForStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil initializer := node.initializer test := node.test @@ -245,7 +240,7 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va body := node.body if initializer != nil { - initialResult := self.cmpl_evaluate_nodeExpression(initializer) + initialResult := rt.cmplEvaluateNodeExpression(initializer) initialResult.resolve() // Side-effect trigger } @@ -253,14 +248,25 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va resultBreak: for { if test != nil { - testResult := self.cmpl_evaluate_nodeExpression(test) + testResult := rt.cmplEvaluateNodeExpression(test) testResultValue := testResult.resolve() - if testResultValue.bool() == false { + if !testResultValue.bool() { break } } + + // this is to prevent for cycles with no body from running forever + if len(body) == 0 && rt.otto.Interrupt != nil { + goruntime.Gosched() + select { + case value := <-rt.otto.Interrupt: + value() + default: + } + } + for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -278,37 +284,36 @@ resultBreak: } resultContinue: if update != nil { - updateResult := self.cmpl_evaluate_nodeExpression(update) + updateResult := rt.cmplEvaluateNodeExpression(update) updateResult.resolve() // Side-effect trigger } } return result } -func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value { - test := self.cmpl_evaluate_nodeExpression(node.test) +func (rt *runtime) cmplEvaluateNodeIfStatement(node *nodeIfStatement) Value { + test := rt.cmplEvaluateNodeExpression(node.test) testValue := test.resolve() if testValue.bool() { - return self.cmpl_evaluate_nodeStatement(node.consequent) + return rt.cmplEvaluateNodeStatement(node.consequent) } else if node.alternate != nil { - return self.cmpl_evaluate_nodeStatement(node.alternate) + return rt.cmplEvaluateNodeStatement(node.alternate) } return emptyValue } -func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value { +func (rt *runtime) cmplEvaluateNodeSwitchStatement(node *nodeSwitchStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil - labels := append(self.labels, "") - self.labels = nil - - discriminantResult := self.cmpl_evaluate_nodeExpression(node.discriminant) - target := node.default_ + discriminantResult := rt.cmplEvaluateNodeExpression(node.discriminant) + target := node.defaultIdx for index, clause := range node.body { test := clause.test if test != nil { - if self.calculateComparison(token.STRICT_EQUAL, discriminantResult, self.cmpl_evaluate_nodeExpression(test)) { + if rt.calculateComparison(token.STRICT_EQUAL, discriminantResult, rt.cmplEvaluateNodeExpression(test)) { target = index break } @@ -319,7 +324,7 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme if target != -1 { for _, clause := range node.body[target:] { for _, statement := range clause.consequent { - value := self.cmpl_evaluate_nodeStatement(statement) + value := rt.cmplEvaluateNodeStatement(statement) switch value.kind { case valueResult: switch value.evaluateBreak(labels) { @@ -339,59 +344,58 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme return result } -func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Value { - tryCatchValue, exception := self.tryCatchEvaluate(func() Value { - return self.cmpl_evaluate_nodeStatement(node.body) +func (rt *runtime) cmplEvaluateNodeTryStatement(node *nodeTryStatement) Value { + tryCatchValue, exep := rt.tryCatchEvaluate(func() Value { + return rt.cmplEvaluateNodeStatement(node.body) }) - if exception && node.catch != nil { - outer := self.scope.lexical - self.scope.lexical = self.newDeclarationStash(outer) + if exep && node.catch != nil { + outer := rt.scope.lexical + rt.scope.lexical = rt.newDeclarationStash(outer) defer func() { - self.scope.lexical = outer + rt.scope.lexical = outer }() // TODO If necessary, convert TypeError => TypeError // That, is, such errors can be thrown despite not being JavaScript "native" // strict = false - self.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) + rt.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) // FIXME node.CatchParameter // FIXME node.Catch - tryCatchValue, exception = self.tryCatchEvaluate(func() Value { - return self.cmpl_evaluate_nodeStatement(node.catch.body) + tryCatchValue, exep = rt.tryCatchEvaluate(func() Value { + return rt.cmplEvaluateNodeStatement(node.catch.body) }) } if node.finally != nil { - finallyValue := self.cmpl_evaluate_nodeStatement(node.finally) + finallyValue := rt.cmplEvaluateNodeStatement(node.finally) if finallyValue.kind == valueResult { return finallyValue } } - if exception { + if exep { panic(newException(tryCatchValue)) } return tryCatchValue } -func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement) Value { - +func (rt *runtime) cmplEvaluateModeWhileStatement(node *nodeWhileStatement) Value { test := node.test body := node.body - labels := append(self.labels, "") - self.labels = nil + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil result := emptyValue resultBreakContinue: for { - if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { + if !rt.cmplEvaluateNodeExpression(test).resolve().bool() { // Stahp: while (false) ... break } for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -411,14 +415,14 @@ resultBreakContinue: return result } -func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value { - object := self.cmpl_evaluate_nodeExpression(node.object) - outer := self.scope.lexical - lexical := self.newObjectStash(self.toObject(object.resolve()), outer) - self.scope.lexical = lexical +func (rt *runtime) cmplEvaluateNodeWithStatement(node *nodeWithStatement) Value { + obj := rt.cmplEvaluateNodeExpression(node.object) + outer := rt.scope.lexical + lexical := rt.newObjectStash(rt.toObject(obj.resolve()), outer) + rt.scope.lexical = lexical defer func() { - self.scope.lexical = outer + rt.scope.lexical = outer }() - return self.cmpl_evaluate_nodeStatement(node.body) + return rt.cmplEvaluateNodeStatement(node.body) } diff --git a/vendor/github.com/robertkrimen/otto/cmpl_parse.go b/vendor/github.com/robertkrimen/otto/cmpl_parse.go index dc5baa12a..d3fe8da55 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_parse.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_parse.go @@ -2,84 +2,84 @@ package otto import ( "fmt" - "regexp" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/token" ) -var trueLiteral = &_nodeLiteral{value: toValue_bool(true)} -var falseLiteral = &_nodeLiteral{value: toValue_bool(false)} -var nullLiteral = &_nodeLiteral{value: nullValue} -var emptyStatement = &_nodeEmptyStatement{} +var ( + trueLiteral = &nodeLiteral{value: boolValue(true)} + falseLiteral = &nodeLiteral{value: boolValue(false)} + nullLiteral = &nodeLiteral{value: nullValue} + emptyStatement = &nodeEmptyStatement{} +) -func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { - if in == nil { +func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression { + if expr == nil { return nil } - switch in := in.(type) { - + switch expr := expr.(type) { case *ast.ArrayLiteral: - out := &_nodeArrayLiteral{ - value: make([]_nodeExpression, len(in.Value)), + out := &nodeArrayLiteral{ + value: make([]nodeExpression, len(expr.Value)), } - for i, value := range in.Value { + for i, value := range expr.Value { out.value[i] = cmpl.parseExpression(value) } return out case *ast.AssignExpression: - return &_nodeAssignExpression{ - operator: in.Operator, - left: cmpl.parseExpression(in.Left), - right: cmpl.parseExpression(in.Right), + return &nodeAssignExpression{ + operator: expr.Operator, + left: cmpl.parseExpression(expr.Left), + right: cmpl.parseExpression(expr.Right), } case *ast.BinaryExpression: - return &_nodeBinaryExpression{ - operator: in.Operator, - left: cmpl.parseExpression(in.Left), - right: cmpl.parseExpression(in.Right), - comparison: in.Comparison, + return &nodeBinaryExpression{ + operator: expr.Operator, + left: cmpl.parseExpression(expr.Left), + right: cmpl.parseExpression(expr.Right), + comparison: expr.Comparison, } case *ast.BooleanLiteral: - if in.Value { + if expr.Value { return trueLiteral } return falseLiteral case *ast.BracketExpression: - return &_nodeBracketExpression{ - idx: in.Left.Idx0(), - left: cmpl.parseExpression(in.Left), - member: cmpl.parseExpression(in.Member), + return &nodeBracketExpression{ + idx: expr.Left.Idx0(), + left: cmpl.parseExpression(expr.Left), + member: cmpl.parseExpression(expr.Member), } case *ast.CallExpression: - out := &_nodeCallExpression{ - callee: cmpl.parseExpression(in.Callee), - argumentList: make([]_nodeExpression, len(in.ArgumentList)), + out := &nodeCallExpression{ + callee: cmpl.parseExpression(expr.Callee), + argumentList: make([]nodeExpression, len(expr.ArgumentList)), } - for i, value := range in.ArgumentList { + for i, value := range expr.ArgumentList { out.argumentList[i] = cmpl.parseExpression(value) } return out case *ast.ConditionalExpression: - return &_nodeConditionalExpression{ - test: cmpl.parseExpression(in.Test), - consequent: cmpl.parseExpression(in.Consequent), - alternate: cmpl.parseExpression(in.Alternate), + return &nodeConditionalExpression{ + test: cmpl.parseExpression(expr.Test), + consequent: cmpl.parseExpression(expr.Consequent), + alternate: cmpl.parseExpression(expr.Alternate), } case *ast.DotExpression: - return &_nodeDotExpression{ - idx: in.Left.Idx0(), - left: cmpl.parseExpression(in.Left), - identifier: in.Identifier.Name, + return &nodeDotExpression{ + idx: expr.Left.Idx0(), + left: cmpl.parseExpression(expr.Left), + identifier: expr.Identifier.Name, } case *ast.EmptyExpression: @@ -87,48 +87,48 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { case *ast.FunctionLiteral: name := "" - if in.Name != nil { - name = in.Name.Name + if expr.Name != nil { + name = expr.Name.Name } - out := &_nodeFunctionLiteral{ + out := &nodeFunctionLiteral{ name: name, - body: cmpl.parseStatement(in.Body), - source: in.Source, + body: cmpl.parseStatement(expr.Body), + source: expr.Source, file: cmpl.file, } - if in.ParameterList != nil { - list := in.ParameterList.List + if expr.ParameterList != nil { + list := expr.ParameterList.List out.parameterList = make([]string, len(list)) for i, value := range list { out.parameterList[i] = value.Name } } - for _, value := range in.DeclarationList { + for _, value := range expr.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value)) + panic(fmt.Sprintf("parse expression unknown function declaration type %T", value)) } } return out case *ast.Identifier: - return &_nodeIdentifier{ - idx: in.Idx, - name: in.Name, + return &nodeIdentifier{ + idx: expr.Idx, + name: expr.Name, } case *ast.NewExpression: - out := &_nodeNewExpression{ - callee: cmpl.parseExpression(in.Callee), - argumentList: make([]_nodeExpression, len(in.ArgumentList)), + out := &nodeNewExpression{ + callee: cmpl.parseExpression(expr.Callee), + argumentList: make([]nodeExpression, len(expr.ArgumentList)), } - for i, value := range in.ArgumentList { + for i, value := range expr.ArgumentList { out.argumentList[i] = cmpl.parseExpression(value) } return out @@ -137,16 +137,16 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { return nullLiteral case *ast.NumberLiteral: - return &_nodeLiteral{ - value: toValue(in.Value), + return &nodeLiteral{ + value: toValue(expr.Value), } case *ast.ObjectLiteral: - out := &_nodeObjectLiteral{ - value: make([]_nodeProperty, len(in.Value)), + out := &nodeObjectLiteral{ + value: make([]nodeProperty, len(expr.Value)), } - for i, value := range in.Value { - out.value[i] = _nodeProperty{ + for i, value := range expr.Value { + out.value[i] = nodeProperty{ key: value.Key, kind: value.Kind, value: cmpl.parseExpression(value.Value), @@ -155,81 +155,79 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { return out case *ast.RegExpLiteral: - return &_nodeRegExpLiteral{ - flags: in.Flags, - pattern: in.Pattern, + return &nodeRegExpLiteral{ + flags: expr.Flags, + pattern: expr.Pattern, } case *ast.SequenceExpression: - out := &_nodeSequenceExpression{ - sequence: make([]_nodeExpression, len(in.Sequence)), + out := &nodeSequenceExpression{ + sequence: make([]nodeExpression, len(expr.Sequence)), } - for i, value := range in.Sequence { + for i, value := range expr.Sequence { out.sequence[i] = cmpl.parseExpression(value) } return out case *ast.StringLiteral: - return &_nodeLiteral{ - value: toValue_string(in.Value), + return &nodeLiteral{ + value: stringValue(expr.Value), } case *ast.ThisExpression: - return &_nodeThisExpression{} + return &nodeThisExpression{} case *ast.UnaryExpression: - return &_nodeUnaryExpression{ - operator: in.Operator, - operand: cmpl.parseExpression(in.Operand), - postfix: in.Postfix, + return &nodeUnaryExpression{ + operator: expr.Operator, + operand: cmpl.parseExpression(expr.Operand), + postfix: expr.Postfix, } case *ast.VariableExpression: - return &_nodeVariableExpression{ - idx: in.Idx0(), - name: in.Name, - initializer: cmpl.parseExpression(in.Initializer), + return &nodeVariableExpression{ + idx: expr.Idx0(), + name: expr.Name, + initializer: cmpl.parseExpression(expr.Initializer), } - + default: + panic(fmt.Errorf("parse expression unknown node type %T", expr)) } - - panic(fmt.Errorf("Here be dragons: cmpl.parseExpression(%T)", in)) } -func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { - if in == nil { +func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement { + if stmt == nil { return nil } - switch in := in.(type) { - + switch stmt := stmt.(type) { case *ast.BlockStatement: - out := &_nodeBlockStatement{ - list: make([]_nodeStatement, len(in.List)), + out := &nodeBlockStatement{ + list: make([]nodeStatement, len(stmt.List)), } - for i, value := range in.List { + for i, value := range stmt.List { out.list[i] = cmpl.parseStatement(value) } return out case *ast.BranchStatement: - out := &_nodeBranchStatement{ - branch: in.Token, + out := &nodeBranchStatement{ + branch: stmt.Token, } - if in.Label != nil { - out.label = in.Label.Name + if stmt.Label != nil { + out.label = stmt.Label.Name } return out case *ast.DebuggerStatement: - return &_nodeDebuggerStatement{} + return &nodeDebuggerStatement{} case *ast.DoWhileStatement: - out := &_nodeDoWhileStatement{ - test: cmpl.parseExpression(in.Test), + out := &nodeDoWhileStatement{ + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -240,17 +238,17 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return emptyStatement case *ast.ExpressionStatement: - return &_nodeExpressionStatement{ - expression: cmpl.parseExpression(in.Expression), + return &nodeExpressionStatement{ + expression: cmpl.parseExpression(stmt.Expression), } case *ast.ForInStatement: - out := &_nodeForInStatement{ - into: cmpl.parseExpression(in.Into), - source: cmpl.parseExpression(in.Source), + out := &nodeForInStatement{ + into: cmpl.parseExpression(stmt.Into), + source: cmpl.parseExpression(stmt.Source), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -258,13 +256,13 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.ForStatement: - out := &_nodeForStatement{ - initializer: cmpl.parseExpression(in.Initializer), - update: cmpl.parseExpression(in.Update), - test: cmpl.parseExpression(in.Test), + out := &nodeForStatement{ + initializer: cmpl.parseExpression(stmt.Initializer), + update: cmpl.parseExpression(stmt.Update), + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -275,33 +273,33 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return emptyStatement case *ast.IfStatement: - return &_nodeIfStatement{ - test: cmpl.parseExpression(in.Test), - consequent: cmpl.parseStatement(in.Consequent), - alternate: cmpl.parseStatement(in.Alternate), + return &nodeIfStatement{ + test: cmpl.parseExpression(stmt.Test), + consequent: cmpl.parseStatement(stmt.Consequent), + alternate: cmpl.parseStatement(stmt.Alternate), } case *ast.LabelledStatement: - return &_nodeLabelledStatement{ - label: in.Label.Name, - statement: cmpl.parseStatement(in.Statement), + return &nodeLabelledStatement{ + label: stmt.Label.Name, + statement: cmpl.parseStatement(stmt.Statement), } case *ast.ReturnStatement: - return &_nodeReturnStatement{ - argument: cmpl.parseExpression(in.Argument), + return &nodeReturnStatement{ + argument: cmpl.parseExpression(stmt.Argument), } case *ast.SwitchStatement: - out := &_nodeSwitchStatement{ - discriminant: cmpl.parseExpression(in.Discriminant), - default_: in.Default, - body: make([]*_nodeCaseStatement, len(in.Body)), + out := &nodeSwitchStatement{ + discriminant: cmpl.parseExpression(stmt.Discriminant), + defaultIdx: stmt.Default, + body: make([]*nodeCaseStatement, len(stmt.Body)), } - for i, clause := range in.Body { - out.body[i] = &_nodeCaseStatement{ + for i, clause := range stmt.Body { + out.body[i] = &nodeCaseStatement{ test: cmpl.parseExpression(clause.Test), - consequent: make([]_nodeStatement, len(clause.Consequent)), + consequent: make([]nodeStatement, len(clause.Consequent)), } for j, value := range clause.Consequent { out.body[i].consequent[j] = cmpl.parseStatement(value) @@ -310,38 +308,38 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.ThrowStatement: - return &_nodeThrowStatement{ - argument: cmpl.parseExpression(in.Argument), + return &nodeThrowStatement{ + argument: cmpl.parseExpression(stmt.Argument), } case *ast.TryStatement: - out := &_nodeTryStatement{ - body: cmpl.parseStatement(in.Body), - finally: cmpl.parseStatement(in.Finally), - } - if in.Catch != nil { - out.catch = &_nodeCatchStatement{ - parameter: in.Catch.Parameter.Name, - body: cmpl.parseStatement(in.Catch.Body), + out := &nodeTryStatement{ + body: cmpl.parseStatement(stmt.Body), + finally: cmpl.parseStatement(stmt.Finally), + } + if stmt.Catch != nil { + out.catch = &nodeCatchStatement{ + parameter: stmt.Catch.Parameter.Name, + body: cmpl.parseStatement(stmt.Catch.Body), } } return out case *ast.VariableStatement: - out := &_nodeVariableStatement{ - list: make([]_nodeExpression, len(in.List)), + out := &nodeVariableStatement{ + list: make([]nodeExpression, len(stmt.List)), } - for i, value := range in.List { + for i, value := range stmt.List { out.list[i] = cmpl.parseExpression(value) } return out case *ast.WhileStatement: - out := &_nodeWhileStatement{ - test: cmpl.parseExpression(in.Test), + out := &nodeWhileStatement{ + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -349,308 +347,296 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.WithStatement: - return &_nodeWithStatement{ - object: cmpl.parseExpression(in.Object), - body: cmpl.parseStatement(in.Body), + return &nodeWithStatement{ + object: cmpl.parseExpression(stmt.Object), + body: cmpl.parseStatement(stmt.Body), } - + default: + panic(fmt.Sprintf("parse statement: unknown type %T", stmt)) } - - panic(fmt.Errorf("Here be dragons: cmpl.parseStatement(%T)", in)) } -func cmpl_parse(in *ast.Program) *_nodeProgram { - cmpl := _compiler{ +func cmplParse(in *ast.Program) *nodeProgram { + cmpl := compiler{ program: in, } + if cmpl.program != nil { + cmpl.file = cmpl.program.File + } + return cmpl.parse() } -func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram { - out := &_nodeProgram{ - body: make([]_nodeStatement, len(in.Body)), - file: in.File, +func (cmpl *compiler) parse() *nodeProgram { + out := &nodeProgram{ + body: make([]nodeStatement, len(cmpl.program.Body)), + file: cmpl.program.File, } - for i, value := range in.Body { + for i, value := range cmpl.program.Body { out.body[i] = cmpl.parseStatement(value) } - for _, value := range in.DeclarationList { + for _, value := range cmpl.program.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) + panic(fmt.Sprintf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) } } return out } -type _nodeProgram struct { - body []_nodeStatement - +type nodeProgram struct { + file *file.File + body []nodeStatement varList []string - functionList []*_nodeFunctionLiteral - - variableList []_nodeDeclaration - - file *file.File -} - -type _nodeDeclaration struct { - name string - definition _node + functionList []*nodeFunctionLiteral } -type _node interface { -} +type node interface{} type ( - _nodeExpression interface { - _node - _expressionNode() + nodeExpression interface { + node + expressionNode() } - _nodeArrayLiteral struct { - value []_nodeExpression + nodeArrayLiteral struct { + value []nodeExpression } - _nodeAssignExpression struct { + nodeAssignExpression struct { + left nodeExpression + right nodeExpression operator token.Token - left _nodeExpression - right _nodeExpression } - _nodeBinaryExpression struct { + nodeBinaryExpression struct { + left nodeExpression + right nodeExpression operator token.Token - left _nodeExpression - right _nodeExpression comparison bool } - _nodeBracketExpression struct { + nodeBracketExpression struct { + left nodeExpression + member nodeExpression idx file.Idx - left _nodeExpression - member _nodeExpression } - _nodeCallExpression struct { - callee _nodeExpression - argumentList []_nodeExpression + nodeCallExpression struct { + callee nodeExpression + argumentList []nodeExpression } - _nodeConditionalExpression struct { - test _nodeExpression - consequent _nodeExpression - alternate _nodeExpression + nodeConditionalExpression struct { + test nodeExpression + consequent nodeExpression + alternate nodeExpression } - _nodeDotExpression struct { - idx file.Idx - left _nodeExpression + nodeDotExpression struct { + left nodeExpression identifier string + idx file.Idx } - _nodeFunctionLiteral struct { + nodeFunctionLiteral struct { + body nodeStatement + file *file.File name string - body _nodeStatement source string parameterList []string varList []string - functionList []*_nodeFunctionLiteral - file *file.File + functionList []*nodeFunctionLiteral } - _nodeIdentifier struct { - idx file.Idx + nodeIdentifier struct { name string + idx file.Idx } - _nodeLiteral struct { + nodeLiteral struct { value Value } - _nodeNewExpression struct { - callee _nodeExpression - argumentList []_nodeExpression + nodeNewExpression struct { + callee nodeExpression + argumentList []nodeExpression } - _nodeObjectLiteral struct { - value []_nodeProperty + nodeObjectLiteral struct { + value []nodeProperty } - _nodeProperty struct { + nodeProperty struct { + value nodeExpression key string kind string - value _nodeExpression } - _nodeRegExpLiteral struct { + nodeRegExpLiteral struct { flags string pattern string // Value? - regexp *regexp.Regexp } - _nodeSequenceExpression struct { - sequence []_nodeExpression + nodeSequenceExpression struct { + sequence []nodeExpression } - _nodeThisExpression struct { - } + nodeThisExpression struct{} - _nodeUnaryExpression struct { + nodeUnaryExpression struct { + operand nodeExpression operator token.Token - operand _nodeExpression postfix bool } - _nodeVariableExpression struct { - idx file.Idx + nodeVariableExpression struct { + initializer nodeExpression name string - initializer _nodeExpression + idx file.Idx } ) type ( - _nodeStatement interface { - _node - _statementNode() + nodeStatement interface { + node + statementNode() } - _nodeBlockStatement struct { - list []_nodeStatement + nodeBlockStatement struct { + list []nodeStatement } - _nodeBranchStatement struct { - branch token.Token + nodeBranchStatement struct { label string + branch token.Token } - _nodeCaseStatement struct { - test _nodeExpression - consequent []_nodeStatement + nodeCaseStatement struct { + test nodeExpression + consequent []nodeStatement } - _nodeCatchStatement struct { + nodeCatchStatement struct { + body nodeStatement parameter string - body _nodeStatement } - _nodeDebuggerStatement struct { - } + nodeDebuggerStatement struct{} - _nodeDoWhileStatement struct { - test _nodeExpression - body []_nodeStatement + nodeDoWhileStatement struct { + test nodeExpression + body []nodeStatement } - _nodeEmptyStatement struct { - } + nodeEmptyStatement struct{} - _nodeExpressionStatement struct { - expression _nodeExpression + nodeExpressionStatement struct { + expression nodeExpression } - _nodeForInStatement struct { - into _nodeExpression - source _nodeExpression - body []_nodeStatement + nodeForInStatement struct { + into nodeExpression + source nodeExpression + body []nodeStatement } - _nodeForStatement struct { - initializer _nodeExpression - update _nodeExpression - test _nodeExpression - body []_nodeStatement + nodeForStatement struct { + initializer nodeExpression + update nodeExpression + test nodeExpression + body []nodeStatement } - _nodeIfStatement struct { - test _nodeExpression - consequent _nodeStatement - alternate _nodeStatement + nodeIfStatement struct { + test nodeExpression + consequent nodeStatement + alternate nodeStatement } - _nodeLabelledStatement struct { + nodeLabelledStatement struct { + statement nodeStatement label string - statement _nodeStatement } - _nodeReturnStatement struct { - argument _nodeExpression + nodeReturnStatement struct { + argument nodeExpression } - _nodeSwitchStatement struct { - discriminant _nodeExpression - default_ int - body []*_nodeCaseStatement + nodeSwitchStatement struct { + discriminant nodeExpression + body []*nodeCaseStatement + defaultIdx int } - _nodeThrowStatement struct { - argument _nodeExpression + nodeThrowStatement struct { + argument nodeExpression } - _nodeTryStatement struct { - body _nodeStatement - catch *_nodeCatchStatement - finally _nodeStatement + nodeTryStatement struct { + body nodeStatement + catch *nodeCatchStatement + finally nodeStatement } - _nodeVariableStatement struct { - list []_nodeExpression + nodeVariableStatement struct { + list []nodeExpression } - _nodeWhileStatement struct { - test _nodeExpression - body []_nodeStatement + nodeWhileStatement struct { + test nodeExpression + body []nodeStatement } - _nodeWithStatement struct { - object _nodeExpression - body _nodeStatement + nodeWithStatement struct { + object nodeExpression + body nodeStatement } ) -// _expressionNode - -func (*_nodeArrayLiteral) _expressionNode() {} -func (*_nodeAssignExpression) _expressionNode() {} -func (*_nodeBinaryExpression) _expressionNode() {} -func (*_nodeBracketExpression) _expressionNode() {} -func (*_nodeCallExpression) _expressionNode() {} -func (*_nodeConditionalExpression) _expressionNode() {} -func (*_nodeDotExpression) _expressionNode() {} -func (*_nodeFunctionLiteral) _expressionNode() {} -func (*_nodeIdentifier) _expressionNode() {} -func (*_nodeLiteral) _expressionNode() {} -func (*_nodeNewExpression) _expressionNode() {} -func (*_nodeObjectLiteral) _expressionNode() {} -func (*_nodeRegExpLiteral) _expressionNode() {} -func (*_nodeSequenceExpression) _expressionNode() {} -func (*_nodeThisExpression) _expressionNode() {} -func (*_nodeUnaryExpression) _expressionNode() {} -func (*_nodeVariableExpression) _expressionNode() {} - -// _statementNode - -func (*_nodeBlockStatement) _statementNode() {} -func (*_nodeBranchStatement) _statementNode() {} -func (*_nodeCaseStatement) _statementNode() {} -func (*_nodeCatchStatement) _statementNode() {} -func (*_nodeDebuggerStatement) _statementNode() {} -func (*_nodeDoWhileStatement) _statementNode() {} -func (*_nodeEmptyStatement) _statementNode() {} -func (*_nodeExpressionStatement) _statementNode() {} -func (*_nodeForInStatement) _statementNode() {} -func (*_nodeForStatement) _statementNode() {} -func (*_nodeIfStatement) _statementNode() {} -func (*_nodeLabelledStatement) _statementNode() {} -func (*_nodeReturnStatement) _statementNode() {} -func (*_nodeSwitchStatement) _statementNode() {} -func (*_nodeThrowStatement) _statementNode() {} -func (*_nodeTryStatement) _statementNode() {} -func (*_nodeVariableStatement) _statementNode() {} -func (*_nodeWhileStatement) _statementNode() {} -func (*_nodeWithStatement) _statementNode() {} +// expressionNode. +func (*nodeArrayLiteral) expressionNode() {} +func (*nodeAssignExpression) expressionNode() {} +func (*nodeBinaryExpression) expressionNode() {} +func (*nodeBracketExpression) expressionNode() {} +func (*nodeCallExpression) expressionNode() {} +func (*nodeConditionalExpression) expressionNode() {} +func (*nodeDotExpression) expressionNode() {} +func (*nodeFunctionLiteral) expressionNode() {} +func (*nodeIdentifier) expressionNode() {} +func (*nodeLiteral) expressionNode() {} +func (*nodeNewExpression) expressionNode() {} +func (*nodeObjectLiteral) expressionNode() {} +func (*nodeRegExpLiteral) expressionNode() {} +func (*nodeSequenceExpression) expressionNode() {} +func (*nodeThisExpression) expressionNode() {} +func (*nodeUnaryExpression) expressionNode() {} +func (*nodeVariableExpression) expressionNode() {} + +// statementNode + +func (*nodeBlockStatement) statementNode() {} +func (*nodeBranchStatement) statementNode() {} +func (*nodeCaseStatement) statementNode() {} +func (*nodeCatchStatement) statementNode() {} +func (*nodeDebuggerStatement) statementNode() {} +func (*nodeDoWhileStatement) statementNode() {} +func (*nodeEmptyStatement) statementNode() {} +func (*nodeExpressionStatement) statementNode() {} +func (*nodeForInStatement) statementNode() {} +func (*nodeForStatement) statementNode() {} +func (*nodeIfStatement) statementNode() {} +func (*nodeLabelledStatement) statementNode() {} +func (*nodeReturnStatement) statementNode() {} +func (*nodeSwitchStatement) statementNode() {} +func (*nodeThrowStatement) statementNode() {} +func (*nodeTryStatement) statementNode() {} +func (*nodeVariableStatement) statementNode() {} +func (*nodeWhileStatement) statementNode() {} +func (*nodeWithStatement) statementNode() {} diff --git a/vendor/github.com/robertkrimen/otto/console.go b/vendor/github.com/robertkrimen/otto/console.go index 948face77..e8d99cf7d 100644 --- a/vendor/github.com/robertkrimen/otto/console.go +++ b/vendor/github.com/robertkrimen/otto/console.go @@ -14,38 +14,33 @@ func formatForConsole(argumentList []Value) string { return strings.Join(output, " ") } -func builtinConsole_log(call FunctionCall) Value { - fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) +func builtinConsoleLog(call FunctionCall) Value { + fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. return Value{} } -func builtinConsole_error(call FunctionCall) Value { - fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) +func builtinConsoleError(call FunctionCall) Value { + fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. return Value{} } // Nothing happens. -func builtinConsole_dir(call FunctionCall) Value { +func builtinConsoleDir(call FunctionCall) Value { return Value{} } -func builtinConsole_time(call FunctionCall) Value { +func builtinConsoleTime(call FunctionCall) Value { return Value{} } -func builtinConsole_timeEnd(call FunctionCall) Value { +func builtinConsoleTimeEnd(call FunctionCall) Value { return Value{} } -func builtinConsole_trace(call FunctionCall) Value { +func builtinConsoleTrace(call FunctionCall) Value { return Value{} } -func builtinConsole_assert(call FunctionCall) Value { +func builtinConsoleAssert(call FunctionCall) Value { return Value{} } - -func (runtime *_runtime) newConsole() *_object { - - return newConsoleObject(runtime) -} diff --git a/vendor/github.com/robertkrimen/otto/dbg/dbg.go b/vendor/github.com/robertkrimen/otto/dbg/dbg.go index 8c27fa293..f0916572e 100644 --- a/vendor/github.com/robertkrimen/otto/dbg/dbg.go +++ b/vendor/github.com/robertkrimen/otto/dbg/dbg.go @@ -3,56 +3,55 @@ /* Package dbg is a println/printf/log-debugging utility library. - import ( - Dbg "github.com/robertkrimen/dbg" - ) + import ( + Dbg "github.com/robertkrimen/dbg" + ) - dbg, dbgf := Dbg.New() + dbg, dbgf := Dbg.New() - dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi) - # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793" + dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi) + # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793" - dbgf("With a %s formatting %.2f", "little", math.Pi) - # "2013/01/28 16:51:55 With a little formatting (3.14)" + dbgf("With a %s formatting %.2f", "little", math.Pi) + # "2013/01/28 16:51:55 With a little formatting (3.14)" - dbgf("%/fatal//A fatal debug statement: should not be here") - # "A fatal debug statement: should not be here" - # ...and then, os.Exit(1) + dbgf("%/fatal//A fatal debug statement: should not be here") + # "A fatal debug statement: should not be here" + # ...and then, os.Exit(1) - dbgf("%/panic//Can also panic %s", "this") - # "Can also panic this" - # ...as a panic, equivalent to: panic("Can also panic this") + dbgf("%/panic//Can also panic %s", "this") + # "Can also panic this" + # ...as a panic, equivalent to: panic("Can also panic this") - dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()") - # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()" + dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()") + # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()" - dbgf("%d %d", 1, 2, 3, 4, 5) - # "2013/01/28 17:16:32 Another example: 1 2 3 4 5" + dbgf("%d %d", 1, 2, 3, 4, 5) + # "2013/01/28 17:16:32 Another example: 1 2 3 4 5" - dbgf("%@: Include the function name for a little context (via %s)", "%@") - # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)" + dbgf("%@: Include the function name for a little context (via %s)", "%@") + # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)" By default, dbg uses log (log.Println, log.Printf, log.Panic, etc.) for output. However, you can also provide your own output destination by invoking dbg.New with a customization function: - import ( - "bytes" - Dbg "github.com/robertkrimen/dbg" - "os" - ) - - # dbg to os.Stderr - dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { - dbgr.SetOutput(os.Stderr) - }) - - # A slightly contrived example: - var buffer bytes.Buffer - dbg, dbgf := New(func(dbgr *Dbgr) { - dbgr.SetOutput(&buffer) - }) - + import ( + "bytes" + Dbg "github.com/robertkrimen/dbg" + "os" + ) + + # dbg to os.Stderr + dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { + dbgr.SetOutput(os.Stderr) + }) + + # A slightly contrived example: + var buffer bytes.Buffer + dbg, dbgf := New(func(dbgr *Dbgr) { + dbgr.SetOutput(&buffer) + }) */ package dbg @@ -63,7 +62,7 @@ import ( "log" "os" "regexp" - "runtime" + goruntime "runtime" "strings" "unicode" ) @@ -130,30 +129,28 @@ func parseFormat(format string) (frmt _frmt) { } type Dbgr struct { - emit _emit + emit emit } type DbgFunction func(values ...interface{}) func NewDbgr() *Dbgr { - self := &Dbgr{} - return self + return &Dbgr{} } /* New will create and return a pair of debugging functions. You can customize where they output to by passing in an (optional) customization function: - import ( - Dbg "github.com/robertkrimen/dbg" - "os" - ) - - # dbg to os.Stderr - dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { - dbgr.SetOutput(os.Stderr) - }) + import ( + Dbg "github.com/robertkrimen/dbg" + "os" + ) + # dbg to os.Stderr + dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { + dbgr.SetOutput(os.Stderr) + }) */ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) { dbgr := NewDbgr() @@ -165,26 +162,25 @@ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) { return dbgr.DbgDbgf() } -func (self Dbgr) Dbg(values ...interface{}) { - self.getEmit().emit(_frmt{}, "", values...) +func (d Dbgr) Dbg(values ...interface{}) { + d.getEmit().emit(_frmt{}, "", values...) } -func (self Dbgr) Dbgf(values ...interface{}) { - self.dbgf(values...) +func (d Dbgr) Dbgf(values ...interface{}) { + d.dbgf(values...) } -func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { +func (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { dbg = func(vl ...interface{}) { - self.Dbg(vl...) + d.Dbg(vl...) } dbgf = func(vl ...interface{}) { - self.dbgf(vl...) + d.dbgf(vl...) } return dbg, dbgf // Redundant, but... } -func (self Dbgr) dbgf(values ...interface{}) { - +func (d Dbgr) dbgf(values ...interface{}) { var frmt _frmt if len(values) > 0 { tmp := fmt.Sprint(values[0]) @@ -192,7 +188,7 @@ func (self Dbgr) dbgf(values ...interface{}) { values = values[1:] } - buffer_f := bytes.Buffer{} + buf := bytes.Buffer{} format := frmt.format end := len(format) for at := 0; at < end; { @@ -201,7 +197,7 @@ func (self Dbgr) dbgf(values ...interface{}) { at++ } if at > last { - buffer_f.WriteString(format[last:at]) + buf.WriteString(format[last:at]) } if at >= end { break @@ -211,100 +207,97 @@ func (self Dbgr) dbgf(values ...interface{}) { // format[at] == ? if format[at] == '@' { depth := 2 - pc, _, _, _ := runtime.Caller(depth) - name := runtime.FuncForPC(pc).Name() - buffer_f.WriteString(name) + pc, _, _, _ := goruntime.Caller(depth) + name := goruntime.FuncForPC(pc).Name() + buf.WriteString(name) } else { - buffer_f.WriteString(format[at-1 : at+1]) + buf.WriteString(format[at-1 : at+1]) } at++ } - //values_f := append([]interface{}{}, values[0:frmt.operandCount]...) - values_f := values[0:frmt.operandCount] - values_dbg := values[frmt.operandCount:] - if len(values_dbg) > 0 { + //valuesF := append([]interface{}{}, values[0:frmt.operandCount]...) + valuesF := values[0:frmt.operandCount] + valuesDbg := values[frmt.operandCount:] + if len(valuesDbg) > 0 { // Adjust frmt.format: // (%v instead of %s because: frmt.check) - { - tmp := format - if len(tmp) > 0 { - if unicode.IsSpace(rune(tmp[len(tmp)-1])) { - buffer_f.WriteString("%v") - } else { - buffer_f.WriteString(" %v") - } - } else if frmt.check { - // Performing a check, so no output + tmp := format + if len(tmp) > 0 { + if unicode.IsSpace(rune(tmp[len(tmp)-1])) { + buf.WriteString("%v") } else { - buffer_f.WriteString("%v") + buf.WriteString(" %v") } + } else if frmt.check { + // Performing a check, so no output + } else { + buf.WriteString("%v") } - // Adjust values_f: + // Adjust valuesF: if !frmt.check { tmp := []string{} - for _, value := range values_dbg { + for _, value := range valuesDbg { tmp = append(tmp, fmt.Sprintf("%v", value)) } - // First, make a copy of values_f, so we avoid overwriting values_dbg when appending - values_f = append([]interface{}{}, values_f...) - values_f = append(values_f, strings.Join(tmp, " ")) + // First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending + valuesF = append([]interface{}{}, valuesF...) + valuesF = append(valuesF, strings.Join(tmp, " ")) } } - format = buffer_f.String() + format = buf.String() if frmt.check { // We do not actually emit to the log, but panic if // a non-nil value is detected (e.g. a non-nil error) - for _, value := range values_dbg { + for _, value := range valuesDbg { if value != nil { if format == "" { panic(value) } else { - panic(fmt.Sprintf(format, append(values_f, value)...)) + panic(fmt.Sprintf(format, append(valuesF, value)...)) } } } } else { - self.getEmit().emit(frmt, format, values_f...) + d.getEmit().emit(frmt, format, valuesF...) } } // Idiot-proof &Dbgr{}, etc. -func (self *Dbgr) getEmit() _emit { - if self.emit == nil { - self.emit = standardEmit() +func (d *Dbgr) getEmit() emit { + if d.emit == nil { + d.emit = standardEmit() } - return self.emit + return d.emit } // SetOutput will accept the following as a destination for output: // -// *log.Logger Print*/Panic*/Fatal* of the logger -// io.Writer - -// nil Reset to the default output (os.Stderr) -// "log" Print*/Panic*/Fatal* via the "log" package -// -func (self *Dbgr) SetOutput(output interface{}) { +// *log.Logger Print*/Panic*/Fatal* of the logger +// io.Writer - +// nil Reset to the default output (os.Stderr) +// "log" Print*/Panic*/Fatal* via the "log" package +func (d *Dbgr) SetOutput(output interface{}) { if output == nil { - self.emit = standardEmit() + d.emit = standardEmit() return } switch output := output.(type) { case *log.Logger: - self.emit = _emitLogger{ + d.emit = emitLogger{ logger: output, } return case io.Writer: - self.emit = _emitWriter{ + d.emit = emitWriter{ writer: output, } return case string: if output == "log" { - self.emit = _emitLog{} + d.emit = emitLog{} return } } @@ -315,8 +308,8 @@ func (self *Dbgr) SetOutput(output interface{}) { // = emit = // // ======== // -func standardEmit() _emit { - return _emitWriter{ +func standardEmit() emit { + return emitWriter{ writer: os.Stderr, } } @@ -329,50 +322,50 @@ func ln(tmp string) string { return tmp } -type _emit interface { +type emit interface { emit(_frmt, string, ...interface{}) } -type _emitWriter struct { +type emitWriter struct { writer io.Writer } -func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) { +func (ew emitWriter) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { - fmt.Fprintln(self.writer, values...) + fmt.Fprintln(ew.writer, values...) } else { if frmt.panic { panic(fmt.Sprintf(format, values...)) } - fmt.Fprintf(self.writer, ln(format), values...) + fmt.Fprintf(ew.writer, ln(format), values...) if frmt.fatal { os.Exit(1) } } } -type _emitLogger struct { +type emitLogger struct { logger *log.Logger } -func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) { +func (el emitLogger) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { - self.logger.Println(values...) + el.logger.Println(values...) } else { if frmt.panic { - self.logger.Panicf(format, values...) + el.logger.Panicf(format, values...) } else if frmt.fatal { - self.logger.Fatalf(format, values...) + el.logger.Fatalf(format, values...) } else { - self.logger.Printf(format, values...) + el.logger.Printf(format, values...) } } } -type _emitLog struct { +type emitLog struct { } -func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) { +func (el emitLog) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { log.Println(values...) } else { diff --git a/vendor/github.com/robertkrimen/otto/error.go b/vendor/github.com/robertkrimen/otto/error.go index c8b5af446..ebbfc69fa 100644 --- a/vendor/github.com/robertkrimen/otto/error.go +++ b/vendor/github.com/robertkrimen/otto/error.go @@ -7,65 +7,63 @@ import ( "github.com/robertkrimen/otto/file" ) -type _exception struct { +type exception struct { value interface{} } -func newException(value interface{}) *_exception { - return &_exception{ +func newException(value interface{}) *exception { + return &exception{ value: value, } } -func (self *_exception) eject() interface{} { - value := self.value - self.value = nil // Prevent Go from holding on to the value, whatever it is +func (e *exception) eject() interface{} { + value := e.value + e.value = nil // Prevent Go from holding on to the value, whatever it is return value } -type _error struct { +type ottoError struct { name string message string - trace []_frame + trace []frame offset int } -func (err _error) format() string { - if len(err.name) == 0 { - return err.message +func (e ottoError) format() string { + if len(e.name) == 0 { + return e.message } - if len(err.message) == 0 { - return err.name + if len(e.message) == 0 { + return e.name } - return fmt.Sprintf("%s: %s", err.name, err.message) + return fmt.Sprintf("%s: %s", e.name, e.message) } -func (err _error) formatWithStack() string { - str := err.format() + "\n" - for _, frame := range err.trace { - str += " at " + frame.location() + "\n" +func (e ottoError) formatWithStack() string { + str := e.format() + "\n" + for _, frm := range e.trace { + str += " at " + frm.location() + "\n" } return str } -type _frame struct { - native bool +type frame struct { + fn interface{} + file *file.File nativeFile string + callee string nativeLine int - file *file.File offset int - callee string - fn interface{} + native bool } -var ( - nativeFrame = _frame{} -) +var nativeFrame = frame{} -type _at int +type at int -func (fr _frame) location() string { +func (fr frame) location() string { str := "" switch { @@ -95,48 +93,52 @@ func (fr _frame) location() string { // An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. type Error struct { - _error + ottoError } // Error returns a description of the error // -// TypeError: 'def' is not a function -// -func (err Error) Error() string { - return err.format() +// TypeError: 'def' is not a function +func (e Error) Error() string { + return e.format() } // String returns a description of the error and a trace of where the // error occurred. // -// TypeError: 'def' is not a function -// at xyz (:3:9) -// at :7:1/ -// -func (err Error) String() string { - return err.formatWithStack() +// TypeError: 'def' is not a function +// at xyz (:3:9) +// at :7:1/ +func (e Error) String() string { + return e.formatWithStack() } -func (err _error) describe(format string, in ...interface{}) string { +// GoString returns a description of the error and a trace of where the +// error occurred. Printing with %#v will trigger this behaviour. +func (e Error) GoString() string { + return e.formatWithStack() +} + +func (e ottoError) describe(format string, in ...interface{}) string { return fmt.Sprintf(format, in...) } -func (self _error) messageValue() Value { - if self.message == "" { +func (e ottoError) messageValue() Value { + if e.message == "" { return Value{} } - return toValue_string(self.message) + return stringValue(e.message) } -func (rt *_runtime) typeErrorResult(throw bool) bool { +func (rt *runtime) typeErrorResult(throw bool) bool { if throw { panic(rt.panicTypeError()) } return false } -func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}) _error { - err := _error{ +func newError(rt *runtime, name string, stackFramesToPop int, in ...interface{}) ottoError { + err := ottoError{ name: name, offset: -1, } @@ -144,21 +146,21 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{} length := len(in) if rt != nil && rt.scope != nil { - scope := rt.scope + curScope := rt.scope - for i := 0; i < stackFramesToPop; i++ { - if scope.outer != nil { - scope = scope.outer + for range stackFramesToPop { + if curScope.outer != nil { + curScope = curScope.outer } } - frame := scope.frame + frm := curScope.frame if length > 0 { - if at, ok := in[length-1].(_at); ok { + if atv, ok := in[length-1].(at); ok { in = in[0 : length-1] - if scope != nil { - frame.offset = int(at) + if curScope != nil { + frm.offset = int(atv) } length-- } @@ -169,54 +171,52 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{} limit := rt.traceLimit - err.trace = append(err.trace, frame) - if scope != nil { - for scope = scope.outer; scope != nil; scope = scope.outer { + err.trace = append(err.trace, frm) + if curScope != nil { + for curScope = curScope.outer; curScope != nil; curScope = curScope.outer { if limit--; limit == 0 { break } - if scope.frame.offset >= 0 { - err.trace = append(err.trace, scope.frame) + if curScope.frame.offset >= 0 { + err.trace = append(err.trace, curScope.frame) } } } - } else { - if length > 0 { - description, in = in[0].(string), in[1:] - } + } else if length > 0 { + description, in = in[0].(string), in[1:] } err.message = err.describe(description, in...) return err } -func (rt *_runtime) panicTypeError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicTypeError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "TypeError", 0, argumentList...), } } -func (rt *_runtime) panicReferenceError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicReferenceError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "ReferenceError", 0, argumentList...), } } -func (rt *_runtime) panicURIError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicURIError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "URIError", 0, argumentList...), } } -func (rt *_runtime) panicSyntaxError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicSyntaxError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "SyntaxError", 0, argumentList...), } } -func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicRangeError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "RangeError", 0, argumentList...), } } @@ -224,20 +224,19 @@ func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { func catchPanic(function func()) (err error) { defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() + if excep, ok := caught.(*exception); ok { + caught = excep.eject() } switch caught := caught.(type) { case *Error: err = caught return - case _error: + case ottoError: err = &Error{caught} return case Value: - if vl := caught._object(); vl != nil { - switch vl := vl.value.(type) { - case _error: + if vl := caught.object(); vl != nil { + if vl, ok := vl.value.(ottoError); ok { err = &Error{vl} return } diff --git a/vendor/github.com/robertkrimen/otto/evaluate.go b/vendor/github.com/robertkrimen/otto/evaluate.go index 093054cc3..269b9dd0a 100644 --- a/vendor/github.com/robertkrimen/otto/evaluate.go +++ b/vendor/github.com/robertkrimen/otto/evaluate.go @@ -8,12 +8,12 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_runtime) evaluateMultiply(left float64, right float64) Value { +func (rt *runtime) evaluateMultiply(left float64, right float64) Value { //nolint:unused // TODO 11.5.1 return Value{} } -func (self *_runtime) evaluateDivide(left float64, right float64) Value { +func (rt *runtime) evaluateDivide(left float64, right float64) Value { if math.IsNaN(left) || math.IsNaN(right) { return NaNValue() } @@ -26,63 +26,57 @@ func (self *_runtime) evaluateDivide(left float64, right float64) Value { if math.IsInf(left, 0) { if math.Signbit(left) == math.Signbit(right) { return positiveInfinityValue() - } else { - return negativeInfinityValue() } + return negativeInfinityValue() } if math.IsInf(right, 0) { if math.Signbit(left) == math.Signbit(right) { return positiveZeroValue() - } else { - return negativeZeroValue() } + return negativeZeroValue() } if right == 0 { if math.Signbit(left) == math.Signbit(right) { return positiveInfinityValue() - } else { - return negativeInfinityValue() } + return negativeInfinityValue() } - return toValue_float64(left / right) + return float64Value(left / right) } -func (self *_runtime) evaluateModulo(left float64, right float64) Value { +func (rt *runtime) evaluateModulo(left float64, right float64) Value { //nolint:unused // TODO 11.5.3 return Value{} } -func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { - +func (rt *runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { leftValue := left.resolve() switch operator { - // Additive case token.PLUS: - leftValue = toPrimitive(leftValue) + leftValue = toPrimitiveValue(leftValue) rightValue := right.resolve() - rightValue = toPrimitive(rightValue) + rightValue = toPrimitiveValue(rightValue) if leftValue.IsString() || rightValue.IsString() { - return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) - } else { - return toValue_float64(leftValue.float64() + rightValue.float64()) + return stringValue(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) } + return float64Value(leftValue.float64() + rightValue.float64()) case token.MINUS: rightValue := right.resolve() - return toValue_float64(leftValue.float64() - rightValue.float64()) + return float64Value(leftValue.float64() - rightValue.float64()) // Multiplicative case token.MULTIPLY: rightValue := right.resolve() - return toValue_float64(leftValue.float64() * rightValue.float64()) + return float64Value(leftValue.float64() * rightValue.float64()) case token.SLASH: rightValue := right.resolve() - return self.evaluateDivide(leftValue.float64(), rightValue.float64()) + return rt.evaluateDivide(leftValue.float64(), rightValue.float64()) case token.REMAINDER: rightValue := right.resolve() - return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64())) + return float64Value(math.Mod(leftValue.float64(), rightValue.float64())) // Logical case token.LOGICAL_AND: @@ -90,86 +84,66 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value if !left { return falseValue } - return toValue_bool(right.resolve().bool()) + return boolValue(right.resolve().bool()) case token.LOGICAL_OR: left := leftValue.bool() if left { return trueValue } - return toValue_bool(right.resolve().bool()) + return boolValue(right.resolve().bool()) // Bitwise case token.AND: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) & toInt32(rightValue)) + return int32Value(toInt32(leftValue) & toInt32(rightValue)) case token.OR: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) | toInt32(rightValue)) + return int32Value(toInt32(leftValue) | toInt32(rightValue)) case token.EXCLUSIVE_OR: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) ^ toInt32(rightValue)) + return int32Value(toInt32(leftValue) ^ toInt32(rightValue)) // Shift // (Masking of 0x1f is to restrict the shift to a maximum of 31 places) case token.SHIFT_LEFT: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) + return int32Value(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) case token.SHIFT_RIGHT: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) + return int32Value(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.UNSIGNED_SHIFT_RIGHT: rightValue := right.resolve() // Shifting an unsigned integer is a logical shift - return toValue_uint32(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) + return uint32Value(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.INSTANCEOF: rightValue := right.resolve() if !rightValue.IsObject() { - panic(self.panicTypeError("Expecting a function in instanceof check, but got: %v", rightValue)) + panic(rt.panicTypeError("invalid kind %s for instanceof (expected object)", rightValue.kind)) } - return toValue_bool(rightValue._object().hasInstance(leftValue)) + return boolValue(rightValue.object().hasInstance(leftValue)) case token.IN: rightValue := right.resolve() if !rightValue.IsObject() { - panic(self.panicTypeError()) + panic(rt.panicTypeError("invalid kind %s for in (expected object)", rightValue.kind)) } - return toValue_bool(rightValue._object().hasProperty(leftValue.string())) + return boolValue(rightValue.object().hasProperty(leftValue.string())) } panic(hereBeDragons(operator)) } -func valueKindDispatchKey(left _valueKind, right _valueKind) int { - return (int(left) << 2) + int(right) -} - -var equalDispatch map[int](func(Value, Value) bool) = makeEqualDispatch() - -func makeEqualDispatch() map[int](func(Value, Value) bool) { - key := valueKindDispatchKey - return map[int](func(Value, Value) bool){ - - key(valueNumber, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() }, - key(valueString, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() }, - key(valueObject, valueNumber): func(x Value, y Value) bool { return x.float64() == y.float64() }, - key(valueObject, valueString): func(x Value, y Value) bool { return x.float64() == y.float64() }, - } -} - -type _lessThanResult int +type lessThanResult int const ( - lessThanFalse _lessThanResult = iota + lessThanFalse lessThanResult = iota lessThanTrue lessThanUndefined ) -func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult { - - x := Value{} - y := x - +func calculateLessThan(left Value, right Value, leftFirst bool) lessThanResult { + var x, y Value if leftFirst { x = toNumberPrimitive(left) y = toNumberPrimitive(right) @@ -178,7 +152,7 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult x = toNumberPrimitive(left) } - result := false + var result bool if x.kind != valueString || y.kind != valueString { x, y := x.float64(), y.float64() if math.IsNaN(x) || math.IsNaN(y) { @@ -197,47 +171,46 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult return lessThanFalse } -// FIXME Probably a map is not the most efficient way to do this -var lessThanTable [4](map[_lessThanResult]bool) = [4](map[_lessThanResult]bool){ +// FIXME Probably a map is not the most efficient way to do this. +var lessThanTable [4](map[lessThanResult]bool) = [4](map[lessThanResult]bool){ // < - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: false, lessThanTrue: true, lessThanUndefined: false, }, // > - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: false, lessThanTrue: true, lessThanUndefined: false, }, // <= - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: true, lessThanTrue: false, lessThanUndefined: false, }, // >= - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: true, lessThanTrue: false, lessThanUndefined: false, }, } -func (self *_runtime) calculateComparison(comparator token.Token, left Value, right Value) bool { - +func (rt *runtime) calculateComparison(comparator token.Token, left Value, right Value) bool { // FIXME Use strictEqualityComparison? // TODO This might be redundant now (with regards to evaluateComparison) x := left.resolve() y := right.resolve() - kindEqualKind := false + var kindEqualKind bool + var negate bool result := true - negate := false switch comparator { case token.LESS: @@ -261,27 +234,28 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri negate = true fallthrough case token.EQUAL: - if x.kind == y.kind { + switch { + case x.kind == y.kind: kindEqualKind = true - } else if x.kind <= valueNull && y.kind <= valueNull { + case x.kind <= valueNull && y.kind <= valueNull: result = true - } else if x.kind <= valueNull || y.kind <= valueNull { + case x.kind <= valueNull || y.kind <= valueNull: result = false - } else if x.kind <= valueString && y.kind <= valueString { + case x.kind <= valueString && y.kind <= valueString: result = x.float64() == y.float64() - } else if x.kind == valueBoolean { - result = self.calculateComparison(token.EQUAL, toValue_float64(x.float64()), y) - } else if y.kind == valueBoolean { - result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.float64())) - } else if x.kind == valueObject { - result = self.calculateComparison(token.EQUAL, toPrimitive(x), y) - } else if y.kind == valueObject { - result = self.calculateComparison(token.EQUAL, x, toPrimitive(y)) - } else { - panic(hereBeDragons("Unable to test for equality: %v ==? %v", x, y)) + case x.kind == valueBoolean: + result = rt.calculateComparison(token.EQUAL, float64Value(x.float64()), y) + case y.kind == valueBoolean: + result = rt.calculateComparison(token.EQUAL, x, float64Value(y.float64())) + case x.kind == valueObject: + result = rt.calculateComparison(token.EQUAL, toPrimitiveValue(x), y) + case y.kind == valueObject: + result = rt.calculateComparison(token.EQUAL, x, toPrimitiveValue(y)) + default: + panic(fmt.Sprintf("unknown types for equal: %v ==? %v", x, y)) } default: - panic(fmt.Errorf("Unknown comparator %s", comparator.String())) + panic("unknown comparator " + comparator.String()) } if kindEqualKind { @@ -301,7 +275,7 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri case valueBoolean: result = x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + result = x.object() == y.object() default: goto ERROR } diff --git a/vendor/github.com/robertkrimen/otto/file/README.markdown b/vendor/github.com/robertkrimen/otto/file/README.markdown deleted file mode 100644 index 79757baa8..000000000 --- a/vendor/github.com/robertkrimen/otto/file/README.markdown +++ /dev/null @@ -1,110 +0,0 @@ -# file --- - import "github.com/robertkrimen/otto/file" - -Package file encapsulates the file abstractions used by the ast & parser. - -## Usage - -#### type File - -```go -type File struct { -} -``` - - -#### func NewFile - -```go -func NewFile(filename, src string, base int) *File -``` - -#### func (*File) Base - -```go -func (fl *File) Base() int -``` - -#### func (*File) Name - -```go -func (fl *File) Name() string -``` - -#### func (*File) Source - -```go -func (fl *File) Source() string -``` - -#### type FileSet - -```go -type FileSet struct { -} -``` - -A FileSet represents a set of source files. - -#### func (*FileSet) AddFile - -```go -func (self *FileSet) AddFile(filename, src string) int -``` -AddFile adds a new file with the given filename and src. - -This an internal method, but exported for cross-package use. - -#### func (*FileSet) File - -```go -func (self *FileSet) File(idx Idx) *File -``` - -#### func (*FileSet) Position - -```go -func (self *FileSet) Position(idx Idx) *Position -``` -Position converts an Idx in the FileSet into a Position. - -#### type Idx - -```go -type Idx int -``` - -Idx is a compact encoding of a source position within a file set. It can be -converted into a Position for a more convenient, but much larger, -representation. - -#### type Position - -```go -type Position struct { - Filename string // The filename where the error occurred, if any - Offset int // The src offset - Line int // The line number, starting at 1 - Column int // The column number, starting at 1 (The character count) - -} -``` - -Position describes an arbitrary source position including the filename, line, -and column location. - -#### func (*Position) String - -```go -func (self *Position) String() string -``` -String returns a string in one of several forms: - - file:line:column A valid position with filename - line:column A valid position without filename - file An invalid position with filename - - An invalid position without filename - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/file/file.go b/vendor/github.com/robertkrimen/otto/file/file.go index 9093206e8..99dd60701 100644 --- a/vendor/github.com/robertkrimen/otto/file/file.go +++ b/vendor/github.com/robertkrimen/otto/file/file.go @@ -1,5 +1,4 @@ // Package file encapsulates the file abstractions used by the ast & parser. -// package file import ( @@ -21,13 +20,12 @@ type Position struct { Offset int // The src offset Line int // The line number, starting at 1 Column int // The column number, starting at 1 (The character count) - } // A Position is valid if the line number is > 0. -func (self *Position) isValid() bool { - return self.Line > 0 +func (p *Position) isValid() bool { + return p.Line > 0 } // String returns a string in one of several forms: @@ -36,14 +34,13 @@ func (self *Position) isValid() bool { // line:column A valid position without filename // file An invalid position with filename // - An invalid position without filename -// -func (self *Position) String() string { - str := self.Filename - if self.isValid() { +func (p *Position) String() string { + str := p.Filename + if p.isValid() { if str != "" { str += ":" } - str += fmt.Sprintf("%d:%d", self.Line, self.Column) + str += fmt.Sprintf("%d:%d", p.Line, p.Column) } if str == "" { str = "-" @@ -51,38 +48,37 @@ func (self *Position) String() string { return str } -// FileSet - // A FileSet represents a set of source files. type FileSet struct { - files []*File last *File + files []*File } // AddFile adds a new file with the given filename and src. // // This an internal method, but exported for cross-package use. -func (self *FileSet) AddFile(filename, src string) int { - base := self.nextBase() +func (fs *FileSet) AddFile(filename, src string) int { + base := fs.nextBase() file := &File{ name: filename, src: src, base: base, } - self.files = append(self.files, file) - self.last = file + fs.files = append(fs.files, file) + fs.last = file return base } -func (self *FileSet) nextBase() int { - if self.last == nil { +func (fs *FileSet) nextBase() int { + if fs.last == nil { return 1 } - return self.last.base + len(self.last.src) + 1 + return fs.last.base + len(fs.last.src) + 1 } -func (self *FileSet) File(idx Idx) *File { - for _, file := range self.files { +// File returns the File at idx or nil if not found. +func (fs *FileSet) File(idx Idx) *File { + for _, file := range fs.files { if idx <= Idx(file.base+len(file.src)) { return file } @@ -91,8 +87,8 @@ func (self *FileSet) File(idx Idx) *File { } // Position converts an Idx in the FileSet into a Position. -func (self *FileSet) Position(idx Idx) *Position { - for _, file := range self.files { +func (fs *FileSet) Position(idx Idx) *Position { + for _, file := range fs.files { if idx <= Idx(file.base+len(file.src)) { return file.Position(idx - Idx(file.base)) } @@ -101,13 +97,15 @@ func (self *FileSet) Position(idx Idx) *Position { return nil } +// File represents a file to parse. type File struct { + sm *sourcemap.Consumer name string src string - base int // This will always be 1 or greater - sm *sourcemap.Consumer + base int } +// NewFile returns a new file with the given filename, src and base. func NewFile(filename, src string, base int) *File { return &File{ name: filename, @@ -116,23 +114,28 @@ func NewFile(filename, src string, base int) *File { } } +// WithSourceMap sets the source map of fl. func (fl *File) WithSourceMap(sm *sourcemap.Consumer) *File { fl.sm = sm return fl } +// Name returns the name of fl. func (fl *File) Name() string { return fl.name } +// Source returns the source of fl. func (fl *File) Source() string { return fl.src } +// Base returns the base of fl. func (fl *File) Base() int { return fl.base } +// Position returns the position at idx or nil if not valid. func (fl *File) Position(idx Idx) *Position { position := &Position{} diff --git a/vendor/github.com/robertkrimen/otto/global.go b/vendor/github.com/robertkrimen/otto/global.go index eb2a2a0fb..a46e6bcfb 100644 --- a/vendor/github.com/robertkrimen/otto/global.go +++ b/vendor/github.com/robertkrimen/otto/global.go @@ -7,12 +7,12 @@ import ( var ( prototypeValueObject = interface{}(nil) - prototypeValueFunction = _nativeFunctionObject{ + prototypeValueFunction = nativeFunctionObject{ call: func(_ FunctionCall) Value { return Value{} }, } - prototypeValueString = _stringASCII("") + prototypeValueString = stringASCII("") // TODO Make this just false? prototypeValueBoolean = Value{ kind: valueBoolean, @@ -22,7 +22,7 @@ var ( kind: valueNumber, value: 0, } - prototypeValueDate = _dateObject{ + prototypeValueDate = dateObject{ epoch: 0, isNaN: false, time: time.Unix(0, 0).UTC(), @@ -31,7 +31,7 @@ var ( value: 0, }, } - prototypeValueRegExp = _regExpObject{ + prototypeValueRegExp = regExpObject{ regularExpression: nil, global: false, ignoreCase: false, @@ -41,104 +41,101 @@ var ( } ) -func newContext() *_runtime { +func newContext() *runtime { + rt := &runtime{} - self := &_runtime{} + rt.globalStash = rt.newObjectStash(nil, nil) + rt.globalObject = rt.globalStash.object - self.globalStash = self.newObjectStash(nil, nil) - self.globalObject = self.globalStash.object + rt.newContext() - _newContext(self) + rt.eval = rt.globalObject.property["eval"].value.(Value).value.(*object) + rt.globalObject.prototype = rt.global.ObjectPrototype - self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object) - self.globalObject.prototype = self.global.ObjectPrototype - - return self + return rt } -func (runtime *_runtime) newBaseObject() *_object { - self := newObject(runtime, "") - return self +func (rt *runtime) newBaseObject() *object { + return newObject(rt, "") } -func (runtime *_runtime) newClassObject(class string) *_object { - return newObject(runtime, class) +func (rt *runtime) newClassObject(class string) *object { + return newObject(rt, class) } -func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object { - self := runtime.newClassObject(class) - self.value = value - return self +func (rt *runtime) newPrimitiveObject(class string, value Value) *object { + o := rt.newClassObject(class) + o.value = value + return o } -func (self *_object) primitiveValue() Value { - switch value := self.value.(type) { +func (o *object) primitiveValue() Value { + switch value := o.value.(type) { case Value: return value - case _stringObject: - return toValue_string(value.String()) + case stringObjecter: + return stringValue(value.String()) } return Value{} } -func (self *_object) hasPrimitive() bool { - switch self.value.(type) { - case Value, _stringObject: +func (o *object) hasPrimitive() bool { //nolint:unused + switch o.value.(type) { + case Value, stringObjecter: return true } return false } -func (runtime *_runtime) newObject() *_object { - self := runtime.newClassObject("Object") - self.prototype = runtime.global.ObjectPrototype - return self +func (rt *runtime) newObject() *object { + o := rt.newClassObject(classObjectName) + o.prototype = rt.global.ObjectPrototype + return o } -func (runtime *_runtime) newArray(length uint32) *_object { - self := runtime.newArrayObject(length) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newArray(length uint32) *object { + o := rt.newArrayObject(length) + o.prototype = rt.global.ArrayPrototype + return o } -func (runtime *_runtime) newArrayOf(valueArray []Value) *_object { - self := runtime.newArray(uint32(len(valueArray))) +func (rt *runtime) newArrayOf(valueArray []Value) *object { + o := rt.newArray(uint32(len(valueArray))) for index, value := range valueArray { if value.isEmpty() { continue } - self.defineProperty(strconv.FormatInt(int64(index), 10), value, 0111, false) + o.defineProperty(strconv.FormatInt(int64(index), 10), value, 0o111, false) } - return self + return o } -func (runtime *_runtime) newString(value Value) *_object { - self := runtime.newStringObject(value) - self.prototype = runtime.global.StringPrototype - return self +func (rt *runtime) newString(value Value) *object { + o := rt.newStringObject(value) + o.prototype = rt.global.StringPrototype + return o } -func (runtime *_runtime) newBoolean(value Value) *_object { - self := runtime.newBooleanObject(value) - self.prototype = runtime.global.BooleanPrototype - return self +func (rt *runtime) newBoolean(value Value) *object { + o := rt.newBooleanObject(value) + o.prototype = rt.global.BooleanPrototype + return o } -func (runtime *_runtime) newNumber(value Value) *_object { - self := runtime.newNumberObject(value) - self.prototype = runtime.global.NumberPrototype - return self +func (rt *runtime) newNumber(value Value) *object { + o := rt.newNumberObject(value) + o.prototype = rt.global.NumberPrototype + return o } -func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object { - +func (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object { pattern := "" flags := "" - if object := patternValue._object(); object != nil && object.class == "RegExp" { + if obj := patternValue.object(); obj != nil && obj.class == classRegExpName { if flagsValue.IsDefined() { - panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another")) + panic(rt.panicTypeError("Cannot supply flags when constructing one RegExp from another")) } - regExp := object.regExpValue() + regExp := obj.regExpValue() pattern = regExp.source flags = regExp.flags } else { @@ -150,72 +147,71 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec } } - return runtime._newRegExp(pattern, flags) + return rt.newRegExpDirect(pattern, flags) } -func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object { - self := runtime.newRegExpObject(pattern, flags) - self.prototype = runtime.global.RegExpPrototype - return self +func (rt *runtime) newRegExpDirect(pattern string, flags string) *object { + o := rt.newRegExpObject(pattern, flags) + o.prototype = rt.global.RegExpPrototype + return o } -// TODO Should (probably) be one argument, right? This is redundant -func (runtime *_runtime) newDate(epoch float64) *_object { - self := runtime.newDateObject(epoch) - self.prototype = runtime.global.DatePrototype - return self +// TODO Should (probably) be one argument, right? This is redundant. +func (rt *runtime) newDate(epoch float64) *object { + o := rt.newDateObject(epoch) + o.prototype = rt.global.DatePrototype + return o } -func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object { - var self *_object +func (rt *runtime) newError(name string, message Value, stackFramesToPop int) *object { switch name { case "EvalError": - return runtime.newEvalError(message) + return rt.newEvalError(message) case "TypeError": - return runtime.newTypeError(message) + return rt.newTypeError(message) case "RangeError": - return runtime.newRangeError(message) + return rt.newRangeError(message) case "ReferenceError": - return runtime.newReferenceError(message) + return rt.newReferenceError(message) case "SyntaxError": - return runtime.newSyntaxError(message) + return rt.newSyntaxError(message) case "URIError": - return runtime.newURIError(message) + return rt.newURIError(message) } - self = runtime.newErrorObject(name, message, stackFramesToPop) - self.prototype = runtime.global.ErrorPrototype + obj := rt.newErrorObject(name, message, stackFramesToPop) + obj.prototype = rt.global.ErrorPrototype if name != "" { - self.defineProperty("name", toValue_string(name), 0111, false) + obj.defineProperty("name", stringValue(name), 0o111, false) } - return self + return obj } -func (runtime *_runtime) newNativeFunction(name, file string, line int, _nativeFunction _nativeFunction) *_object { - self := runtime.newNativeFunctionObject(name, file, line, _nativeFunction, 0) - self.prototype = runtime.global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0100, false) - return self +func (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object { + o := rt.newNativeFunctionObject(name, file, line, fn, 0) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o100, false) + return o } -func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_object { +func (rt *runtime) newNodeFunction(node *nodeFunctionLiteral, scopeEnvironment stasher) *object { // TODO Implement 13.2 fully - self := runtime.newNodeFunctionObject(node, scopeEnvironment) - self.prototype = runtime.global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0101, false) - return self + o := rt.newNodeFunctionObject(node, scopeEnvironment) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o101, false) + return o } // FIXME Only in one place... -func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newBoundFunctionObject(target, this, argumentList) - self.prototype = runtime.global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0100, false) - return self +func (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object { + o := rt.newBoundFunctionObject(target, this, argumentList) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o100, false) + return o } diff --git a/vendor/github.com/robertkrimen/otto/inline.go b/vendor/github.com/robertkrimen/otto/inline.go index 6e5df8393..30e00beec 100644 --- a/vendor/github.com/robertkrimen/otto/inline.go +++ b/vendor/github.com/robertkrimen/otto/inline.go @@ -1,6647 +1,8772 @@ +// Code generated by tools/gen-jscore. DO NOT EDIT. + package otto import ( "math" ) -func _newContext(runtime *_runtime) { - { - runtime.global.ObjectPrototype = &_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: nil, - extensible: true, - value: prototypeValueObject, - } +func (rt *runtime) newContext() { + // Order here is import as definitions depend on each other. + + // Object prototype. + rt.global.ObjectPrototype = &object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: nil, + extensible: true, + value: prototypeValueObject, } - { - runtime.global.FunctionPrototype = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueFunction, - } + + // Function prototype. + rt.global.FunctionPrototype = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueFunction, } - { - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinObject_valueOf, - }, - } - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinObject_toString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinObject_toLocaleString, - }, - } - hasOwnProperty_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "hasOwnProperty", - call: builtinObject_hasOwnProperty, - }, - } - isPrototypeOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isPrototypeOf", - call: builtinObject_isPrototypeOf, - }, - } - propertyIsEnumerable_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "propertyIsEnumerable", - call: builtinObject_propertyIsEnumerable, - }, - } - runtime.global.ObjectPrototype.property = map[string]_property{ - "valueOf": _property{ - mode: 0101, + + // Object prototype property definition. + rt.global.ObjectPrototype.property = map[string]property{ + "hasOwnProperty": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "hasOwnProperty", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "hasOwnProperty", + call: builtinObjectHasOwnProperty, + }, + }, + }, + }, + "isPrototypeOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isPrototypeOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isPrototypeOf", + call: builtinObjectIsPrototypeOf, + }, + }, + }, + }, + "propertyIsEnumerable": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "propertyIsEnumerable", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "propertyIsEnumerable", + call: builtinObjectPropertyIsEnumerable, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinObjectToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinObjectValueOf, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinObjectToLocaleString, + }, + }, + }, + }, + } + rt.global.ObjectPrototype.propertyOrder = []string{ + propertyConstructor, + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + methodToString, + "valueOf", + "toLocaleString", + } + + // Function prototype property definition. + rt.global.FunctionPrototype.property = map[string]property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinFunctionToString, + }, + }, + }, + }, + "apply": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "apply", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "apply", + call: builtinFunctionApply, + }, + }, + }, + }, + "call": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "call", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "call", + call: builtinFunctionCall, + }, + }, + }, + }, + "bind": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "bind", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "bind", + call: builtinFunctionBind, + }, + }, + }, + }, + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + } + rt.global.FunctionPrototype.propertyOrder = []string{ + methodToString, + "apply", + "call", + "bind", + propertyConstructor, + propertyLength, + } + + // Object definition. + rt.global.Object = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classObjectName, + call: builtinObject, + construct: builtinNewObject, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: valueOf_function, + kind: valueNumber, + value: 1, }, }, - "toString": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: toString_function, + value: rt.global.ObjectPrototype, }, }, - "toLocaleString": _property{ - mode: 0101, + "getPrototypeOf": { + mode: 0o101, value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "hasOwnProperty": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getPrototypeOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getPrototypeOf", + call: builtinObjectGetPrototypeOf, + }, + }, + }, + }, + "getOwnPropertyDescriptor": { + mode: 0o101, value: Value{ - kind: valueObject, - value: hasOwnProperty_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getOwnPropertyDescriptor", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getOwnPropertyDescriptor", + call: builtinObjectGetOwnPropertyDescriptor, + }, + }, + }, + }, + "defineProperty": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "defineProperty", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "defineProperty", + call: builtinObjectDefineProperty, + }, + }, + }, + }, + "defineProperties": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "defineProperties", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "defineProperties", + call: builtinObjectDefineProperties, + }, + }, + }, + }, + "create": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "create", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "create", + call: builtinObjectCreate, + }, + }, + }, + }, + "isExtensible": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isExtensible", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isExtensible", + call: builtinObjectIsExtensible, + }, + }, + }, + }, + "preventExtensions": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "preventExtensions", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "preventExtensions", + call: builtinObjectPreventExtensions, + }, + }, + }, + }, + "isSealed": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isSealed", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isSealed", + call: builtinObjectIsSealed, + }, + }, + }, + }, + "seal": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "seal", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "seal", + call: builtinObjectSeal, + }, + }, + }, + }, + "isFrozen": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isFrozen", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isFrozen", + call: builtinObjectIsFrozen, + }, + }, + }, + }, + "freeze": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "freeze", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "freeze", + call: builtinObjectFreeze, + }, + }, + }, + }, + "keys": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "keys", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "keys", + call: builtinObjectKeys, + }, + }, + }, + }, + "values": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "values", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "values", + call: builtinObjectValues, + }, + }, + }, + }, + "getOwnPropertyNames": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getOwnPropertyNames", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getOwnPropertyNames", + call: builtinObjectGetOwnPropertyNames, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "getPrototypeOf", + "getOwnPropertyDescriptor", + "defineProperty", + "defineProperties", + "create", + "isExtensible", + "preventExtensions", + "isSealed", + "seal", + "isFrozen", + "freeze", + "keys", + "values", + "getOwnPropertyNames", + }, + } + + // Object constructor definition. + rt.global.ObjectPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Object, + }, + } + + // Function definition. + rt.global.Function = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classFunctionName, + call: builtinFunction, + construct: builtinNewFunction, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "isPrototypeOf": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: isPrototypeOf_function, + value: rt.global.FunctionPrototype, }, }, - "propertyIsEnumerable": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // Function constructor definition. + rt.global.FunctionPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Function, + }, + } + + // Array prototype. + rt.global.ArrayPrototype = &object{ + runtime: rt, + class: classArrayName, + objectClass: classArray, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: nil, + property: map[string]property{ + propertyLength: { + mode: 0o100, value: Value{ - kind: valueObject, - value: propertyIsEnumerable_function, + kind: valueNumber, + value: uint32(0), }, }, - "constructor": _property{ - mode: 0101, - value: Value{}, - }, - } - runtime.global.ObjectPrototype.propertyOrder = []string{ - "valueOf", - "toString", + "concat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "concat", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "concat", + call: builtinArrayConcat, + }, + }, + }, + }, + "lastIndexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "lastIndexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "lastIndexOf", + call: builtinArrayLastIndexOf, + }, + }, + }, + }, + "pop": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "pop", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "pop", + call: builtinArrayPop, + }, + }, + }, + }, + "push": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "push", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "push", + call: builtinArrayPush, + }, + }, + }, + }, + "reverse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "reverse", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "reverse", + call: builtinArrayReverse, + }, + }, + }, + }, + "shift": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "shift", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "shift", + call: builtinArrayShift, + }, + }, + }, + }, + "unshift": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "unshift", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "unshift", + call: builtinArrayUnshift, + }, + }, + }, + }, + "slice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "slice", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "slice", + call: builtinArraySlice, + }, + }, + }, + }, + "sort": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sort", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sort", + call: builtinArraySort, + }, + }, + }, + }, + "splice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "splice", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "splice", + call: builtinArraySplice, + }, + }, + }, + }, + "indexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "indexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "indexOf", + call: builtinArrayIndexOf, + }, + }, + }, + }, + "join": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "join", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "join", + call: builtinArrayJoin, + }, + }, + }, + }, + "forEach": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "forEach", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "forEach", + call: builtinArrayForEach, + }, + }, + }, + }, + "filter": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "filter", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "filter", + call: builtinArrayFilter, + }, + }, + }, + }, + "map": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "map", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "map", + call: builtinArrayMap, + }, + }, + }, + }, + "every": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "every", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "every", + call: builtinArrayEvery, + }, + }, + }, + }, + "some": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "some", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "some", + call: builtinArraySome, + }, + }, + }, + }, + "reduce": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "reduce", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "reduce", + call: builtinArrayReduce, + }, + }, + }, + }, + "reduceRight": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "reduceRight", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "reduceRight", + call: builtinArrayReduceRight, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinArrayToLocaleString, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinArrayToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyConstructor, + "concat", + "lastIndexOf", + "pop", + "push", + "reverse", + "shift", + "unshift", + "slice", + "sort", + "splice", + "indexOf", + "join", + "forEach", + "filter", + "map", + "every", + "some", + "reduce", + "reduceRight", "toLocaleString", - "hasOwnProperty", - "isPrototypeOf", - "propertyIsEnumerable", - "constructor", - } + methodToString, + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinFunction_toString, - }, - } - apply_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "apply", - call: builtinFunction_apply, - }, - } - call_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "call", - call: builtinFunction_call, - }, - } - bind_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "bind", - call: builtinFunction_bind, - }, - } - runtime.global.FunctionPrototype.property = map[string]_property{ - "toString": _property{ - mode: 0101, + + // Array definition. + rt.global.Array = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classArrayName, + call: builtinArray, + construct: builtinNewArray, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: toString_function, + kind: valueNumber, + value: 1, }, }, - "apply": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: apply_function, + value: rt.global.ArrayPrototype, }, }, - "call": _property{ - mode: 0101, + "isArray": { + mode: 0o101, value: Value{ - kind: valueObject, - value: call_function, - }, - }, - "bind": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isArray", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isArray", + call: builtinArrayIsArray, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "isArray", + }, + } + + // Array constructor definition. + rt.global.ArrayPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Array, + }, + } + + // String prototype. + rt.global.StringPrototype = &object{ + runtime: rt, + class: classStringName, + objectClass: classString, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueString, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: bind_function, + kind: valueNumber, + value: int(0), }, }, - "constructor": _property{ - mode: 0101, - value: Value{}, - }, - "length": _property{ + "charAt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "charAt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "charAt", + call: builtinStringCharAt, + }, + }, + }, + }, + "charCodeAt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "charCodeAt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "charCodeAt", + call: builtinStringCharCodeAt, + }, + }, + }, + }, + "concat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "concat", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "concat", + call: builtinStringConcat, + }, + }, + }, + }, + "indexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "indexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "indexOf", + call: builtinStringIndexOf, + }, + }, + }, + }, + "lastIndexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "lastIndexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "lastIndexOf", + call: builtinStringLastIndexOf, + }, + }, + }, + }, + "localeCompare": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "localeCompare", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "localeCompare", + call: builtinStringLocaleCompare, + }, + }, + }, + }, + "match": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "match", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "match", + call: builtinStringMatch, + }, + }, + }, + }, + "replace": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "replace", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "replace", + call: builtinStringReplace, + }, + }, + }, + }, + "search": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "search", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "search", + call: builtinStringSearch, + }, + }, + }, + }, + "slice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "slice", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "slice", + call: builtinStringSlice, + }, + }, + }, + }, + "split": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "split", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "split", + call: builtinStringSplit, + }, + }, + }, + }, + "substr": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "substr", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "substr", + call: builtinStringSubstr, + }, + }, + }, + }, + "substring": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "substring", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "substring", + call: builtinStringSubstring, + }, + }, + }, + }, + "startsWith": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "startsWith", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "startsWith", + call: builtinStringStartsWith, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinStringToString, + }, + }, + }, + }, + "trim": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trim", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trim", + call: builtinStringTrim, + }, + }, + }, + }, + "trimLeft": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimLeft", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimLeft", + call: builtinStringTrimLeft, + }, + }, + }, + }, + "trimRight": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimRight", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimRight", + call: builtinStringTrimRight, + }, + }, + }, + }, + "trimStart": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimStart", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimStart", + call: builtinStringTrimStart, + }, + }, + }, + }, + "trimEnd": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimEnd", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimEnd", + call: builtinStringTrimEnd, + }, + }, + }, + }, + "toLocaleLowerCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleLowerCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleLowerCase", + call: builtinStringToLocaleLowerCase, + }, + }, + }, + }, + "toLocaleUpperCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleUpperCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleUpperCase", + call: builtinStringToLocaleUpperCase, + }, + }, + }, + }, + "toLowerCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLowerCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLowerCase", + call: builtinStringToLowerCase, + }, + }, + }, + }, + "toUpperCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toUpperCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toUpperCase", + call: builtinStringToUpperCase, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinStringValueOf, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyConstructor, + "charAt", + "charCodeAt", + "concat", + "indexOf", + "lastIndexOf", + "localeCompare", + "match", + "replace", + "search", + "slice", + "split", + "substr", + "substring", + "startsWith", + methodToString, + "trim", + "trimLeft", + "trimRight", + "trimStart", + "trimEnd", + "toLocaleLowerCase", + "toLocaleUpperCase", + "toLowerCase", + "toUpperCase", + "valueOf", + }, + } + + // String definition. + rt.global.String = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classStringName, + call: builtinString, + construct: builtinNewString, + }, + property: map[string]property{ + propertyLength: { mode: 0, value: Value{ kind: valueNumber, - value: 0, - }, - }, - } - runtime.global.FunctionPrototype.propertyOrder = []string{ - "toString", - "apply", - "call", - "bind", - "constructor", - "length", - } - } - { - getPrototypeOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getPrototypeOf", - call: builtinObject_getPrototypeOf, - }, - } - getOwnPropertyDescriptor_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getOwnPropertyDescriptor", - call: builtinObject_getOwnPropertyDescriptor, - }, - } - defineProperty_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "defineProperty", - call: builtinObject_defineProperty, - }, - } - defineProperties_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "defineProperties", - call: builtinObject_defineProperties, - }, - } - create_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "create", - call: builtinObject_create, - }, - } - isExtensible_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isExtensible", - call: builtinObject_isExtensible, - }, - } - preventExtensions_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "preventExtensions", - call: builtinObject_preventExtensions, - }, - } - isSealed_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isSealed", - call: builtinObject_isSealed, - }, - } - seal_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "seal", - call: builtinObject_seal, - }, - } - isFrozen_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isFrozen", - call: builtinObject_isFrozen, - }, - } - freeze_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "freeze", - call: builtinObject_freeze, - }, - } - keys_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "keys", - call: builtinObject_keys, - }, - } - getOwnPropertyNames_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getOwnPropertyNames", - call: builtinObject_getOwnPropertyNames, - }, - } - runtime.global.Object = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Object", - call: builtinObject, - construct: builtinNewObject, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ObjectPrototype, - }, - }, - "getPrototypeOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getPrototypeOf_function, - }, - }, - "getOwnPropertyDescriptor": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getOwnPropertyDescriptor_function, - }, - }, - "defineProperty": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: defineProperty_function, - }, - }, - "defineProperties": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: defineProperties_function, - }, - }, - "create": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: create_function, - }, - }, - "isExtensible": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isExtensible_function, - }, - }, - "preventExtensions": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: preventExtensions_function, - }, - }, - "isSealed": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isSealed_function, - }, + value: 1, }, - "seal": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: seal_function, - }, - }, - "isFrozen": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isFrozen_function, - }, - }, - "freeze": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: freeze_function, - }, - }, - "keys": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: keys_function, - }, - }, - "getOwnPropertyNames": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getOwnPropertyNames_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "getPrototypeOf", - "getOwnPropertyDescriptor", - "defineProperty", - "defineProperties", - "create", - "isExtensible", - "preventExtensions", - "isSealed", - "seal", - "isFrozen", - "freeze", - "keys", - "getOwnPropertyNames", }, - } - runtime.global.ObjectPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Object, + value: rt.global.StringPrototype, }, - } - } - { - Function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Function", - call: builtinFunction, - construct: builtinNewFunction, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.FunctionPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.Function = Function - runtime.global.FunctionPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "fromCharCode": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Function, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "fromCharCode", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "fromCharCode", + call: builtinStringFromCharCode, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "fromCharCode", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinArray_toString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinArray_toLocaleString, - }, - } - concat_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "concat", - call: builtinArray_concat, - }, - } - join_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "join", - call: builtinArray_join, - }, - } - splice_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "splice", - call: builtinArray_splice, - }, - } - shift_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "shift", - call: builtinArray_shift, - }, - } - pop_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "pop", - call: builtinArray_pop, - }, - } - push_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "push", - call: builtinArray_push, - }, - } - slice_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "slice", - call: builtinArray_slice, - }, - } - unshift_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "unshift", - call: builtinArray_unshift, - }, - } - reverse_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "reverse", - call: builtinArray_reverse, - }, - } - sort_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "sort", - call: builtinArray_sort, - }, - } - indexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "indexOf", - call: builtinArray_indexOf, - }, - } - lastIndexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "lastIndexOf", - call: builtinArray_lastIndexOf, - }, - } - every_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "every", - call: builtinArray_every, - }, - } - some_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "some", - call: builtinArray_some, - }, - } - forEach_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "forEach", - call: builtinArray_forEach, - }, - } - map_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "map", - call: builtinArray_map, - }, - } - filter_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "filter", - call: builtinArray_filter, - }, - } - reduce_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "reduce", - call: builtinArray_reduce, - }, - } - reduceRight_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "reduceRight", - call: builtinArray_reduceRight, - }, - } - isArray_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isArray", - call: builtinArray_isArray, - }, - } - runtime.global.ArrayPrototype = &_object{ - runtime: runtime, - class: "Array", - objectClass: _classArray, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "length": _property{ - mode: 0100, - value: Value{ - kind: valueNumber, - value: uint32(0), - }, - }, - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "concat": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: concat_function, - }, - }, - "join": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: join_function, - }, - }, - "splice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: splice_function, - }, - }, - "shift": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: shift_function, - }, - }, - "pop": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: pop_function, - }, - }, - "push": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: push_function, - }, - }, - "slice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: slice_function, - }, - }, - "unshift": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: unshift_function, - }, - }, - "reverse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reverse_function, - }, - }, - "sort": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sort_function, - }, - }, - "indexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: indexOf_function, - }, - }, - "lastIndexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: lastIndexOf_function, - }, - }, - "every": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: every_function, - }, - }, - "some": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: some_function, - }, - }, - "forEach": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: forEach_function, - }, - }, - "map": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: map_function, - }, - }, - "filter": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: filter_function, - }, - }, - "reduce": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reduce_function, - }, - }, - "reduceRight": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reduceRight_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "toString", - "toLocaleString", - "concat", - "join", - "splice", - "shift", - "pop", - "push", - "slice", - "unshift", - "reverse", - "sort", - "indexOf", - "lastIndexOf", - "every", - "some", - "forEach", - "map", - "filter", - "reduce", - "reduceRight", - }, - } - runtime.global.Array = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Array", - call: builtinArray, - construct: builtinNewArray, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ArrayPrototype, - }, - }, - "isArray": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isArray_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "isArray", - }, - } - runtime.global.ArrayPrototype.property["constructor"] = - _property{ - mode: 0101, + + // String constructor definition. + rt.global.StringPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.String, + }, + } + + // Boolean prototype. + rt.global.BooleanPrototype = &object{ + runtime: rt, + class: classBooleanName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueBoolean, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Array, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinBooleanToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinBooleanValueOf, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + methodToString, + "valueOf", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinString_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinString_valueOf, - }, - } - charAt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "charAt", - call: builtinString_charAt, - }, - } - charCodeAt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "charCodeAt", - call: builtinString_charCodeAt, - }, - } - concat_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "concat", - call: builtinString_concat, - }, - } - indexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "indexOf", - call: builtinString_indexOf, - }, - } - lastIndexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "lastIndexOf", - call: builtinString_lastIndexOf, - }, - } - match_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "match", - call: builtinString_match, - }, - } - replace_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "replace", - call: builtinString_replace, - }, - } - search_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "search", - call: builtinString_search, - }, - } - split_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "split", - call: builtinString_split, - }, - } - slice_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "slice", - call: builtinString_slice, - }, - } - substring_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "substring", - call: builtinString_substring, - }, - } - toLowerCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLowerCase", - call: builtinString_toLowerCase, - }, - } - toUpperCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toUpperCase", - call: builtinString_toUpperCase, - }, - } - substr_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "substr", - call: builtinString_substr, - }, - } - trim_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trim", - call: builtinString_trim, - }, - } - trimLeft_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trimLeft", - call: builtinString_trimLeft, - }, - } - trimRight_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trimRight", - call: builtinString_trimRight, - }, - } - localeCompare_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "localeCompare", - call: builtinString_localeCompare, - }, - } - toLocaleLowerCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleLowerCase", - call: builtinString_toLocaleLowerCase, - }, - } - toLocaleUpperCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleUpperCase", - call: builtinString_toLocaleUpperCase, - }, - } - fromCharCode_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "fromCharCode", - call: builtinString_fromCharCode, - }, - } - runtime.global.StringPrototype = &_object{ - runtime: runtime, - class: "String", - objectClass: _classString, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueString, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: int(0), - }, - }, - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "charAt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: charAt_function, - }, - }, - "charCodeAt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: charCodeAt_function, - }, - }, - "concat": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: concat_function, - }, - }, - "indexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: indexOf_function, - }, - }, - "lastIndexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: lastIndexOf_function, - }, - }, - "match": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: match_function, - }, - }, - "replace": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: replace_function, - }, - }, - "search": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: search_function, - }, - }, - "split": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: split_function, - }, - }, - "slice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: slice_function, - }, - }, - "substring": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: substring_function, - }, - }, - "toLowerCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLowerCase_function, - }, - }, - "toUpperCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toUpperCase_function, - }, - }, - "substr": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: substr_function, - }, - }, - "trim": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trim_function, - }, - }, - "trimLeft": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trimLeft_function, - }, - }, - "trimRight": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trimRight_function, - }, - }, - "localeCompare": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: localeCompare_function, - }, - }, - "toLocaleLowerCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleLowerCase_function, - }, - }, - "toLocaleUpperCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleUpperCase_function, - }, + + // Boolean definition. + rt.global.Boolean = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classBooleanName, + call: builtinBoolean, + construct: builtinNewBoolean, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - propertyOrder: []string{ - "length", - "toString", - "valueOf", - "charAt", - "charCodeAt", - "concat", - "indexOf", - "lastIndexOf", - "match", - "replace", - "search", - "split", - "slice", - "substring", - "toLowerCase", - "toUpperCase", - "substr", - "trim", - "trimLeft", - "trimRight", - "localeCompare", - "toLocaleLowerCase", - "toLocaleUpperCase", - }, - } - runtime.global.String = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "String", - call: builtinString, - construct: builtinNewString, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.StringPrototype, - }, - }, - "fromCharCode": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: fromCharCode_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "fromCharCode", - }, - } - runtime.global.StringPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.String, + value: rt.global.BooleanPrototype, }, - } + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinBoolean_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinBoolean_valueOf, - }, - } - runtime.global.BooleanPrototype = &_object{ - runtime: runtime, - class: "Boolean", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueBoolean, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "valueOf", - }, - } - runtime.global.Boolean = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Boolean", - call: builtinBoolean, - construct: builtinNewBoolean, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.BooleanPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.BooleanPrototype.property["constructor"] = - _property{ - mode: 0101, + + // Boolean constructor definition. + rt.global.BooleanPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Boolean, + }, + } + + // Number prototype. + rt.global.NumberPrototype = &object{ + runtime: rt, + class: classNumberName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueNumber, + property: map[string]property{ + "toExponential": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Boolean, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toExponential", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toExponential", + call: builtinNumberToExponential, + }, + }, + }, + }, + "toFixed": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toFixed", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toFixed", + call: builtinNumberToFixed, + }, + }, + }, + }, + "toPrecision": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toPrecision", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toPrecision", + call: builtinNumberToPrecision, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinNumberToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinNumberValueOf, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinNumberToLocaleString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "toExponential", + "toFixed", + "toPrecision", + methodToString, + "valueOf", + "toLocaleString", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinNumber_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinNumber_valueOf, - }, - } - toFixed_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toFixed", - call: builtinNumber_toFixed, - }, - } - toExponential_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toExponential", - call: builtinNumber_toExponential, - }, - } - toPrecision_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toPrecision", - call: builtinNumber_toPrecision, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinNumber_toLocaleString, - }, - } - runtime.global.NumberPrototype = &_object{ - runtime: runtime, - class: "Number", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueNumber, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "toFixed": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toFixed_function, - }, - }, - "toExponential": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toExponential_function, - }, - }, - "toPrecision": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toPrecision_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "valueOf", - "toFixed", - "toExponential", - "toPrecision", - "toLocaleString", - }, - } - runtime.global.Number = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Number", - call: builtinNumber, - construct: builtinNewNumber, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.NumberPrototype, - }, - }, - "MAX_VALUE": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.MaxFloat64, - }, - }, - "MIN_VALUE": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.SmallestNonzeroFloat64, - }, - }, - "NaN": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.NaN(), - }, - }, - "NEGATIVE_INFINITY": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Inf(-1), - }, - }, - "POSITIVE_INFINITY": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Inf(+1), - }, + + // Number definition. + rt.global.Number = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classNumberName, + call: builtinNumber, + construct: builtinNewNumber, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - propertyOrder: []string{ - "length", - "prototype", - "MAX_VALUE", - "MIN_VALUE", - "NaN", - "NEGATIVE_INFINITY", - "POSITIVE_INFINITY", - }, - } - runtime.global.NumberPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Number, + value: rt.global.NumberPrototype, }, - } - } - { - abs_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "abs", - call: builtinMath_abs, - }, - } - acos_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "acos", - call: builtinMath_acos, - }, - } - asin_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "asin", - call: builtinMath_asin, - }, - } - atan_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "atan", - call: builtinMath_atan, - }, - } - atan2_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "atan2", - call: builtinMath_atan2, - }, - } - ceil_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "ceil", - call: builtinMath_ceil, - }, - } - cos_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "cos", - call: builtinMath_cos, - }, - } - exp_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "exp", - call: builtinMath_exp, - }, - } - floor_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "floor", - call: builtinMath_floor, - }, - } - log_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "log", - call: builtinMath_log, - }, - } - max_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "max", - call: builtinMath_max, - }, - } - min_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "min", - call: builtinMath_min, - }, - } - pow_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "pow", - call: builtinMath_pow, - }, - } - random_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "random", - call: builtinMath_random, - }, - } - round_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "round", - call: builtinMath_round, - }, - } - sin_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "sin", - call: builtinMath_sin, - }, - } - sqrt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "sqrt", - call: builtinMath_sqrt, - }, - } - tan_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "tan", - call: builtinMath_tan, }, - } - runtime.global.Math = &_object{ - runtime: runtime, - class: "Math", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "abs": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: abs_function, - }, - }, - "acos": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: acos_function, - }, - }, - "asin": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: asin_function, - }, - }, - "atan": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: atan_function, - }, - }, - "atan2": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: atan2_function, - }, - }, - "ceil": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: ceil_function, - }, - }, - "cos": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: cos_function, - }, - }, - "exp": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: exp_function, - }, - }, - "floor": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: floor_function, - }, - }, - "log": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: log_function, - }, - }, - "max": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: max_function, - }, - }, - "min": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: min_function, - }, - }, - "pow": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: pow_function, - }, - }, - "random": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: random_function, - }, - }, - "round": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: round_function, - }, - }, - "sin": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sin_function, - }, - }, - "sqrt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sqrt_function, - }, - }, - "tan": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: tan_function, - }, - }, - "E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.E, - }, - }, - "LN10": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Ln10, - }, - }, - "LN2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Ln2, - }, - }, - "LOG2E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Log2E, - }, + "isNaN": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isNaN", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isNaN", + call: builtinNumberIsNaN, + }, + }, + }, + }, + "MAX_VALUE": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.MaxFloat64, }, - "LOG10E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Log10E, - }, + }, + "MIN_VALUE": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.SmallestNonzeroFloat64, }, - "PI": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Pi, - }, + }, + "NaN": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.NaN(), }, - "SQRT1_2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: sqrt1_2, - }, + }, + "NEGATIVE_INFINITY": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(-1), }, - "SQRT2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Sqrt2, - }, + }, + "POSITIVE_INFINITY": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(+1), }, }, - propertyOrder: []string{ - "abs", - "acos", - "asin", - "atan", - "atan2", - "ceil", - "cos", - "exp", - "floor", - "log", - "max", - "min", - "pow", - "random", - "round", - "sin", - "sqrt", - "tan", - "E", - "LN10", - "LN2", - "LOG2E", - "LOG10E", - "PI", - "SQRT1_2", - "SQRT2", - }, - } + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "isNaN", + "MAX_VALUE", + "MIN_VALUE", + "NaN", + "NEGATIVE_INFINITY", + "POSITIVE_INFINITY", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinDate_toString, - }, - } - toDateString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toDateString", - call: builtinDate_toDateString, - }, - } - toTimeString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toTimeString", - call: builtinDate_toTimeString, - }, - } - toUTCString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toUTCString", - call: builtinDate_toUTCString, - }, - } - toISOString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toISOString", - call: builtinDate_toISOString, - }, - } - toJSON_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toJSON", - call: builtinDate_toJSON, - }, - } - toGMTString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toGMTString", - call: builtinDate_toGMTString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinDate_toLocaleString, - }, - } - toLocaleDateString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleDateString", - call: builtinDate_toLocaleDateString, - }, - } - toLocaleTimeString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleTimeString", - call: builtinDate_toLocaleTimeString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinDate_valueOf, - }, - } - getTime_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getTime", - call: builtinDate_getTime, - }, - } - getYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getYear", - call: builtinDate_getYear, - }, - } - getFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getFullYear", - call: builtinDate_getFullYear, - }, - } - getUTCFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCFullYear", - call: builtinDate_getUTCFullYear, - }, - } - getMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getMonth", - call: builtinDate_getMonth, - }, - } - getUTCMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCMonth", - call: builtinDate_getUTCMonth, - }, - } - getDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getDate", - call: builtinDate_getDate, - }, - } - getUTCDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCDate", - call: builtinDate_getUTCDate, - }, - } - getDay_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getDay", - call: builtinDate_getDay, - }, - } - getUTCDay_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCDay", - call: builtinDate_getUTCDay, - }, - } - getHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getHours", - call: builtinDate_getHours, - }, - } - getUTCHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCHours", - call: builtinDate_getUTCHours, - }, - } - getMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getMinutes", - call: builtinDate_getMinutes, - }, - } - getUTCMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCMinutes", - call: builtinDate_getUTCMinutes, - }, - } - getSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getSeconds", - call: builtinDate_getSeconds, - }, - } - getUTCSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCSeconds", - call: builtinDate_getUTCSeconds, - }, - } - getMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getMilliseconds", - call: builtinDate_getMilliseconds, - }, - } - getUTCMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCMilliseconds", - call: builtinDate_getUTCMilliseconds, - }, - } - getTimezoneOffset_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getTimezoneOffset", - call: builtinDate_getTimezoneOffset, - }, - } - setTime_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setTime", - call: builtinDate_setTime, - }, - } - setMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setMilliseconds", - call: builtinDate_setMilliseconds, - }, - } - setUTCMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCMilliseconds", - call: builtinDate_setUTCMilliseconds, - }, - } - setSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setSeconds", - call: builtinDate_setSeconds, - }, - } - setUTCSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCSeconds", - call: builtinDate_setUTCSeconds, - }, - } - setMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setMinutes", - call: builtinDate_setMinutes, - }, - } - setUTCMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCMinutes", - call: builtinDate_setUTCMinutes, - }, - } - setHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 4, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setHours", - call: builtinDate_setHours, - }, - } - setUTCHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 4, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCHours", - call: builtinDate_setUTCHours, - }, - } - setDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setDate", - call: builtinDate_setDate, - }, - } - setUTCDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCDate", - call: builtinDate_setUTCDate, - }, - } - setMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setMonth", - call: builtinDate_setMonth, - }, - } - setUTCMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCMonth", - call: builtinDate_setUTCMonth, - }, - } - setYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setYear", - call: builtinDate_setYear, - }, - } - setFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setFullYear", - call: builtinDate_setFullYear, - }, - } - setUTCFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCFullYear", - call: builtinDate_setUTCFullYear, - }, - } - parse_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parse", - call: builtinDate_parse, - }, - } - UTC_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 7, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "UTC", - call: builtinDate_UTC, - }, - } - now_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "now", - call: builtinDate_now, - }, - } - runtime.global.DatePrototype = &_object{ - runtime: runtime, - class: "Date", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueDate, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "toDateString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toDateString_function, - }, - }, - "toTimeString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toTimeString_function, - }, - }, - "toUTCString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toUTCString_function, - }, - }, - "toISOString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toISOString_function, - }, - }, - "toJSON": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toJSON_function, - }, - }, - "toGMTString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toGMTString_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "toLocaleDateString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleDateString_function, - }, - }, - "toLocaleTimeString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleTimeString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "getTime": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getTime_function, - }, - }, - "getYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getYear_function, - }, - }, - "getFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getFullYear_function, - }, - }, - "getUTCFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCFullYear_function, - }, - }, - "getMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMonth_function, - }, - }, - "getUTCMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMonth_function, - }, - }, - "getDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getDate_function, - }, - }, - "getUTCDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCDate_function, - }, - }, - "getDay": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getDay_function, - }, - }, - "getUTCDay": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCDay_function, - }, - }, - "getHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getHours_function, - }, - }, - "getUTCHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCHours_function, - }, - }, - "getMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMinutes_function, - }, - }, - "getUTCMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMinutes_function, - }, - }, - "getSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getSeconds_function, - }, - }, - "getUTCSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCSeconds_function, - }, - }, - "getMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMilliseconds_function, - }, - }, - "getUTCMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMilliseconds_function, - }, - }, - "getTimezoneOffset": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getTimezoneOffset_function, - }, - }, - "setTime": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setTime_function, - }, - }, - "setMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMilliseconds_function, - }, - }, - "setUTCMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMilliseconds_function, - }, - }, - "setSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setSeconds_function, - }, - }, - "setUTCSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCSeconds_function, - }, - }, - "setMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMinutes_function, - }, + + // Number constructor definition. + rt.global.NumberPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Number, + }, + } + + // Math definition. + rt.global.Math = &object{ + runtime: rt, + class: classMathName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "abs": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "abs", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "abs", + call: builtinMathAbs, + }, + }, + }, + }, + "acos": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "acos", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "acos", + call: builtinMathAcos, + }, + }, + }, + }, + "acosh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "acosh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "acosh", + call: builtinMathAcosh, + }, + }, + }, + }, + "asin": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "asin", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "asin", + call: builtinMathAsin, + }, + }, + }, + }, + "asinh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "asinh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "asinh", + call: builtinMathAsinh, + }, + }, + }, + }, + "atan": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "atan", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "atan", + call: builtinMathAtan, + }, + }, + }, + }, + "atanh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "atanh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "atanh", + call: builtinMathAtanh, + }, + }, + }, + }, + "atan2": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "atan2", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "atan2", + call: builtinMathAtan2, + }, + }, + }, + }, + "cbrt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "cbrt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "cbrt", + call: builtinMathCbrt, + }, + }, + }, + }, + "ceil": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "ceil", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "ceil", + call: builtinMathCeil, + }, + }, + }, + }, + "cos": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "cos", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "cos", + call: builtinMathCos, + }, + }, + }, + }, + "cosh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "cosh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "cosh", + call: builtinMathCosh, + }, + }, + }, + }, + "exp": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "exp", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "exp", + call: builtinMathExp, + }, + }, + }, + }, + "expm1": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "expm1", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "expm1", + call: builtinMathExpm1, + }, + }, + }, + }, + "floor": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "floor", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "floor", + call: builtinMathFloor, + }, + }, + }, + }, + "log": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log", + call: builtinMathLog, + }, + }, + }, + }, + "log10": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log10", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log10", + call: builtinMathLog10, + }, + }, + }, + }, + "log1p": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log1p", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log1p", + call: builtinMathLog1p, + }, + }, + }, + }, + "log2": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log2", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log2", + call: builtinMathLog2, + }, + }, + }, + }, + "max": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "max", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "max", + call: builtinMathMax, + }, + }, + }, + }, + "min": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "min", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "min", + call: builtinMathMin, + }, + }, + }, + }, + "pow": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "pow", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "pow", + call: builtinMathPow, + }, + }, + }, + }, + "random": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "random", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "random", + call: builtinMathRandom, + }, + }, + }, + }, + "round": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "round", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "round", + call: builtinMathRound, + }, + }, + }, + }, + "sin": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sin", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sin", + call: builtinMathSin, + }, + }, + }, + }, + "sinh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sinh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sinh", + call: builtinMathSinh, + }, + }, + }, + }, + "sqrt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sqrt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sqrt", + call: builtinMathSqrt, + }, + }, + }, + }, + "tan": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "tan", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "tan", + call: builtinMathTan, + }, + }, + }, + }, + "tanh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "tanh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "tanh", + call: builtinMathTanh, + }, + }, + }, + }, + "trunc": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trunc", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trunc", + call: builtinMathTrunc, + }, + }, + }, + }, + "E": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.E, }, - "setUTCMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMinutes_function, - }, - }, - "setHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setHours_function, - }, - }, - "setUTCHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCHours_function, - }, - }, - "setDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setDate_function, - }, - }, - "setUTCDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCDate_function, - }, - }, - "setMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMonth_function, - }, - }, - "setUTCMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMonth_function, - }, - }, - "setYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setYear_function, - }, - }, - "setFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setFullYear_function, - }, - }, - "setUTCFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCFullYear_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "toDateString", - "toTimeString", - "toUTCString", - "toISOString", - "toJSON", - "toGMTString", - "toLocaleString", - "toLocaleDateString", - "toLocaleTimeString", - "valueOf", - "getTime", - "getYear", - "getFullYear", - "getUTCFullYear", - "getMonth", - "getUTCMonth", - "getDate", - "getUTCDate", - "getDay", - "getUTCDay", - "getHours", - "getUTCHours", - "getMinutes", - "getUTCMinutes", - "getSeconds", - "getUTCSeconds", - "getMilliseconds", - "getUTCMilliseconds", - "getTimezoneOffset", - "setTime", - "setMilliseconds", - "setUTCMilliseconds", - "setSeconds", - "setUTCSeconds", - "setMinutes", - "setUTCMinutes", - "setHours", - "setUTCHours", - "setDate", - "setUTCDate", - "setMonth", - "setUTCMonth", - "setYear", - "setFullYear", - "setUTCFullYear", - }, - } - runtime.global.Date = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Date", - call: builtinDate, - construct: builtinNewDate, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 7, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.DatePrototype, - }, - }, - "parse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: parse_function, - }, - }, - "UTC": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: UTC_function, - }, - }, - "now": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: now_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "parse", - "UTC", - "now", - }, - } - runtime.global.DatePrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LN10": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Date, + kind: valueNumber, + value: math.Ln10, }, - } - } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinRegExp_toString, - }, - } - exec_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "exec", - call: builtinRegExp_exec, - }, - } - test_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "test", - call: builtinRegExp_test, - }, - } - compile_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "compile", - call: builtinRegExp_compile, - }, - } - runtime.global.RegExpPrototype = &_object{ - runtime: runtime, - class: "RegExp", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueRegExp, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "exec": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: exec_function, - }, - }, - "test": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: test_function, - }, - }, - "compile": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: compile_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "exec", - "test", - "compile", - }, - } - runtime.global.RegExp = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "RegExp", - call: builtinRegExp, - construct: builtinNewRegExp, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.RegExpPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.RegExpPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LN2": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.RegExp, + kind: valueNumber, + value: math.Ln2, }, - } - } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinError_toString, - }, - } - runtime.global.ErrorPrototype = &_object{ - runtime: runtime, - class: "Error", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "Error", - }, - }, - "message": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "", - }, - }, - }, - propertyOrder: []string{ - "toString", - "name", - "message", - }, - } - runtime.global.Error = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Error", - call: builtinError, - construct: builtinNewError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.ErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LOG10E": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Error, + kind: valueNumber, + value: math.Log10E, }, - } - } - { - runtime.global.EvalErrorPrototype = &_object{ - runtime: runtime, - class: "EvalError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "EvalError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.EvalError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "EvalError", - call: builtinEvalError, - construct: builtinNewEvalError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.EvalErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.EvalErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LOG2E": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.EvalError, + kind: valueNumber, + value: math.Log2E, }, - } - } - { - runtime.global.TypeErrorPrototype = &_object{ - runtime: runtime, - class: "TypeError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "TypeError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.TypeError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "TypeError", - call: builtinTypeError, - construct: builtinNewTypeError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.TypeErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.TypeErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "PI": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.TypeError, + kind: valueNumber, + value: math.Pi, }, - } - } - { - runtime.global.RangeErrorPrototype = &_object{ - runtime: runtime, - class: "RangeError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "RangeError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.RangeError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "RangeError", - call: builtinRangeError, - construct: builtinNewRangeError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.RangeErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.RangeErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "SQRT1_2": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.RangeError, + kind: valueNumber, + value: sqrt1_2, }, - } + }, + "SQRT2": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Sqrt2, + }, + }, + }, + propertyOrder: []string{ + "abs", + "acos", + "acosh", + "asin", + "asinh", + "atan", + "atanh", + "atan2", + "cbrt", + "ceil", + "cos", + "cosh", + "exp", + "expm1", + "floor", + "log", + "log10", + "log1p", + "log2", + "max", + "min", + "pow", + "random", + "round", + "sin", + "sinh", + "sqrt", + "tan", + "tanh", + "trunc", + "E", + "LN10", + "LN2", + "LOG10E", + "LOG2E", + "PI", + "SQRT1_2", + "SQRT2", + }, } - { - runtime.global.ReferenceErrorPrototype = &_object{ - runtime: runtime, - class: "ReferenceError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "ReferenceError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.ReferenceError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "ReferenceError", - call: builtinReferenceError, - construct: builtinNewReferenceError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ReferenceErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.ReferenceErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + + // Date prototype. + rt.global.DatePrototype = &object{ + runtime: rt, + class: classDateName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueDate, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.ReferenceError, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinDateToString, + }, + }, + }, + }, + "toDateString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toDateString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toDateString", + call: builtinDateToDateString, + }, + }, + }, + }, + "toTimeString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toTimeString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toTimeString", + call: builtinDateToTimeString, + }, + }, + }, + }, + "toISOString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toISOString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toISOString", + call: builtinDateToISOString, + }, + }, + }, + }, + "toUTCString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toUTCString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toUTCString", + call: builtinDateToUTCString, + }, + }, + }, + }, + "toGMTString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toGMTString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toGMTString", + call: builtinDateToGMTString, + }, + }, + }, + }, + "getDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getDate", + call: builtinDateGetDate, + }, + }, + }, + }, + "setDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setDate", + call: builtinDateSetDate, + }, + }, + }, + }, + "getDay": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getDay", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getDay", + call: builtinDateGetDay, + }, + }, + }, + }, + "getFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getFullYear", + call: builtinDateGetFullYear, + }, + }, + }, + }, + "setFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setFullYear", + call: builtinDateSetFullYear, + }, + }, + }, + }, + "getHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getHours", + call: builtinDateGetHours, + }, + }, + }, + }, + "setHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 4, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setHours", + call: builtinDateSetHours, + }, + }, + }, + }, + "getMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getMilliseconds", + call: builtinDateGetMilliseconds, + }, + }, + }, + }, + "setMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setMilliseconds", + call: builtinDateSetMilliseconds, + }, + }, + }, + }, + "getMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getMinutes", + call: builtinDateGetMinutes, + }, + }, + }, + }, + "setMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setMinutes", + call: builtinDateSetMinutes, + }, + }, + }, + }, + "getMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getMonth", + call: builtinDateGetMonth, + }, + }, + }, + }, + "setMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setMonth", + call: builtinDateSetMonth, + }, + }, + }, + }, + "getSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getSeconds", + call: builtinDateGetSeconds, + }, + }, + }, + }, + "setSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setSeconds", + call: builtinDateSetSeconds, + }, + }, + }, + }, + "getTime": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getTime", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getTime", + call: builtinDateGetTime, + }, + }, + }, + }, + "setTime": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setTime", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setTime", + call: builtinDateSetTime, + }, + }, + }, + }, + "getTimezoneOffset": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getTimezoneOffset", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getTimezoneOffset", + call: builtinDateGetTimezoneOffset, + }, + }, + }, + }, + "getUTCDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCDate", + call: builtinDateGetUTCDate, + }, + }, + }, + }, + "setUTCDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCDate", + call: builtinDateSetUTCDate, + }, + }, + }, + }, + "getUTCDay": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCDay", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCDay", + call: builtinDateGetUTCDay, + }, + }, + }, + }, + "getUTCFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCFullYear", + call: builtinDateGetUTCFullYear, + }, + }, + }, + }, + "setUTCFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCFullYear", + call: builtinDateSetUTCFullYear, + }, + }, + }, + }, + "getUTCHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCHours", + call: builtinDateGetUTCHours, + }, + }, + }, + }, + "setUTCHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 4, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCHours", + call: builtinDateSetUTCHours, + }, + }, + }, + }, + "getUTCMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCMilliseconds", + call: builtinDateGetUTCMilliseconds, + }, + }, + }, + }, + "setUTCMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCMilliseconds", + call: builtinDateSetUTCMilliseconds, + }, + }, + }, + }, + "getUTCMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCMinutes", + call: builtinDateGetUTCMinutes, + }, + }, + }, + }, + "setUTCMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCMinutes", + call: builtinDateSetUTCMinutes, + }, + }, + }, + }, + "getUTCMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCMonth", + call: builtinDateGetUTCMonth, + }, + }, + }, + }, + "setUTCMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCMonth", + call: builtinDateSetUTCMonth, + }, + }, + }, + }, + "getUTCSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCSeconds", + call: builtinDateGetUTCSeconds, + }, + }, + }, + }, + "setUTCSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCSeconds", + call: builtinDateSetUTCSeconds, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinDateValueOf, + }, + }, + }, + }, + "getYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getYear", + call: builtinDateGetYear, + }, + }, + }, + }, + "setYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setYear", + call: builtinDateSetYear, + }, + }, + }, + }, + "toJSON": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toJSON", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toJSON", + call: builtinDateToJSON, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinDateToLocaleString, + }, + }, + }, + }, + "toLocaleDateString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleDateString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleDateString", + call: builtinDateToLocaleDateString, + }, + }, + }, + }, + "toLocaleTimeString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleTimeString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleTimeString", + call: builtinDateToLocaleTimeString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + methodToString, + "toDateString", + "toTimeString", + "toISOString", + "toUTCString", + "toGMTString", + "getDate", + "setDate", + "getDay", + "getFullYear", + "setFullYear", + "getHours", + "setHours", + "getMilliseconds", + "setMilliseconds", + "getMinutes", + "setMinutes", + "getMonth", + "setMonth", + "getSeconds", + "setSeconds", + "getTime", + "setTime", + "getTimezoneOffset", + "getUTCDate", + "setUTCDate", + "getUTCDay", + "getUTCFullYear", + "setUTCFullYear", + "getUTCHours", + "setUTCHours", + "getUTCMilliseconds", + "setUTCMilliseconds", + "getUTCMinutes", + "setUTCMinutes", + "getUTCMonth", + "setUTCMonth", + "getUTCSeconds", + "setUTCSeconds", + "valueOf", + "getYear", + "setYear", + "toJSON", + "toLocaleString", + "toLocaleDateString", + "toLocaleTimeString", + }, } - { - runtime.global.SyntaxErrorPrototype = &_object{ - runtime: runtime, - class: "SyntaxError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "SyntaxError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.SyntaxError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "SyntaxError", - call: builtinSyntaxError, - construct: builtinNewSyntaxError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.SyntaxErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.SyntaxErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + + // Date definition. + rt.global.Date = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classDateName, + call: builtinDate, + construct: builtinNewDate, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.SyntaxError, + kind: valueNumber, + value: 7, }, - } - } - { - runtime.global.URIErrorPrototype = &_object{ - runtime: runtime, - class: "URIError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "URIError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.URIError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "URIError", - call: builtinURIError, - construct: builtinNewURIError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.URIErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.URIErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.URIError, + value: rt.global.DatePrototype, }, - } + }, + "parse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parse", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parse", + call: builtinDateParse, + }, + }, + }, + }, + "UTC": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 7, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "UTC", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "UTC", + call: builtinDateUTC, + }, + }, + }, + }, + "now": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "now", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "now", + call: builtinDateNow, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "parse", + "UTC", + "now", + }, } - { - parse_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parse", - call: builtinJSON_parse, - }, - } - stringify_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "stringify", - call: builtinJSON_stringify, - }, - } - runtime.global.JSON = &_object{ - runtime: runtime, - class: "JSON", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "parse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: parse_function, - }, - }, - "stringify": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: stringify_function, - }, - }, - }, - propertyOrder: []string{ - "parse", - "stringify", - }, - } + + // Date constructor definition. + rt.global.DatePrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Date, + }, } - { - eval_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "eval", - call: builtinGlobal_eval, - }, - } - parseInt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parseInt", - call: builtinGlobal_parseInt, - }, - } - parseFloat_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parseFloat", - call: builtinGlobal_parseFloat, - }, - } - isNaN_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isNaN", - call: builtinGlobal_isNaN, - }, - } - isFinite_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isFinite", - call: builtinGlobal_isFinite, - }, - } - decodeURI_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "decodeURI", - call: builtinGlobal_decodeURI, - }, - } - decodeURIComponent_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "decodeURIComponent", - call: builtinGlobal_decodeURIComponent, - }, - } - encodeURI_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "encodeURI", - call: builtinGlobal_encodeURI, - }, - } - encodeURIComponent_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "encodeURIComponent", - call: builtinGlobal_encodeURIComponent, - }, - } - escape_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "escape", - call: builtinGlobal_escape, - }, - } - unescape_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "unescape", - call: builtinGlobal_unescape, - }, - } - runtime.globalObject.property = map[string]_property{ - "eval": _property{ - mode: 0101, + + // RegExp prototype. + rt.global.RegExpPrototype = &object{ + runtime: rt, + class: classRegExpName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueRegExp, + property: map[string]property{ + "exec": { + mode: 0o101, value: Value{ - kind: valueObject, - value: eval_function, - }, - }, - "parseInt": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "exec", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "exec", + call: builtinRegExpExec, + }, + }, + }, + }, + "compile": { + mode: 0o101, value: Value{ - kind: valueObject, - value: parseInt_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "compile", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "compile", + call: builtinRegExpCompile, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinRegExpToString, + }, + }, + }, + }, + "test": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "test", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "test", + call: builtinRegExpTest, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "exec", + "compile", + methodToString, + "test", + }, + } + + // RegExp definition. + rt.global.RegExp = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classRegExpName, + call: builtinRegExp, + construct: builtinNewRegExp, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, }, }, - "parseFloat": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: parseFloat_function, + value: rt.global.RegExpPrototype, }, }, - "isNaN": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // RegExp constructor definition. + rt.global.RegExpPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RegExp, + }, + } + + // Error prototype. + rt.global.ErrorPrototype = &object{ + runtime: rt, + class: classErrorName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: isNaN_function, + kind: valueString, + value: classErrorName, }, }, - "isFinite": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: isFinite_function, + kind: valueString, + value: "", }, }, - "decodeURI": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: decodeURI_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // Error definition. + rt.global.Error = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classErrorName, + call: builtinError, + construct: builtinNewError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "decodeURIComponent": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: decodeURIComponent_function, + value: rt.global.ErrorPrototype, }, }, - "encodeURI": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // Error constructor definition. + rt.global.ErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Error, + }, + } + + // EvalError prototype. + rt.global.EvalErrorPrototype = &object{ + runtime: rt, + class: classEvalErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: encodeURI_function, + kind: valueString, + value: classEvalErrorName, }, }, - "encodeURIComponent": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: encodeURIComponent_function, + kind: valueString, + value: "", }, }, - "escape": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: escape_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // EvalError definition. + rt.global.EvalError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classEvalErrorName, + call: builtinEvalError, + construct: builtinNewEvalError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "unescape": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: unescape_function, + value: rt.global.EvalErrorPrototype, }, }, - "Object": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // EvalError constructor definition. + rt.global.EvalErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.EvalError, + }, + } + + // TypeError prototype. + rt.global.TypeErrorPrototype = &object{ + runtime: rt, + class: classTypeErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Object, + kind: valueString, + value: classTypeErrorName, }, }, - "Function": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Function, + kind: valueString, + value: "", }, }, - "Array": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Array, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // TypeError definition. + rt.global.TypeError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classTypeErrorName, + call: builtinTypeError, + construct: builtinNewTypeError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "String": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.String, + value: rt.global.TypeErrorPrototype, }, }, - "Boolean": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // TypeError constructor definition. + rt.global.TypeErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.TypeError, + }, + } + + // RangeError prototype. + rt.global.RangeErrorPrototype = &object{ + runtime: rt, + class: classRangeErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Boolean, + kind: valueString, + value: classRangeErrorName, }, }, - "Number": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Number, + kind: valueString, + value: "", }, }, - "Math": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Math, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // RangeError definition. + rt.global.RangeError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classRangeErrorName, + call: builtinRangeError, + construct: builtinNewRangeError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "Date": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Date, + value: rt.global.RangeErrorPrototype, }, }, - "RegExp": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // RangeError constructor definition. + rt.global.RangeErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RangeError, + }, + } + + // ReferenceError prototype. + rt.global.ReferenceErrorPrototype = &object{ + runtime: rt, + class: classReferenceErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.RegExp, + kind: valueString, + value: classReferenceErrorName, }, }, - "Error": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Error, + kind: valueString, + value: "", }, }, - "EvalError": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.EvalError, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // ReferenceError definition. + rt.global.ReferenceError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classReferenceErrorName, + call: builtinReferenceError, + construct: builtinNewReferenceError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "TypeError": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.TypeError, + value: rt.global.ReferenceErrorPrototype, }, }, - "RangeError": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // ReferenceError constructor definition. + rt.global.ReferenceErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.ReferenceError, + }, + } + + // SyntaxError prototype. + rt.global.SyntaxErrorPrototype = &object{ + runtime: rt, + class: classSyntaxErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.RangeError, + kind: valueString, + value: classSyntaxErrorName, }, }, - "ReferenceError": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.ReferenceError, + kind: valueString, + value: "", }, }, - "SyntaxError": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.SyntaxError, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // SyntaxError definition. + rt.global.SyntaxError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classSyntaxErrorName, + call: builtinSyntaxError, + construct: builtinNewSyntaxError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "URIError": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.URIError, + value: rt.global.SyntaxErrorPrototype, }, }, - "JSON": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // SyntaxError constructor definition. + rt.global.SyntaxErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.SyntaxError, + }, + } + + // URIError prototype. + rt.global.URIErrorPrototype = &object{ + runtime: rt, + class: classURIErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.JSON, + kind: valueString, + value: classURIErrorName, }, }, - "undefined": _property{ - mode: 0, + "message": { + mode: 0o101, value: Value{ - kind: valueUndefined, + kind: valueString, + value: "", }, }, - "NaN": _property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // URIError definition. + rt.global.URIError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classURIErrorName, + call: builtinURIError, + construct: builtinNewURIError, + }, + property: map[string]property{ + propertyLength: { mode: 0, value: Value{ kind: valueNumber, - value: math.NaN(), + value: 1, }, }, - "Infinity": _property{ + propertyPrototype: { mode: 0, value: Value{ - kind: valueNumber, - value: math.Inf(+1), - }, - }, - } - runtime.globalObject.propertyOrder = []string{ - "eval", - "parseInt", - "parseFloat", - "isNaN", - "isFinite", - "decodeURI", - "decodeURIComponent", - "encodeURI", - "encodeURIComponent", - "escape", - "unescape", - "Object", - "Function", - "Array", - "String", - "Boolean", - "Number", - "Math", - "Date", - "RegExp", - "Error", - "EvalError", - "TypeError", - "RangeError", - "ReferenceError", - "SyntaxError", - "URIError", - "JSON", - "undefined", - "NaN", - "Infinity", - } - } -} - -func newConsoleObject(runtime *_runtime) *_object { - { - log_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "log", - call: builtinConsole_log, - }, - } - debug_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "debug", - call: builtinConsole_log, - }, - } - info_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "info", - call: builtinConsole_log, - }, - } - error_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "error", - call: builtinConsole_error, - }, - } - warn_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "warn", - call: builtinConsole_error, - }, - } - dir_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "dir", - call: builtinConsole_dir, - }, - } - time_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "time", - call: builtinConsole_time, - }, - } - timeEnd_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "timeEnd", - call: builtinConsole_timeEnd, - }, - } - trace_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trace", - call: builtinConsole_trace, - }, - } - assert_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "assert", - call: builtinConsole_assert, - }, - } - return &_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "log": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: log_function, - }, - }, - "debug": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: debug_function, - }, - }, - "info": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: info_function, - }, - }, - "error": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: error_function, - }, - }, - "warn": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: warn_function, - }, - }, - "dir": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: dir_function, - }, - }, - "time": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: time_function, - }, - }, - "timeEnd": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: timeEnd_function, - }, + kind: valueObject, + value: rt.global.URIErrorPrototype, }, - "trace": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trace_function, - }, - }, - "assert": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: assert_function, - }, - }, - }, - propertyOrder: []string{ - "log", - "debug", - "info", - "error", - "warn", - "dir", - "time", - "timeEnd", - "trace", - "assert", }, - } - } -} - -func toValue_int(value int) Value { - return Value{ - kind: valueNumber, - value: value, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, } -} -func toValue_int8(value int8) Value { - return Value{ - kind: valueNumber, - value: value, + // URIError constructor definition. + rt.global.URIErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.URIError, + }, } -} -func toValue_int16(value int16) Value { - return Value{ - kind: valueNumber, - value: value, + // JSON definition. + rt.global.JSON = &object{ + runtime: rt, + class: classJSONName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "parse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parse", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parse", + call: builtinJSONParse, + }, + }, + }, + }, + "stringify": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "stringify", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "stringify", + call: builtinJSONStringify, + }, + }, + }, + }, + }, + propertyOrder: []string{ + "parse", + "stringify", + }, } -} -func toValue_int32(value int32) Value { - return Value{ - kind: valueNumber, - value: value, + // Global properties. + rt.globalObject.property = map[string]property{ + "eval": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "eval", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "eval", + call: builtinGlobalEval, + }, + }, + }, + }, + "parseInt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parseInt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parseInt", + call: builtinGlobalParseInt, + }, + }, + }, + }, + "parseFloat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parseFloat", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parseFloat", + call: builtinGlobalParseFloat, + }, + }, + }, + }, + "isNaN": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isNaN", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isNaN", + call: builtinGlobalIsNaN, + }, + }, + }, + }, + "isFinite": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isFinite", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isFinite", + call: builtinGlobalIsFinite, + }, + }, + }, + }, + "decodeURI": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "decodeURI", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "decodeURI", + call: builtinGlobalDecodeURI, + }, + }, + }, + }, + "decodeURIComponent": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "decodeURIComponent", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "decodeURIComponent", + call: builtinGlobalDecodeURIComponent, + }, + }, + }, + }, + "encodeURI": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "encodeURI", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "encodeURI", + call: builtinGlobalEncodeURI, + }, + }, + }, + }, + "encodeURIComponent": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "encodeURIComponent", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "encodeURIComponent", + call: builtinGlobalEncodeURIComponent, + }, + }, + }, + }, + "escape": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "escape", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "escape", + call: builtinGlobalEscape, + }, + }, + }, + }, + "unescape": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "unescape", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "unescape", + call: builtinGlobalUnescape, + }, + }, + }, + }, + classObjectName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Object, + }, + }, + classFunctionName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Function, + }, + }, + classArrayName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Array, + }, + }, + classStringName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.String, + }, + }, + classBooleanName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Boolean, + }, + }, + classNumberName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Number, + }, + }, + classMathName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Math, + }, + }, + classDateName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Date, + }, + }, + classRegExpName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RegExp, + }, + }, + classErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Error, + }, + }, + classEvalErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.EvalError, + }, + }, + classTypeErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.TypeError, + }, + }, + classRangeErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RangeError, + }, + }, + classReferenceErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.ReferenceError, + }, + }, + classSyntaxErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.SyntaxError, + }, + }, + classURIErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.URIError, + }, + }, + classJSONName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.JSON, + }, + }, + "undefined": { + mode: 0, + value: Value{ + kind: valueUndefined, + }, + }, + "NaN": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.NaN(), + }, + }, + "Infinity": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(+1), + }, + }, } -} -func toValue_int64(value int64) Value { - return Value{ - kind: valueNumber, - value: value, + // Global property order. + rt.globalObject.propertyOrder = []string{ + "eval", + "parseInt", + "parseFloat", + "isNaN", + "isFinite", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "escape", + "unescape", + classObjectName, + classFunctionName, + classArrayName, + classStringName, + classBooleanName, + classNumberName, + classMathName, + classDateName, + classRegExpName, + classErrorName, + classEvalErrorName, + classTypeErrorName, + classRangeErrorName, + classReferenceErrorName, + classSyntaxErrorName, + classURIErrorName, + classJSONName, + "undefined", + "NaN", + "Infinity", } } -func toValue_uint(value uint) Value { - return Value{ - kind: valueNumber, - value: value, +func (rt *runtime) newConsole() *object { + return &object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "log": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log", + call: builtinConsoleLog, + }, + }, + }, + }, + "debug": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "debug", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "debug", + call: builtinConsoleLog, + }, + }, + }, + }, + "info": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "info", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "info", + call: builtinConsoleLog, + }, + }, + }, + }, + "error": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "error", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "error", + call: builtinConsoleError, + }, + }, + }, + }, + "warn": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "warn", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "warn", + call: builtinConsoleError, + }, + }, + }, + }, + "dir": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "dir", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "dir", + call: builtinConsoleDir, + }, + }, + }, + }, + "time": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "time", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "time", + call: builtinConsoleTime, + }, + }, + }, + }, + "timeEnd": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "timeEnd", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "timeEnd", + call: builtinConsoleTimeEnd, + }, + }, + }, + }, + "trace": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trace", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trace", + call: builtinConsoleTrace, + }, + }, + }, + }, + "assert": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "assert", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "assert", + call: builtinConsoleAssert, + }, + }, + }, + }, + }, + propertyOrder: []string{ + "log", + "debug", + "info", + "error", + "warn", + "dir", + "time", + "timeEnd", + "trace", + "assert", + }, } } -func toValue_uint8(value uint8) Value { +func intValue(value int) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint16(value uint16) Value { +func int32Value(value int32) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint32(value uint32) Value { +func int64Value(value int64) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint64(value uint64) Value { +func uint16Value(value uint16) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_float32(value float32) Value { +func uint32Value(value uint32) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_float64(value float64) Value { +func float64Value(value float64) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_string(value string) Value { +func stringValue(value string) Value { return Value{ kind: valueString, value: value, } } -func toValue_string16(value []uint16) Value { +func string16Value(value []uint16) Value { return Value{ kind: valueString, value: value, } } -func toValue_bool(value bool) Value { +func boolValue(value bool) Value { return Value{ kind: valueBoolean, value: value, } } -func toValue_object(value *_object) Value { +func objectValue(value *object) Value { return Value{ kind: valueObject, value: value, diff --git a/vendor/github.com/robertkrimen/otto/inline.pl b/vendor/github.com/robertkrimen/otto/inline.pl deleted file mode 100644 index e90290489..000000000 --- a/vendor/github.com/robertkrimen/otto/inline.pl +++ /dev/null @@ -1,1086 +0,0 @@ -#!/usr/bin/env perl - -my $_fmt; -$_fmt = "gofmt"; -$_fmt = "cat -n" if "cat" eq ($ARGV[0] || ""); - -use strict; -use warnings; -use IO::File; - -my $self = __PACKAGE__; - -sub functionLabel ($) { - return "$_[0]_function"; -} - -sub trim ($) { - local $_ = shift; - s/^\s*//, s/\s*$// for $_; - return $_; -} - -open my $fmt, "|-", "$_fmt" or die $!; - -$fmt->print(<<_END_); -package otto - -import ( - "math" -) - -func _newContext(runtime *_runtime) { -@{[ join "\n", $self->newContext() ]} -} - -func newConsoleObject(runtime *_runtime) *_object { -@{[ join "\n", $self->newConsoleObject() ]} -} -_END_ - -for (qw/int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float32 float64/) { - $fmt->print(<<_END_); - -func toValue_$_(value $_) Value { - return Value{ - kind: valueNumber, - value: value, - } -} -_END_ -} - -$fmt->print(<<_END_); - -func toValue_string(value string) Value { - return Value{ - kind: valueString, - value: value, - } -} - -func toValue_string16(value []uint16) Value { - return Value{ - kind: valueString, - value: value, - } -} - -func toValue_bool(value bool) Value { - return Value{ - kind: valueBoolean, - value: value, - } -} - -func toValue_object(value *_object) Value { - return Value{ - kind: valueObject, - value: value, - } -} -_END_ - -close $fmt; - -sub newConsoleObject { - my $self = shift; - - return - $self->block(sub { - my $class = "Console"; - my @got = $self->functionDeclare( - $class, - "log", 0, - "debug:log", 0, - "info:log", 0, - "error", 0, - "warn:error", 0, - "dir", 0, - "time", 0, - "timeEnd", 0, - "trace", 0, - "assert", 0, - ); - return - "return @{[ $self->newObject(@got) ]}" - }), - ; -} - -sub newContext { - my $self = shift; - return - # ObjectPrototype - $self->block(sub { - my $class = "Object"; - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - undef, - "prototypeValueObject", - ), - }), - - # FunctionPrototype - $self->block(sub { - my $class = "Function"; - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueFunction", - ), - }), - - # ObjectPrototype - $self->block(sub { - my $class = "Object"; - my @got = $self->functionDeclare( - $class, - "valueOf", 0, - "toString", 0, - "toLocaleString", 0, - "hasOwnProperty", 1, - "isPrototypeOf", 1, - "propertyIsEnumerable", 1, - ); - my @propertyMap = $self->propertyMap( - @got, - $self->property("constructor", undef), - ); - my $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder =~ s/^propertyOrder: //; - return - ".${class}Prototype.property =", @propertyMap, - ".${class}Prototype.propertyOrder =", $propertyOrder, - }), - - # FunctionPrototype - $self->block(sub { - my $class = "Function"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "apply", 2, - "call", 1, - "bind", 1, - ); - my @propertyMap = $self->propertyMap( - @got, - $self->property("constructor", undef), - $self->property("length", $self->numberValue(0), "0"), - ); - my $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder =~ s/^propertyOrder: //; - return - ".${class}Prototype.property =", @propertyMap, - ".${class}Prototype.propertyOrder =", $propertyOrder, - }), - - # Object - $self->block(sub { - my $class = "Object"; - return - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - "getPrototypeOf", 1, - "getOwnPropertyDescriptor", 2, - "defineProperty", 3, - "defineProperties", 2, - "create", 2, - "isExtensible", 1, - "preventExtensions", 1, - "isSealed", 1, - "seal", 1, - "isFrozen", 1, - "freeze", 1, - "keys", 1, - "getOwnPropertyNames", 1, - ), - ), - }), - - # Function - $self->block(sub { - my $class = "Function"; - return - "Function :=", - $self->globalFunction( - $class, - 1, - ), - ".$class = Function", - }), - - # Array - $self->block(sub { - my $class = "Array"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "toLocaleString", 0, - "concat", 1, - "join", 1, - "splice", 2, - "shift", 0, - "pop", 0, - "push", 1, - "slice", 2, - "unshift", 1, - "reverse", 0, - "sort", 1, - "indexOf", 1, - "lastIndexOf", 1, - "every", 1, - "some", 1, - "forEach", 1, - "map", 1, - "filter", 1, - "reduce", 1, - "reduceRight", 1, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classArray", - ".ObjectPrototype", - undef, - $self->property("length", $self->numberValue("uint32(0)"), "0100"), - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - "isArray", 1, - ), - ), - }), - - # String - $self->block(sub { - my $class = "String"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "valueOf", 0, - "charAt", 1, - "charCodeAt", 1, - "concat", 1, - "indexOf", 1, - "lastIndexOf", 1, - "match", 1, - "replace", 2, - "search", 1, - "split", 2, - "slice", 2, - "substring", 2, - "toLowerCase", 0, - "toUpperCase", 0, - "substr", 2, - "trim", 0, - "trimLeft", 0, - "trimRight", 0, - "localeCompare", 1, - "toLocaleLowerCase", 0, - "toLocaleUpperCase", 0, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classString", - ".ObjectPrototype", - "prototypeValueString", - $self->property("length", $self->numberValue("int(0)"), "0"), - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - "fromCharCode", 1, - ), - ), - }), - - # Boolean - $self->block(sub { - my $class = "Boolean"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "valueOf", 0, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueBoolean", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - ), - }), - - # Number - $self->block(sub { - my $class = "Number"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "valueOf", 0, - "toFixed", 1, - "toExponential", 1, - "toPrecision", 1, - "toLocaleString", 1, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueNumber", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - $self->numberConstantDeclare( - "MAX_VALUE", "math.MaxFloat64", - "MIN_VALUE", "math.SmallestNonzeroFloat64", - "NaN", "math.NaN()", - "NEGATIVE_INFINITY", "math.Inf(-1)", - "POSITIVE_INFINITY", "math.Inf(+1)", - ), - ), - }), - - # Math - $self->block(sub { - my $class = "Math"; - return - ".$class =", - $self->globalObject( - $class, - $self->functionDeclare( - $class, - "abs", 1, - "acos", 1, - "asin", 1, - "atan", 1, - "atan2", 1, - "ceil", 1, - "cos", 1, - "exp", 1, - "floor", 1, - "log", 1, - "max", 2, - "min", 2, - "pow", 2, - "random", 0, - "round", 1, - "sin", 1, - "sqrt", 1, - "tan", 1, - ), - $self->numberConstantDeclare( - "E", "math.E", - "LN10", "math.Ln10", - "LN2", "math.Ln2", - "LOG2E", "math.Log2E", - "LOG10E", "math.Log10E", - "PI", "math.Pi", - "SQRT1_2", "sqrt1_2", - "SQRT2", "math.Sqrt2", - ) - ), - }), - - # Date - $self->block(sub { - my $class = "Date"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "toDateString", 0, - "toTimeString", 0, - "toUTCString", 0, - "toISOString", 0, - "toJSON", 1, - "toGMTString", 0, - "toLocaleString", 0, - "toLocaleDateString", 0, - "toLocaleTimeString", 0, - "valueOf", 0, - "getTime", 0, - "getYear", 0, - "getFullYear", 0, - "getUTCFullYear", 0, - "getMonth", 0, - "getUTCMonth", 0, - "getDate", 0, - "getUTCDate", 0, - "getDay", 0, - "getUTCDay", 0, - "getHours", 0, - "getUTCHours", 0, - "getMinutes", 0, - "getUTCMinutes", 0, - "getSeconds", 0, - "getUTCSeconds", 0, - "getMilliseconds", 0, - "getUTCMilliseconds", 0, - "getTimezoneOffset", 0, - "setTime", 1, - "setMilliseconds", 1, - "setUTCMilliseconds", 1, - "setSeconds", 2, - "setUTCSeconds", 2, - "setMinutes", 3, - "setUTCMinutes", 3, - "setHours", 4, - "setUTCHours", 4, - "setDate", 1, - "setUTCDate", 1, - "setMonth", 2, - "setUTCMonth", 2, - "setYear", 1, - "setFullYear", 3, - "setUTCFullYear", 3, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueDate", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 7, - $self->functionDeclare( - $class, - "parse", 1, - "UTC", 7, - "now", 0, - ), - ), - }), - - # RegExp - $self->block(sub { - my $class = "RegExp"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "exec", 1, - "test", 1, - "compile", 1, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueRegExp", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 2, - $self->functionDeclare( - $class, - ), - ), - }), - - # Error - $self->block(sub { - my $class = "Error"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - undef, - @got, - $self->property("name", $self->stringValue("Error")), - $self->property("message", $self->stringValue("")), - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - ), - }), - - (map { - my $class = "${_}Error"; - $self->block(sub { - my @got = $self->functionDeclare( - $class, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ErrorPrototype", - undef, - @got, - $self->property("name", $self->stringValue($class)), - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - ), - }); - } qw/Eval Type Range Reference Syntax URI/), - - # JSON - $self->block(sub { - my $class = "JSON"; - return - ".$class =", - $self->globalObject( - $class, - $self->functionDeclare( - $class, - "parse", 2, - "stringify", 3, - ), - ), - }), - - # Global - $self->block(sub { - my $class = "Global"; - my @got = $self->functionDeclare( - $class, - "eval", 1, - "parseInt", 2, - "parseFloat", 1, - "isNaN", 1, - "isFinite", 1, - "decodeURI", 1, - "decodeURIComponent", 1, - "encodeURI", 1, - "encodeURIComponent", 1, - "escape", 1, - "unescape", 1, - ); - my @propertyMap = $self->propertyMap( - @got, - $self->globalDeclare( - "Object", - "Function", - "Array", - "String", - "Boolean", - "Number", - "Math", - "Date", - "RegExp", - "Error", - "EvalError", - "TypeError", - "RangeError", - "ReferenceError", - "SyntaxError", - "URIError", - "JSON", - ), - $self->property("undefined", $self->undefinedValue(), "0"), - $self->property("NaN", $self->numberValue("math.NaN()"), "0"), - $self->property("Infinity", $self->numberValue("math.Inf(+1)"), "0"), - ); - my $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder =~ s/^propertyOrder: //; - return - "runtime.globalObject.property =", - @propertyMap, - "runtime.globalObject.propertyOrder =", - $propertyOrder, - ; - }), - ; -} - -sub propertyMap { - my $self = shift; - return "map[string]_property{", (join ",\n", @_, ""), "}", -} - -our (@preblock, @postblock); -sub block { - my $self = shift; - local @preblock = (); - local @postblock = (); - my @input = $_[0]->(); - my @output; - while (@input) { - local $_ = shift @input; - if (m/^\./) { - $_ = "runtime.global$_"; - } - if (m/ :?=$/) { - $_ .= shift @input; - } - push @output, $_; - } - return - "{", - @preblock, - @output, - @postblock, - "}", - ; -} - -sub numberConstantDeclare { - my $self = shift; - my @got; - while (@_) { - my $name = shift; - my $value = shift; - push @got, $self->property($name, $self->numberValue($value), "0"), - } - return @got; -} - -sub functionDeclare { - my $self = shift; - my $class = shift; - my $builtin = "builtin${class}"; - my @got; - while (@_) { - my $name = shift; - my $length = shift; - $name = $self->newFunction($name, "${builtin}_", $length); - push @got, $self->functionProperty($name), - } - return @got; -} - -sub globalDeclare { - my $self = shift; - my @got; - while (@_) { - my $name = shift; - push @got, $self->property($name, $self->objectValue("runtime.global.$name"), "0101"), - } - return @got; -} - -sub propertyOrder { - my $self = shift; - my $propertyMap = join "", @_; - - my (@keys) = $propertyMap =~ m/("\w+"):/g; - my $propertyOrder = - join "\n", "propertyOrder: []string{", (join ",\n", @keys, ""), "}"; - return $propertyOrder; -} - -sub globalObject { - my $self = shift; - my $name = shift; - - my $propertyMap = ""; - if (@_) { - $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - $propertyMap = "property: $propertyMap,\n$propertyOrder,"; - } - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "$name", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - $propertyMap -} -_END_ -} - -sub globalFunction { - my $self = shift; - my $name = shift; - my $length = shift; - - my $builtin = "builtin${name}"; - my $builtinNew = "builtinNew${name}"; - my $prototype = "runtime.global.${name}Prototype"; - my $propertyMap = ""; - unshift @_, - $self->property("length", $self->numberValue($length), "0"), - $self->property("prototype", $self->objectValue($prototype), "0"), - ; - - if (@_) { - $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - $propertyMap = "property: $propertyMap,\n$propertyOrder,"; - } - - push @postblock, $self->statement( - "$prototype.property[\"constructor\"] =", - $self->property(undef, $self->objectValue("runtime.global.${name}"), "0101"), - ); - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: @{[ $self->nativeFunctionOf($name, $builtin, $builtinNew) ]}, - $propertyMap -} -_END_ -} - -sub nativeCallFunction { - my $self = shift; - my $name = shift; - my $func = shift; - return trim <<_END_; -_nativeCallFunction{ "$name", $func } -_END_ -} - -sub globalPrototype { - my $self = shift; - my $class = shift; - my $classObject = shift; - my $prototype = shift; - my $value = shift; - - if (!defined $prototype) { - $prototype = "nil"; - } - - if (!defined $value) { - $value = "nil"; - } - - if ($prototype =~ m/^\./) { - $prototype = "runtime.global$prototype"; - } - - my $propertyMap = ""; - if (@_) { - $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - $propertyMap = "property: $propertyMap,\n$propertyOrder,"; - } - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "$class", - objectClass: $classObject, - prototype: $prototype, - extensible: true, - value: $value, - $propertyMap -} -_END_ -} - -sub newFunction { - my $self = shift; - my $name = shift; - my $func = shift; - my $length = shift; - - my @name = ($name, $name); - if ($name =~ m/^(\w+):(\w+)$/) { - @name = ($1, $2); - $name = $name[0]; - } - - if ($func =~ m/^builtin\w+_$/) { - $func = "$func$name[1]"; - } - - my $propertyOrder = ""; - my @propertyMap = ( - $self->property("length", $self->numberValue($length), "0"), - ); - - if (@propertyMap) { - $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder = "$propertyOrder,"; - } - - my $label = functionLabel($name); - push @preblock, $self->statement( - "$label := @{[ trim <<_END_ ]}", -&_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: @{[ join "\n", $self->propertyMap(@propertyMap) ]}, - $propertyOrder - value: @{[ $self->nativeFunctionOf($name, $func) ]}, -} -_END_ - ); - - return $name; -} - -sub newObject { - my $self = shift; - - my $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: $propertyMap, - $propertyOrder, -} -_END_ -} - -sub newPrototypeObject { - my $self = shift; - my $class = shift; - my $objectClass = shift; - my $value = shift; - if (defined $value) { - $value = "value: $value,"; - } - - my $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "$class", - objectClass: $objectClass, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: $propertyMap, - $propertyOrder, - $value -} -_END_ -} - -sub functionProperty { - my $self = shift; - my $name = shift; - - return $self->property( - $name, - $self->objectValue(functionLabel($name)) - ); -} - -sub statement { - my $self = shift; - return join "\n", @_; -} - -sub functionOf { - my $self = shift; - my $call = shift; - my $construct = shift; - if ($construct) { - $construct = "construct: $construct,"; - } else { - $construct = ""; - } - - return trim <<_END_ -_functionObject{ - call: $call, - $construct -} -_END_ -} - -sub nativeFunctionOf { - my $self = shift; - my $name = shift; - my $call = shift; - my $construct = shift; - if ($construct) { - $construct = "construct: $construct,"; - } else { - $construct = ""; - } - - return trim <<_END_ -_nativeFunctionObject{ - name: "$name", - call: $call, - $construct -} -_END_ -} - -sub nameProperty { - my $self = shift; - my $name = shift; - my $value = shift; - - return trim <<_END_; -"$name": _property{ - mode: 0101, - value: $value, -} -_END_ -} - -sub numberValue { - my $self = shift; - my $value = shift; - return trim <<_END_; -Value{ - kind: valueNumber, - value: $value, -} -_END_ -} - -sub property { - my $self = shift; - my $name = shift; - my $value = shift; - my $mode = shift; - $mode = "0101" unless defined $mode; - if (! defined $value) { - $value = "Value{}"; - } - if (defined $name) { - return trim <<_END_; -"$name": _property{ - mode: $mode, - value: $value, -} -_END_ - } else { - return trim <<_END_; -_property{ - mode: $mode, - value: $value, -} -_END_ - } - -} - -sub objectProperty { - my $self = shift; - my $name = shift; - my $value = shift; - - return trim <<_END_; -"$name": _property{ - mode: 0101, - value: @{[ $self->objectValue($value)]}, -} -_END_ -} - -sub objectValue { - my $self = shift; - my $value = shift; - return trim <<_END_ -Value{ - kind: valueObject, - value: $value, -} -_END_ -} - -sub stringValue { - my $self = shift; - my $value = shift; - return trim <<_END_ -Value{ - kind: valueString, - value: "$value", -} -_END_ -} - -sub booleanValue { - my $self = shift; - my $value = shift; - return trim <<_END_ -Value{ - kind: valueBoolean, - value: $value, -} -_END_ -} - -sub undefinedValue { - my $self = shift; - return trim <<_END_ -Value{ - kind: valueUndefined, -} -_END_ -} diff --git a/vendor/github.com/robertkrimen/otto/object.go b/vendor/github.com/robertkrimen/otto/object.go index 849812c91..40da58f76 100644 --- a/vendor/github.com/robertkrimen/otto/object.go +++ b/vendor/github.com/robertkrimen/otto/object.go @@ -1,78 +1,75 @@ package otto -type _object struct { - runtime *_runtime - - class string - objectClass *_objectClass - value interface{} - - prototype *_object - extensible bool - - property map[string]_property +type object struct { + value interface{} + runtime *runtime + objectClass *objectClass + prototype *object + property map[string]property + class string propertyOrder []string + extensible bool } -func newObject(runtime *_runtime, class string) *_object { - self := &_object{ - runtime: runtime, +func newObject(rt *runtime, class string) *object { + o := &object{ + runtime: rt, class: class, - objectClass: _classObject, - property: make(map[string]_property), + objectClass: classObject, + property: make(map[string]property), extensible: true, } - return self + return o } // 8.12 -// 8.12.1 -func (self *_object) getOwnProperty(name string) *_property { - return self.objectClass.getOwnProperty(self, name) +// 8.12.1. +func (o *object) getOwnProperty(name string) *property { + return o.objectClass.getOwnProperty(o, name) } -// 8.12.2 -func (self *_object) getProperty(name string) *_property { - return self.objectClass.getProperty(self, name) +// 8.12.2. +func (o *object) getProperty(name string) *property { + return o.objectClass.getProperty(o, name) } -// 8.12.3 -func (self *_object) get(name string) Value { - return self.objectClass.get(self, name) +// 8.12.3. +func (o *object) get(name string) Value { + return o.objectClass.get(o, name) } -// 8.12.4 -func (self *_object) canPut(name string) bool { - return self.objectClass.canPut(self, name) +// 8.12.4. +func (o *object) canPut(name string) bool { + return o.objectClass.canPut(o, name) } -// 8.12.5 -func (self *_object) put(name string, value Value, throw bool) { - self.objectClass.put(self, name, value, throw) +// 8.12.5. +func (o *object) put(name string, value Value, throw bool) { + o.objectClass.put(o, name, value, throw) } -// 8.12.6 -func (self *_object) hasProperty(name string) bool { - return self.objectClass.hasProperty(self, name) +// 8.12.6. +func (o *object) hasProperty(name string) bool { + return o.objectClass.hasProperty(o, name) } -func (self *_object) hasOwnProperty(name string) bool { - return self.objectClass.hasOwnProperty(self, name) +func (o *object) hasOwnProperty(name string) bool { + return o.objectClass.hasOwnProperty(o, name) } -type _defaultValueHint int +type defaultValueHint int const ( - defaultValueNoHint _defaultValueHint = iota + defaultValueNoHint defaultValueHint = iota defaultValueHintString defaultValueHintNumber ) -// 8.12.8 -func (self *_object) DefaultValue(hint _defaultValueHint) Value { +// 8.12.8. +func (o *object) DefaultValue(hint defaultValueHint) Value { if hint == defaultValueNoHint { - if self.class == "Date" { + if o.class == classDateName { // Date exception hint = defaultValueHintString } else { @@ -84,72 +81,67 @@ func (self *_object) DefaultValue(hint _defaultValueHint) Value { methodSequence = []string{"toString", "valueOf"} } for _, methodName := range methodSequence { - method := self.get(methodName) + method := o.get(methodName) // FIXME This is redundant... if method.isCallable() { - result := method._object().call(toValue_object(self), nil, false, nativeFrame) + result := method.object().call(objectValue(o), nil, false, nativeFrame) if result.IsPrimitive() { return result } } } - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError("Object.DefaultValue unknown")) } -func (self *_object) String() string { - return self.DefaultValue(defaultValueHintString).string() +func (o *object) String() string { + return o.DefaultValue(defaultValueHintString).string() } -func (self *_object) defineProperty(name string, value Value, mode _propertyMode, throw bool) bool { - return self.defineOwnProperty(name, _property{value, mode}, throw) +func (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint:unparam + return o.defineOwnProperty(name, property{value, mode}, throw) } -// 8.12.9 -func (self *_object) defineOwnProperty(name string, descriptor _property, throw bool) bool { - return self.objectClass.defineOwnProperty(self, name, descriptor, throw) +// 8.12.9. +func (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool { + return o.objectClass.defineOwnProperty(o, name, descriptor, throw) } -func (self *_object) delete(name string, throw bool) bool { - return self.objectClass.delete(self, name, throw) +func (o *object) delete(name string, throw bool) bool { + return o.objectClass.delete(o, name, throw) } -func (self *_object) enumerate(all bool, each func(string) bool) { - self.objectClass.enumerate(self, all, each) +func (o *object) enumerate(all bool, each func(string) bool) { + o.objectClass.enumerate(o, all, each) } -func (self *_object) _exists(name string) bool { - _, exists := self.property[name] - return exists +func (o *object) readProperty(name string) (property, bool) { + prop, exists := o.property[name] + return prop, exists } -func (self *_object) _read(name string) (_property, bool) { - property, exists := self.property[name] - return property, exists -} - -func (self *_object) _write(name string, value interface{}, mode _propertyMode) { +func (o *object) writeProperty(name string, value interface{}, mode propertyMode) { if value == nil { value = Value{} } - _, exists := self.property[name] - self.property[name] = _property{value, mode} - if !exists { - self.propertyOrder = append(self.propertyOrder, name) + if _, exists := o.property[name]; !exists { + o.propertyOrder = append(o.propertyOrder, name) } + o.property[name] = property{value, mode} } -func (self *_object) _delete(name string) { - _, exists := self.property[name] - delete(self.property, name) - if exists { - for index, property := range self.propertyOrder { - if name == property { - if index == len(self.propertyOrder)-1 { - self.propertyOrder = self.propertyOrder[:index] - } else { - self.propertyOrder = append(self.propertyOrder[:index], self.propertyOrder[index+1:]...) - } +func (o *object) deleteProperty(name string) { + if _, exists := o.property[name]; !exists { + return + } + + delete(o.property, name) + for index, prop := range o.propertyOrder { + if name == prop { + if index == len(o.propertyOrder)-1 { + o.propertyOrder = o.propertyOrder[:index] + } else { + o.propertyOrder = append(o.propertyOrder[:index], o.propertyOrder[index+1:]...) } } } diff --git a/vendor/github.com/robertkrimen/otto/object_class.go b/vendor/github.com/robertkrimen/otto/object_class.go index d18b9cede..e77ad8d92 100644 --- a/vendor/github.com/robertkrimen/otto/object_class.go +++ b/vendor/github.com/robertkrimen/otto/object_class.go @@ -4,24 +4,24 @@ import ( "encoding/json" ) -type _objectClass struct { - getOwnProperty func(*_object, string) *_property - getProperty func(*_object, string) *_property - get func(*_object, string) Value - canPut func(*_object, string) bool - put func(*_object, string, Value, bool) - hasProperty func(*_object, string) bool - hasOwnProperty func(*_object, string) bool - defineOwnProperty func(*_object, string, _property, bool) bool - delete func(*_object, string, bool) bool - enumerate func(*_object, bool, func(string) bool) - clone func(*_object, *_object, *_clone) *_object - marshalJSON func(*_object) json.Marshaler +type objectClass struct { + getOwnProperty func(*object, string) *property + getProperty func(*object, string) *property + get func(*object, string) Value + canPut func(*object, string) bool + put func(*object, string, Value, bool) + hasProperty func(*object, string) bool + hasOwnProperty func(*object, string) bool + defineOwnProperty func(*object, string, property, bool) bool + delete func(*object, string, bool) bool + enumerate func(*object, bool, func(string) bool) + clone func(*object, *object, *cloner) *object + marshalJSON func(*object) json.Marshaler } -func objectEnumerate(self *_object, all bool, each func(string) bool) { - for _, name := range self.propertyOrder { - if all || self.property[name].enumerable() { +func objectEnumerate(obj *object, all bool, each func(string) bool) { + for _, name := range obj.propertyOrder { + if all || obj.property[name].enumerable() { if !each(name) { return } @@ -29,20 +29,17 @@ func objectEnumerate(self *_object, all bool, each func(string) bool) { } } -var ( - _classObject, - _classArray, - _classString, - _classArguments, - _classGoStruct, - _classGoMap, - _classGoArray, - _classGoSlice, - _ *_objectClass -) +var classObject, + classArray, + classString, + classArguments, + classGoStruct, + classGoMap, + classGoArray, + classGoSlice *objectClass func init() { - _classObject = &_objectClass{ + classObject = &objectClass{ objectGetOwnProperty, objectGetProperty, objectGet, @@ -57,7 +54,7 @@ func init() { nil, } - _classArray = &_objectClass{ + classArray = &objectClass{ objectGetOwnProperty, objectGetProperty, objectGet, @@ -72,7 +69,7 @@ func init() { nil, } - _classString = &_objectClass{ + classString = &objectClass{ stringGetOwnProperty, objectGetProperty, objectGet, @@ -87,7 +84,7 @@ func init() { nil, } - _classArguments = &_objectClass{ + classArguments = &objectClass{ argumentsGetOwnProperty, objectGetProperty, argumentsGet, @@ -102,7 +99,7 @@ func init() { nil, } - _classGoStruct = &_objectClass{ + classGoStruct = &objectClass{ goStructGetOwnProperty, objectGetProperty, objectGet, @@ -117,7 +114,7 @@ func init() { goStructMarshalJSON, } - _classGoMap = &_objectClass{ + classGoMap = &objectClass{ goMapGetOwnProperty, objectGetProperty, objectGet, @@ -132,7 +129,7 @@ func init() { nil, } - _classGoArray = &_objectClass{ + classGoArray = &objectClass{ goArrayGetOwnProperty, objectGetProperty, objectGet, @@ -147,7 +144,7 @@ func init() { nil, } - _classGoSlice = &_objectClass{ + classGoSlice = &objectClass{ goSliceGetOwnProperty, objectGetProperty, objectGet, @@ -165,86 +162,81 @@ func init() { // Allons-y -// 8.12.1 -func objectGetOwnProperty(self *_object, name string) *_property { - // Return a _copy_ of the property - property, exists := self._read(name) +// 8.12.1. +func objectGetOwnProperty(obj *object, name string) *property { + // Return a _copy_ of the prop + prop, exists := obj.readProperty(name) if !exists { return nil } - return &property + return &prop } -// 8.12.2 -func objectGetProperty(self *_object, name string) *_property { - property := self.getOwnProperty(name) - if property != nil { - return property +// 8.12.2. +func objectGetProperty(obj *object, name string) *property { + prop := obj.getOwnProperty(name) + if prop != nil { + return prop } - if self.prototype != nil { - return self.prototype.getProperty(name) + if obj.prototype != nil { + return obj.prototype.getProperty(name) } return nil } -// 8.12.3 -func objectGet(self *_object, name string) Value { - property := self.getProperty(name) - if property != nil { - return property.get(self) +// 8.12.3. +func objectGet(obj *object, name string) Value { + if prop := obj.getProperty(name); prop != nil { + return prop.get(obj) } return Value{} } -// 8.12.4 -func objectCanPut(self *_object, name string) bool { - canPut, _, _ := _objectCanPut(self, name) +// 8.12.4. +func objectCanPut(obj *object, name string) bool { + canPut, _, _ := objectCanPutDetails(obj, name) return canPut } -func _objectCanPut(self *_object, name string) (canPut bool, property *_property, setter *_object) { - property = self.getOwnProperty(name) - if property != nil { - switch propertyValue := property.value.(type) { +func objectCanPutDetails(obj *object, name string) (canPut bool, prop *property, setter *object) { //nolint:nonamedreturns + prop = obj.getOwnProperty(name) + if prop != nil { + switch propertyValue := prop.value.(type) { case Value: - canPut = property.writable() - return - case _propertyGetSet: + return prop.writable(), prop, nil + case propertyGetSet: setter = propertyValue[1] - canPut = setter != nil - return + return setter != nil, prop, setter default: - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value)) } } - if self.prototype == nil { - return self.extensible, nil, nil + if obj.prototype == nil { + return obj.extensible, nil, nil } - property = self.prototype.getProperty(name) - if property == nil { - return self.extensible, nil, nil + prop = obj.prototype.getProperty(name) + if prop == nil { + return obj.extensible, nil, nil } - switch propertyValue := property.value.(type) { + switch propertyValue := prop.value.(type) { case Value: - if !self.extensible { + if !obj.extensible { return false, nil, nil } - return property.writable(), nil, nil - case _propertyGetSet: + return prop.writable(), nil, nil + case propertyGetSet: setter = propertyValue[1] - canPut = setter != nil - return + return setter != nil, prop, setter default: - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value)) } } -// 8.12.5 -func objectPut(self *_object, name string, value Value, throw bool) { - +// 8.12.5. +func objectPut(obj *object, name string, value Value, throw bool) { if true { // Shortcut... // @@ -254,16 +246,17 @@ func objectPut(self *_object, name string, value Value, throw bool) { // If that were to no longer be the case, we would have to have // something to detect that here, so that we do not use an // incompatible canPut routine - canPut, property, setter := _objectCanPut(self, name) - if !canPut { - self.runtime.typeErrorResult(throw) - } else if setter != nil { - setter.call(toValue(self), []Value{value}, false, nativeFrame) - } else if property != nil { - property.value = value - self.defineOwnProperty(name, *property, throw) - } else { - self.defineProperty(name, value, 0111, throw) + canPut, prop, setter := objectCanPutDetails(obj, name) + switch { + case !canPut: + obj.runtime.typeErrorResult(throw) + case setter != nil: + setter.call(toValue(obj), []Value{value}, false, nativeFrame) + case prop != nil: + prop.value = value + obj.defineOwnProperty(name, *prop, throw) + default: + obj.defineProperty(name, value, 0o111, throw) } return } @@ -271,221 +264,225 @@ func objectPut(self *_object, name string, value Value, throw bool) { // The long way... // // Right now, code should never get here, see above - if !self.canPut(name) { - self.runtime.typeErrorResult(throw) + if !obj.canPut(name) { + obj.runtime.typeErrorResult(throw) return } - property := self.getOwnProperty(name) - if property == nil { - property = self.getProperty(name) - if property != nil { - if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor { - getSet[1].call(toValue(self), []Value{value}, false, nativeFrame) + prop := obj.getOwnProperty(name) + if prop == nil { + prop = obj.getProperty(name) + if prop != nil { + if getSet, isAccessor := prop.value.(propertyGetSet); isAccessor { + getSet[1].call(toValue(obj), []Value{value}, false, nativeFrame) return } } - self.defineProperty(name, value, 0111, throw) - } else { - switch propertyValue := property.value.(type) { - case Value: - property.value = value - self.defineOwnProperty(name, *property, throw) - case _propertyGetSet: - if propertyValue[1] != nil { - propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame) - return - } - if throw { - panic(self.runtime.panicTypeError()) - } - default: - panic(self.runtime.panicTypeError()) + obj.defineProperty(name, value, 0o111, throw) + return + } + + switch propertyValue := prop.value.(type) { + case Value: + prop.value = value + obj.defineOwnProperty(name, *prop, throw) + case propertyGetSet: + if propertyValue[1] != nil { + propertyValue[1].call(toValue(obj), []Value{value}, false, nativeFrame) + return } + if throw { + panic(obj.runtime.panicTypeError("Object.Put nil second parameter to propertyGetSet")) + } + default: + panic(obj.runtime.panicTypeError("Object.Put unexpected type %T", prop.value)) } } -// 8.12.6 -func objectHasProperty(self *_object, name string) bool { - return self.getProperty(name) != nil +// 8.12.6. +func objectHasProperty(obj *object, name string) bool { + return obj.getProperty(name) != nil } -func objectHasOwnProperty(self *_object, name string) bool { - return self.getOwnProperty(name) != nil +func objectHasOwnProperty(obj *object, name string) bool { + return obj.getOwnProperty(name) != nil } -// 8.12.9 -func objectDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - property, exists := self._read(name) - { - if !exists { - if !self.extensible { - goto Reject - } - if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor { - if newGetSet[0] == &_nilGetSetObject { - newGetSet[0] = nil - } - if newGetSet[1] == &_nilGetSetObject { - newGetSet[1] = nil - } - descriptor.value = newGetSet - } - self._write(name, descriptor.value, descriptor.mode) - return true - } - if descriptor.isEmpty() { - return true +// 8.12.9. +func objectDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + reject := func(reason string) bool { + if throw { + panic(obj.runtime.panicTypeError("Object.DefineOwnProperty: %s", reason)) } + return false + } - // TODO Per 8.12.9.6 - We should shortcut here (returning true) if - // the current and new (define) properties are the same - - configurable := property.configurable() - if !configurable { - if descriptor.configurable() { - goto Reject - } - // Test that, if enumerable is set on the property descriptor, then it should - // be the same as the existing property - if descriptor.enumerateSet() && descriptor.enumerable() != property.enumerable() { - goto Reject - } + prop, exists := obj.readProperty(name) + if !exists { + if !obj.extensible { + return reject("not exists and not extensible") } - value, isDataDescriptor := property.value.(Value) - getSet, _ := property.value.(_propertyGetSet) - if descriptor.isGenericDescriptor() { - // GenericDescriptor - } else if isDataDescriptor != descriptor.isDataDescriptor() { - // DataDescriptor <=> AccessorDescriptor - if !configurable { - goto Reject - } - } else if isDataDescriptor && descriptor.isDataDescriptor() { - // DataDescriptor <=> DataDescriptor - if !configurable { - if !property.writable() && descriptor.writable() { - goto Reject - } - if !property.writable() { - if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) { - goto Reject - } - } - } - } else { - // AccessorDescriptor <=> AccessorDescriptor - newGetSet, _ := descriptor.value.(_propertyGetSet) - presentGet, presentSet := true, true - if newGetSet[0] == &_nilGetSetObject { - // Present, but nil + if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor { + if newGetSet[0] == &nilGetSetObject { newGetSet[0] = nil - } else if newGetSet[0] == nil { - // Missing, not even nil - newGetSet[0] = getSet[0] - presentGet = false } - if newGetSet[1] == &_nilGetSetObject { - // Present, but nil + if newGetSet[1] == &nilGetSetObject { newGetSet[1] = nil - } else if newGetSet[1] == nil { - // Missing, not even nil - newGetSet[1] = getSet[1] - presentSet = false - } - if !configurable { - if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) { - goto Reject - } } descriptor.value = newGetSet } - { - // This section will preserve attributes of - // the original property, if necessary - value1 := descriptor.value - if value1 == nil { - value1 = property.value - } else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor { - if newGetSet[0] == &_nilGetSetObject { - newGetSet[0] = nil - } - if newGetSet[1] == &_nilGetSetObject { - newGetSet[1] = nil - } - value1 = newGetSet + obj.writeProperty(name, descriptor.value, descriptor.mode) + return true + } + + if descriptor.isEmpty() { + return true + } + + // TODO Per 8.12.9.6 - We should shortcut here (returning true) if + // the current and new (define) properties are the same + + configurable := prop.configurable() + if !configurable { + if descriptor.configurable() { + return reject("property and descriptor not configurable") + } + // Test that, if enumerable is set on the property descriptor, then it should + // be the same as the existing property + if descriptor.enumerateSet() && descriptor.enumerable() != prop.enumerable() { + return reject("property not configurable and enumerable miss match") + } + } + + value, isDataDescriptor := prop.value.(Value) + getSet, _ := prop.value.(propertyGetSet) + switch { + case descriptor.isGenericDescriptor(): + // GenericDescriptor + case isDataDescriptor != descriptor.isDataDescriptor(): + // DataDescriptor <=> AccessorDescriptor + if !configurable { + return reject("property descriptor not configurable") + } + case isDataDescriptor && descriptor.isDataDescriptor(): + // DataDescriptor <=> DataDescriptor + if !configurable { + if !prop.writable() && descriptor.writable() { + return reject("property not configurable or writeable and descriptor not writeable") } - mode1 := descriptor.mode - if mode1&0222 != 0 { - // TODO Factor this out into somewhere testable - // (Maybe put into switch ...) - mode0 := property.mode - if mode1&0200 != 0 { - if descriptor.isDataDescriptor() { - mode1 &= ^0200 // Turn off "writable" missing - mode1 |= (mode0 & 0100) - } - } - if mode1&020 != 0 { - mode1 |= (mode0 & 010) + if !prop.writable() { + if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) { + return reject("property not configurable or writeable and descriptor not the same") } - if mode1&02 != 0 { - mode1 |= (mode0 & 01) - } - mode1 &= 0311 // 0311 to preserve the non-setting on "writable" } - self._write(name, value1, mode1) } - return true + default: + // AccessorDescriptor <=> AccessorDescriptor + newGetSet, _ := descriptor.value.(propertyGetSet) + presentGet, presentSet := true, true + if newGetSet[0] == &nilGetSetObject { + // Present, but nil + newGetSet[0] = nil + } else if newGetSet[0] == nil { + // Missing, not even nil + newGetSet[0] = getSet[0] + presentGet = false + } + if newGetSet[1] == &nilGetSetObject { + // Present, but nil + newGetSet[1] = nil + } else if newGetSet[1] == nil { + // Missing, not even nil + newGetSet[1] = getSet[1] + presentSet = false + } + if !configurable { + if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) { + return reject("access descriptor not configurable") + } + } + descriptor.value = newGetSet } -Reject: - if throw { - panic(self.runtime.panicTypeError()) + + // This section will preserve attributes of + // the original property, if necessary + value1 := descriptor.value + if value1 == nil { + value1 = prop.value + } else if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor { + if newGetSet[0] == &nilGetSetObject { + newGetSet[0] = nil + } + if newGetSet[1] == &nilGetSetObject { + newGetSet[1] = nil + } + value1 = newGetSet + } + mode1 := descriptor.mode + if mode1&0o222 != 0 { + // TODO Factor this out into somewhere testable + // (Maybe put into switch ...) + mode0 := prop.mode + if mode1&0o200 != 0 { + if descriptor.isDataDescriptor() { + mode1 &= ^0o200 // Turn off "writable" missing + mode1 |= (mode0 & 0o100) + } + } + if mode1&0o20 != 0 { + mode1 |= (mode0 & 0o10) + } + if mode1&0o2 != 0 { + mode1 |= (mode0 & 0o1) + } + mode1 &= 0o311 // 0311 to preserve the non-setting on "writable" } - return false + obj.writeProperty(name, value1, mode1) + + return true } -func objectDelete(self *_object, name string, throw bool) bool { - property_ := self.getOwnProperty(name) - if property_ == nil { +func objectDelete(obj *object, name string, throw bool) bool { + prop := obj.getOwnProperty(name) + if prop == nil { return true } - if property_.configurable() { - self._delete(name) + if prop.configurable() { + obj.deleteProperty(name) return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } -func objectClone(in *_object, out *_object, clone *_clone) *_object { +func objectClone(in *object, out *object, clone *cloner) *object { *out = *in out.runtime = clone.runtime if out.prototype != nil { out.prototype = clone.object(in.prototype) } - out.property = make(map[string]_property, len(in.property)) + out.property = make(map[string]property, len(in.property)) out.propertyOrder = make([]string, len(in.propertyOrder)) copy(out.propertyOrder, in.propertyOrder) - for index, property := range in.property { - out.property[index] = clone.property(property) + for index, prop := range in.property { + out.property[index] = clone.property(prop) } switch value := in.value.(type) { - case _nativeFunctionObject: + case nativeFunctionObject: out.value = value - case _bindFunctionObject: - out.value = _bindFunctionObject{ + case bindFunctionObject: + out.value = bindFunctionObject{ target: clone.object(value.target), this: clone.value(value.this), argumentList: clone.valueArray(value.argumentList), } - case _nodeFunctionObject: - out.value = _nodeFunctionObject{ + case nodeFunctionObject: + out.value = nodeFunctionObject{ node: value.node, stash: clone.stash(value.stash), } - case _argumentsObject: + case argumentsObject: out.value = value.clone(clone) } diff --git a/vendor/github.com/robertkrimen/otto/otto.go b/vendor/github.com/robertkrimen/otto/otto.go index b5b528d53..31b7e3013 100644 --- a/vendor/github.com/robertkrimen/otto/otto.go +++ b/vendor/github.com/robertkrimen/otto/otto.go @@ -3,81 +3,79 @@ Package otto is a JavaScript parser and interpreter written natively in Go. http://godoc.org/github.com/robertkrimen/otto - import ( - "github.com/robertkrimen/otto" - ) + import ( + "github.com/robertkrimen/otto" + ) Run something in the VM - vm := otto.New() - vm.Run(` - abc = 2 + 2; - console.log("The value of abc is " + abc); // 4 - `) + vm := otto.New() + vm.Run(` + abc = 2 + 2; + console.log("The value of abc is " + abc); // 4 + `) Get a value out of the VM - value, err := vm.Get("abc") - value, _ := value.ToInteger() - } + value, err := vm.Get("abc") + value, _ := value.ToInteger() + } Set a number - vm.Set("def", 11) - vm.Run(` - console.log("The value of def is " + def); - // The value of def is 11 - `) + vm.Set("def", 11) + vm.Run(` + console.log("The value of def is " + def); + // The value of def is 11 + `) Set a string - vm.Set("xyzzy", "Nothing happens.") - vm.Run(` - console.log(xyzzy.length); // 16 - `) + vm.Set("xyzzy", "Nothing happens.") + vm.Run(` + console.log(xyzzy.length); // 16 + `) Get the value of an expression - value, _ = vm.Run("xyzzy.length") - { - // value is an int64 with a value of 16 - value, _ := value.ToInteger() - } + value, _ = vm.Run("xyzzy.length") + // iv is an int64 with a value of 16 + iv, _ := value.ToInteger() An error happens - value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") - if err != nil { - // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined - // If there is an error, then value.IsUndefined() is true - ... - } + value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") + if err != nil { + // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined + // If there is an error, then value.IsUndefined() is true + ... + } Set a Go function - vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { - fmt.Printf("Hello, %s.\n", call.Argument(0).String()) - return otto.Value{} - }) + vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { + fmt.Printf("Hello, %s.\n", call.Argument(0).String()) + return otto.Value{} + }) Set a Go function that returns something useful - vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { - right, _ := call.Argument(0).ToInteger() - result, _ := vm.ToValue(2 + right) - return result - }) + vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { + right, _ := call.Argument(0).ToInteger() + result, _ := vm.ToValue(2 + right) + return result + }) Use the functions in JavaScript - result, _ = vm.Run(` - sayHello("Xyzzy"); // Hello, Xyzzy. - sayHello(); // Hello, undefined + result, _ = vm.Run(` + sayHello("Xyzzy"); // Hello, Xyzzy. + sayHello(); // Hello, undefined - result = twoPlus(2.0); // 4 - `) + result = twoPlus(2.0); // 4 + `) -Parser +# Parser A separate parser is available in the parser package if you're just interested in building an AST. @@ -85,23 +83,23 @@ http://godoc.org/github.com/robertkrimen/otto/parser Parse and return an AST - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } + filename := "" // A filename is optional + src := ` + // Sample xyzzy example + (function(){ + if (3.14159 > 0) { + console.log("Hello, World."); + return; + } - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` + var xyzzy = NaN; + console.log("Nothing happens."); + return xyzzy; + })(); + ` - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) + // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList + program, err := parser.ParseFile(nil, filename, src, 0) otto @@ -126,24 +124,24 @@ Optionally include the JavaScript utility-belt library, underscore, with this im For more information: http://github.com/robertkrimen/otto/tree/master/underscore -Caveat Emptor +# Caveat Emptor The following are some limitations with otto: - * "use strict" will parse, but does nothing. - * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. - * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. + - "use strict" will parse, but does nothing. + - The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. + - Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. -Regular Expression Incompatibility +# Regular Expression Incompatibility Go translates JavaScript-style regular expressions into something that is "regexp" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires backtracking for some patterns, and backtracking is not supported by the standard Go engine: https://code.google.com/p/re2/wiki/Syntax Therefore, the following syntax is incompatible: - (?=) // Lookahead (positive), currently a parsing error - (?!) // Lookahead (backhead), currently a parsing error - \1 // Backreference (\1, \2, \3, ...), currently a parsing error + (?=) // Lookahead (positive), currently a parsing error + (?!) // Lookahead (backhead), currently a parsing error + \1 // Backreference (\1, \2, \3, ...), currently a parsing error A brief discussion of these limitations: "Regexp (?!re)" https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E @@ -152,57 +150,57 @@ More information about re2: https://code.google.com/p/re2/ In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript definition, on the other hand, also includes \v, Unicode "Separator, Space", etc. -Halting Problem +# Halting Problem If you want to stop long running executions (like third-party code), you can use the interrupt channel to do this: - package main - - import ( - "errors" - "fmt" - "os" - "time" - - "github.com/robertkrimen/otto" - ) - - var halt = errors.New("Stahp") - - func main() { - runUnsafe(`var abc = [];`) - runUnsafe(` - while (true) { - // Loop forever - }`) - } - - func runUnsafe(unsafe string) { - start := time.Now() - defer func() { - duration := time.Since(start) - if caught := recover(); caught != nil { - if caught == halt { - fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration) - return - } - panic(caught) // Something else happened, repanic! - } - fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) - }() - - vm := otto.New() - vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking - - go func() { - time.Sleep(2 * time.Second) // Stop after two seconds - vm.Interrupt <- func() { - panic(halt) - } - }() - - vm.Run(unsafe) // Here be dragons (risky code) - } + package main + + import ( + "errors" + "fmt" + "os" + "time" + + "github.com/robertkrimen/otto" + ) + + var halt = errors.New("Stahp") + + func main() { + runUnsafe(`var abc = [];`) + runUnsafe(` + while (true) { + // Loop forever + }`) + } + + func runUnsafe(unsafe string) { + start := time.Now() + defer func() { + duration := time.Since(start) + if caught := recover(); caught != nil { + if caught == halt { + fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration) + return + } + panic(caught) // Something else happened, repanic! + } + fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) + }() + + vm := otto.New() + vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking + + go func() { + time.Sleep(2 * time.Second) // Stop after two seconds + vm.Interrupt <- func() { + panic(halt) + } + }() + + vm.Run(unsafe) // Here be dragons (risky code) + } Where is setTimeout/setInterval? @@ -216,52 +214,55 @@ http://github.com/robertkrimen/natto Here is some more discussion of the issue: * http://book.mixu.net/node/ch2.html - * http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 - * http://aaroncrane.co.uk/2009/02/perl_safe_signals/ - */ package otto import ( - "fmt" + "encoding/json" + "errors" "strings" "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/registry" ) -// Otto is the representation of the JavaScript runtime. Each instance of Otto has a self-contained namespace. +// Otto is the representation of the JavaScript runtime. +// Each instance of Otto has a self-contained namespace. type Otto struct { // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. // See "Halting Problem" for more information. Interrupt chan func() - runtime *_runtime + runtime *runtime } -// New will allocate a new JavaScript runtime +// New will allocate a new JavaScript runtime. func New() *Otto { - self := &Otto{ + o := &Otto{ runtime: newContext(), } - self.runtime.otto = self - self.runtime.traceLimit = 10 - self.Set("console", self.runtime.newConsole()) + o.runtime.otto = o + o.runtime.traceLimit = 10 + if err := o.Set("console", o.runtime.newConsole()); err != nil { + panic(err) + } registry.Apply(func(entry registry.Entry) { - self.Run(entry.Source()) + if _, err := o.Run(entry.Source()); err != nil { + panic(err) + } }) - return self + return o } -func (otto *Otto) clone() *Otto { - self := &Otto{ - runtime: otto.runtime.clone(), +func (o *Otto) clone() *Otto { + n := &Otto{ + runtime: o.runtime.clone(), } - self.runtime.otto = self - return self + n.runtime.otto = n + return n } // Run will allocate a new JavaScript runtime, run the given source @@ -273,7 +274,6 @@ func (otto *Otto) clone() *Otto { // src may also be a Script. // // src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. -// func Run(src interface{}) (*Otto, Value, error) { otto := New() value, err := otto.Run(src) // This already does safety checking @@ -290,9 +290,8 @@ func Run(src interface{}) (*Otto, Value, error) { // src may also be a Script. // // src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. -// -func (self Otto) Run(src interface{}) (Value, error) { - value, err := self.runtime.cmpl_run(src, nil) +func (o Otto) Run(src interface{}) (Value, error) { + value, err := o.runtime.cmplRun(src, nil) if !value.safe() { value = Value{} } @@ -304,13 +303,13 @@ func (self Otto) Run(src interface{}) (Value, error) { // By staying in the same scope, the code evaluated has access to everything // already defined in the current stack frame. This is most useful in, for // example, a debugger call. -func (self Otto) Eval(src interface{}) (Value, error) { - if self.runtime.scope == nil { - self.runtime.enterGlobalScope() - defer self.runtime.leaveScope() +func (o Otto) Eval(src interface{}) (Value, error) { + if o.runtime.scope == nil { + o.runtime.enterGlobalScope() + defer o.runtime.leaveScope() } - value, err := self.runtime.cmpl_eval(src, nil) + value, err := o.runtime.cmplEval(src, nil) if !value.safe() { value = Value{} } @@ -321,10 +320,10 @@ func (self Otto) Eval(src interface{}) (Value, error) { // // If there is an error (like the binding does not exist), then the value // will be undefined. -func (self Otto) Get(name string) (Value, error) { +func (o Otto) Get(name string) (Value, error) { value := Value{} err := catchPanic(func() { - value = self.getValue(name) + value = o.getValue(name) }) if !value.safe() { value = Value{} @@ -332,8 +331,8 @@ func (self Otto) Get(name string) (Value, error) { return value, err } -func (self Otto) getValue(name string) Value { - return self.runtime.globalStash.getBinding(name, false) +func (o Otto) getValue(name string) Value { + return o.runtime.globalStash.getBinding(name, false) } // Set the top-level binding of the given name to the given value. @@ -345,29 +344,29 @@ func (self Otto) getValue(name string) Value { // fails), then an error is returned. // // If the top-level binding does not exist, it will be created. -func (self Otto) Set(name string, value interface{}) error { - { - value, err := self.ToValue(value) - if err != nil { - return err - } - err = catchPanic(func() { - self.setValue(name, value) - }) +func (o Otto) Set(name string, value interface{}) error { + val, err := o.ToValue(value) + if err != nil { return err } + + return catchPanic(func() { + o.setValue(name, val) + }) } -func (self Otto) setValue(name string, value Value) { - self.runtime.globalStash.setValue(name, value, false) +func (o Otto) setValue(name string, value Value) { + o.runtime.globalStash.setValue(name, value, false) } -func (self Otto) SetDebuggerHandler(fn func(vm *Otto)) { - self.runtime.debugger = fn +// SetDebuggerHandler sets the debugger handler to fn. +func (o Otto) SetDebuggerHandler(fn func(vm *Otto)) { + o.runtime.debugger = fn } -func (self Otto) SetRandomSource(fn func() float64) { - self.runtime.random = fn +// SetRandomSource sets the random source to fn. +func (o Otto) SetRandomSource(fn func() float64) { + o.runtime.random = fn } // SetStackDepthLimit sets an upper limit to the depth of the JavaScript @@ -378,99 +377,100 @@ func (self Otto) SetRandomSource(fn func() float64) { // JavaScript makes a call to a Go function, otto won't keep track of what // happens outside the interpreter. So if your Go function is infinitely // recursive, you're still in trouble. -func (self Otto) SetStackDepthLimit(limit int) { - self.runtime.stackLimit = limit +func (o Otto) SetStackDepthLimit(limit int) { + o.runtime.stackLimit = limit } // SetStackTraceLimit sets an upper limit to the number of stack frames that // otto will use when formatting an error's stack trace. By default, the limit // is 10. This is consistent with V8 and SpiderMonkey. // -// TODO: expose via `Error.stackTraceLimit` -func (self Otto) SetStackTraceLimit(limit int) { - self.runtime.traceLimit = limit +// TODO: expose via `Error.stackTraceLimit`. +func (o Otto) SetStackTraceLimit(limit int) { + o.runtime.traceLimit = limit } // MakeCustomError creates a new Error object with the given name and message, // returning it as a Value. -func (self Otto) MakeCustomError(name, message string) Value { - return self.runtime.toValue(self.runtime.newError(name, self.runtime.toValue(message), 0)) +func (o Otto) MakeCustomError(name, message string) Value { + return o.runtime.toValue(o.runtime.newError(name, o.runtime.toValue(message), 0)) } // MakeRangeError creates a new RangeError object with the given message, // returning it as a Value. -func (self Otto) MakeRangeError(message string) Value { - return self.runtime.toValue(self.runtime.newRangeError(self.runtime.toValue(message))) +func (o Otto) MakeRangeError(message string) Value { + return o.runtime.toValue(o.runtime.newRangeError(o.runtime.toValue(message))) } // MakeSyntaxError creates a new SyntaxError object with the given message, // returning it as a Value. -func (self Otto) MakeSyntaxError(message string) Value { - return self.runtime.toValue(self.runtime.newSyntaxError(self.runtime.toValue(message))) +func (o Otto) MakeSyntaxError(message string) Value { + return o.runtime.toValue(o.runtime.newSyntaxError(o.runtime.toValue(message))) } // MakeTypeError creates a new TypeError object with the given message, // returning it as a Value. -func (self Otto) MakeTypeError(message string) Value { - return self.runtime.toValue(self.runtime.newTypeError(self.runtime.toValue(message))) +func (o Otto) MakeTypeError(message string) Value { + return o.runtime.toValue(o.runtime.newTypeError(o.runtime.toValue(message))) } // Context is a structure that contains information about the current execution // context. type Context struct { + This Value + Symbols map[string]Value Filename string - Line int - Column int Callee string - Symbols map[string]Value - This Value Stacktrace []string + Line int + Column int } // Context returns the current execution context of the vm, traversing up to // ten stack frames, and skipping any innermost native function stack frames. -func (self Otto) Context() Context { - return self.ContextSkip(10, true) +func (o Otto) Context() Context { + return o.ContextSkip(10, true) } // ContextLimit returns the current execution context of the vm, with a // specific limit on the number of stack frames to traverse, skipping any // innermost native function stack frames. -func (self Otto) ContextLimit(limit int) Context { - return self.ContextSkip(limit, true) +func (o Otto) ContextLimit(limit int) Context { + return o.ContextSkip(limit, true) } // ContextSkip returns the current execution context of the vm, with a // specific limit on the number of stack frames to traverse, optionally // skipping any innermost native function stack frames. -func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { +func (o Otto) ContextSkip(limit int, skipNative bool) Context { // Ensure we are operating in a scope - if self.runtime.scope == nil { - self.runtime.enterGlobalScope() - defer self.runtime.leaveScope() + if o.runtime.scope == nil { + o.runtime.enterGlobalScope() + defer o.runtime.leaveScope() } - scope := self.runtime.scope - frame := scope.frame + curScope := o.runtime.scope + frm := curScope.frame - for skipNative && frame.native && scope.outer != nil { - scope = scope.outer - frame = scope.frame + for skipNative && frm.native && curScope.outer != nil { + curScope = curScope.outer + frm = curScope.frame } // Get location information + var ctx Context ctx.Filename = "" - ctx.Callee = frame.callee + ctx.Callee = frm.callee switch { - case frame.native: - ctx.Filename = frame.nativeFile - ctx.Line = frame.nativeLine + case frm.native: + ctx.Filename = frm.nativeFile + ctx.Line = frm.nativeLine ctx.Column = 0 - case frame.file != nil: + case frm.file != nil: ctx.Filename = "" - if p := frame.file.Position(file.Idx(frame.offset)); p != nil { + if p := frm.file.Position(file.Idx(frm.offset)); p != nil { ctx.Line = p.Line ctx.Column = p.Column @@ -481,14 +481,14 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { } // Get the current scope this Value - ctx.This = toValue_object(scope.this) + ctx.This = objectValue(curScope.this) // Build stacktrace (up to 10 levels deep) ctx.Symbols = make(map[string]Value) - ctx.Stacktrace = append(ctx.Stacktrace, frame.location()) + ctx.Stacktrace = append(ctx.Stacktrace, frm.location()) for limit != 0 { // Get variables - stash := scope.lexical + stash := curScope.lexical for { for _, name := range getStashProperties(stash) { if _, ok := ctx.Symbols[name]; !ok { @@ -501,17 +501,17 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { } } - scope = scope.outer - if scope == nil { + curScope = curScope.outer + if curScope == nil { break } - if scope.frame.offset >= 0 { - ctx.Stacktrace = append(ctx.Stacktrace, scope.frame.location()) + if curScope.frame.offset >= 0 { + ctx.Stacktrace = append(ctx.Stacktrace, curScope.frame.location()) } limit-- } - return + return ctx } // Call the given JavaScript with a given this and arguments. @@ -524,18 +524,16 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { // Call will invoke the function constructor rather than performing a function call. // In this case, the this argument has no effect. // -// // value is a String object -// value, _ := vm.Call("Object", nil, "Hello, World.") +// // value is a String object +// value, _ := vm.Call("Object", nil, "Hello, World.") // -// // Likewise... -// value, _ := vm.Call("new Object", nil, "Hello, World.") +// // Likewise... +// value, _ := vm.Call("new Object", nil, "Hello, World.") // -// // This will perform a concat on the given array and return the result -// // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] -// value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") -// -func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { - +// // This will perform a concat on the given array and return the result +// // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] +// value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") +func (o Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { thisValue := Value{} construct := false @@ -545,21 +543,20 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } // FIXME enterGlobalScope - self.runtime.enterGlobalScope() + o.runtime.enterGlobalScope() defer func() { - self.runtime.leaveScope() + o.runtime.leaveScope() }() if !construct && this == nil { - program, err := self.runtime.cmpl_parse("", source+"()", nil) + program, err := o.runtime.cmplParse("", source+"()", nil) if err == nil { - if node, ok := program.body[0].(*_nodeExpressionStatement); ok { - if node, ok := node.expression.(*_nodeCallExpression); ok { + if node, ok := program.body[0].(*nodeExpressionStatement); ok { + if node, ok2 := node.expression.(*nodeCallExpression); ok2 { var value Value - err := catchPanic(func() { - value = self.runtime.cmpl_evaluate_nodeCallExpression(node, argumentList) - }) - if err != nil { + if err = catchPanic(func() { + value = o.runtime.cmplEvaluateNodeCallExpression(node, argumentList) + }); err != nil { return Value{}, err } return value, nil @@ -567,68 +564,65 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } } } else { - value, err := self.ToValue(this) + value, err := o.ToValue(this) if err != nil { return Value{}, err } thisValue = value } - { - this := thisValue - - fn, err := self.Run(source) - if err != nil { - return Value{}, err - } - - if construct { - result, err := fn.constructSafe(self.runtime, this, argumentList...) - if err != nil { - return Value{}, err - } - return result, nil - } + val := thisValue + fn, err := o.Run(source) + if err != nil { + return Value{}, err + } - result, err := fn.Call(this, argumentList...) - if err != nil { - return Value{}, err + if construct { + result, err2 := fn.constructSafe(o.runtime, val, argumentList...) + if err2 != nil { + return Value{}, err2 } return result, nil } + + result, err := fn.Call(val, argumentList...) + if err != nil { + return Value{}, err + } + return result, nil } // Object will run the given source and return the result as an object. // // For example, accessing an existing object: // -// object, _ := vm.Object(`Number`) +// object, _ := vm.Object(`Number`) // // Or, creating a new object: // -// object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`) +// object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`) // // Or, creating and assigning an object: // -// object, _ := vm.Object(`xyzzy = {}`) -// object.Set("volume", 11) +// object, _ := vm.Object(`xyzzy = {}`) +// object.Set("volume", 11) // // If there is an error (like the source does not result in an object), then // nil and an error is returned. -func (self Otto) Object(source string) (*Object, error) { - value, err := self.runtime.cmpl_run(source, nil) +func (o Otto) Object(source string) (*Object, error) { + value, err := o.runtime.cmplRun(source, nil) if err != nil { return nil, err } if value.IsObject() { return value.Object(), nil } - return nil, fmt.Errorf("value is not an object") + return nil, errors.New("value is not an object") } // ToValue will convert an interface{} value to a value digestible by otto/JavaScript. -func (self Otto) ToValue(value interface{}) (Value, error) { - return self.runtime.safeToValue(value) +func (o Otto) ToValue(value interface{}) (Value, error) { + return o.runtime.safeToValue(value) } // Copy will create a copy/clone of the runtime. @@ -639,64 +633,53 @@ func (self Otto) ToValue(value interface{}) (Value, error) { // etc. into a new runtime. // // Be on the lookout for memory leaks or inadvertent sharing of resources. -func (in *Otto) Copy() *Otto { +func (o *Otto) Copy() *Otto { out := &Otto{ - runtime: in.runtime.clone(), + runtime: o.runtime.clone(), } out.runtime.otto = out return out } -// Object{} - // Object is the representation of a JavaScript object. type Object struct { - object *_object + object *object value Value } -func _newObject(object *_object, value Value) *Object { - // value MUST contain object! - return &Object{ - object: object, - value: value, - } -} - // Call a method on the object. // // It is essentially equivalent to: // -// var method, _ := object.Get(name) -// method.Call(object, argumentList...) +// var method, _ := object.Get(name) +// method.Call(object, argumentList...) // // An undefined value and an error will result if: // -// 1. There is an error during conversion of the argument list -// 2. The property is not actually a function -// 3. An (uncaught) exception is thrown -// -func (self Object) Call(name string, argumentList ...interface{}) (Value, error) { +// 1. There is an error during conversion of the argument list +// 2. The property is not actually a function +// 3. An (uncaught) exception is thrown +func (o Object) Call(name string, argumentList ...interface{}) (Value, error) { // TODO: Insert an example using JavaScript below... // e.g., Object("JSON").Call("stringify", ...) - function, err := self.Get(name) + function, err := o.Get(name) if err != nil { return Value{}, err } - return function.Call(self.Value(), argumentList...) + return function.Call(o.Value(), argumentList...) } -// Value will return self as a value. -func (self Object) Value() Value { - return self.value +// Value returns the value of o. +func (o Object) Value() Value { + return o.value } // Get the value of the property with the given name. -func (self Object) Get(name string) (Value, error) { +func (o Object) Get(name string) (Value, error) { value := Value{} err := catchPanic(func() { - value = self.object.get(name) + value = o.object.get(name) }) if !value.safe() { value = Value{} @@ -708,25 +691,23 @@ func (self Object) Get(name string) (Value, error) { // // An error will result if the setting the property triggers an exception (i.e. read-only), // or there is an error during conversion of the given value. -func (self Object) Set(name string, value interface{}) error { - { - value, err := self.object.runtime.safeToValue(value) - if err != nil { - return err - } - err = catchPanic(func() { - self.object.put(name, value, true) - }) +func (o Object) Set(name string, value interface{}) error { + val, err := o.object.runtime.safeToValue(value) + if err != nil { return err } + + return catchPanic(func() { + o.object.put(name, val, true) + }) } // Keys gets the keys for the given object. // // Equivalent to calling Object.keys on the object. -func (self Object) Keys() []string { +func (o Object) Keys() []string { var keys []string - self.object.enumerate(false, func(name string) bool { + o.object.enumerate(false, func(name string) bool { keys = append(keys, name) return true }) @@ -735,10 +716,10 @@ func (self Object) Keys() []string { // KeysByParent gets the keys (and those of the parents) for the given object, // in order of "closest" to "furthest". -func (self Object) KeysByParent() [][]string { +func (o Object) KeysByParent() [][]string { var a [][]string - for o := self.object; o != nil; o = o.prototype { + for o := o.object; o != nil; o = o.prototype { var l []string o.enumerate(false, func(name string) bool { @@ -756,15 +737,41 @@ func (self Object) KeysByParent() [][]string { // // The return value will (generally) be one of: // -// Object -// Function -// Array -// String -// Number -// Boolean -// Date -// RegExp -// -func (self Object) Class() string { - return self.object.class +// Object +// Function +// Array +// String +// Number +// Boolean +// Date +// RegExp +func (o Object) Class() string { + return o.object.class +} + +// MarshalJSON implements json.Marshaller. +func (o Object) MarshalJSON() ([]byte, error) { + var goValue interface{} + switch value := o.object.value.(type) { + case *goStructObject: + goValue = value.value.Interface() + case *goMapObject: + goValue = value.value.Interface() + case *goArrayObject: + goValue = value.value.Interface() + case *goSliceObject: + goValue = value.value.Interface() + default: + // It's a JS object; pass it to JSON.stringify: + var result []byte + err := catchPanic(func() { + resultVal := builtinJSONStringify(FunctionCall{ + runtime: o.object.runtime, + ArgumentList: []Value{o.value}, + }) + result = []byte(resultVal.String()) + }) + return result, err + } + return json.Marshal(goValue) } diff --git a/vendor/github.com/robertkrimen/otto/otto_.go b/vendor/github.com/robertkrimen/otto/otto_.go index 304a83150..2bf06d27d 100644 --- a/vendor/github.com/robertkrimen/otto/otto_.go +++ b/vendor/github.com/robertkrimen/otto/otto_.go @@ -3,29 +3,28 @@ package otto import ( "fmt" "regexp" - runtime_ "runtime" + goruntime "runtime" "strconv" - "strings" ) -var isIdentifier_Regexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`) +var isIdentifierRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`) -func isIdentifier(string_ string) bool { - return isIdentifier_Regexp.MatchString(string_) +func isIdentifier(value string) bool { + return isIdentifierRegexp.MatchString(value) } -func (self *_runtime) toValueArray(arguments ...interface{}) []Value { +func (rt *runtime) toValueArray(arguments ...interface{}) []Value { length := len(arguments) if length == 1 { if valueArray, ok := arguments[0].([]Value); ok { return valueArray } - return []Value{self.toValue(arguments[0])} + return []Value{rt.toValue(arguments[0])} } valueArray := make([]Value, length) for index, value := range arguments { - valueArray[index] = self.toValue(value) + valueArray[index] = rt.toValue(value) } return valueArray @@ -90,15 +89,13 @@ func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int6 if index < 0 { index = 0 } - } else { - if index > length { - index = length - } + } else if index > length { + index = length } return index } -func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { +func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { //nolint:nonamedreturns start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero) if len(array) == 1 { // If there is only the start argument, then end = size @@ -116,14 +113,14 @@ func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end i return } -func rangeStartLength(source []Value, size int64) (start, length int64) { +func rangeStartLength(source []Value, size int64) (start, length int64) { //nolint:nonamedreturns start = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false) // Assume the second argument is missing or undefined - length = int64(size) + length = size if len(source) == 1 { // If there is only the start argument, then length = size - return + return start, length } lengthValue := valueOfArrayIndex(source, 1) @@ -131,21 +128,13 @@ func rangeStartLength(source []Value, size int64) (start, length int64) { // Which it is not, so get the value as an array index length = lengthValue.number().int64 } - return -} - -func boolFields(input string) (result map[string]bool) { - result = map[string]bool{} - for _, word := range strings.Fields(input) { - result[word] = true - } - return result + return start, length } func hereBeDragons(arguments ...interface{}) string { - pc, _, _, _ := runtime_.Caller(1) - name := runtime_.FuncForPC(pc).Name() - message := fmt.Sprintf("Here be dragons -- %s", name) + pc, _, _, _ := goruntime.Caller(1) //nolint:dogsled + name := goruntime.FuncForPC(pc).Name() + message := "Here be dragons -- " + name if len(arguments) > 0 { message += ": " argument0 := fmt.Sprintf("%s", arguments[0]) @@ -159,20 +148,3 @@ func hereBeDragons(arguments ...interface{}) string { } return message } - -func throwHereBeDragons(arguments ...interface{}) { - panic(hereBeDragons(arguments...)) -} - -func eachPair(list []interface{}, fn func(_0, _1 interface{})) { - for len(list) > 0 { - var _0, _1 interface{} - _0 = list[0] - list = list[1:] // Pop off first - if len(list) > 0 { - _1 = list[0] - list = list[1:] // Pop off second - } - fn(_0, _1) - } -} diff --git a/vendor/github.com/robertkrimen/otto/parser/Makefile b/vendor/github.com/robertkrimen/otto/parser/Makefile deleted file mode 100644 index 766fd4d0b..000000000 --- a/vendor/github.com/robertkrimen/otto/parser/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -.PHONY: test - -test: - go test diff --git a/vendor/github.com/robertkrimen/otto/parser/README.markdown b/vendor/github.com/robertkrimen/otto/parser/README.markdown deleted file mode 100644 index c3cae5b60..000000000 --- a/vendor/github.com/robertkrimen/otto/parser/README.markdown +++ /dev/null @@ -1,190 +0,0 @@ -# parser --- - import "github.com/robertkrimen/otto/parser" - -Package parser implements a parser for JavaScript. - - import ( - "github.com/robertkrimen/otto/parser" - ) - -Parse and return an AST - - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } - - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) - - -### Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -## Usage - -#### func ParseFile - -```go -func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) -``` -ParseFile parses the source code of a single JavaScript/ECMAScript source file -and returns the corresponding ast.Program node. - -If fileSet == nil, ParseFile parses source without a FileSet. If fileSet != nil, -ParseFile first adds filename and src to fileSet. - -The filename argument is optional and is used for labelling errors, etc. - -src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST -always be in UTF-8. - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) - -#### func ParseFunction - -```go -func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) -``` -ParseFunction parses a given parameter list and body as a function and returns -the corresponding ast.FunctionLiteral node. - -The parameter list, if any, should be a comma-separated list of identifiers. - -#### func ReadSource - -```go -func ReadSource(filename string, src interface{}) ([]byte, error) -``` - -#### func TransformRegExp - -```go -func TransformRegExp(pattern string) (string, error) -``` -TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern. - -re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or -backreference (\1, \2, ...) will cause an error. - -re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript -definition, on the other hand, also includes \v, Unicode "Separator, Space", -etc. - -If the pattern is invalid (not valid even in JavaScript), then this function -returns the empty string and an error. - -If the pattern is valid, but incompatible (contains a lookahead or -backreference), then this function returns the transformation (a non-empty -string) AND an error. - -#### type Error - -```go -type Error struct { - Position file.Position - Message string -} -``` - -An Error represents a parsing error. It includes the position where the error -occurred and a message/description. - -#### func (Error) Error - -```go -func (self Error) Error() string -``` - -#### type ErrorList - -```go -type ErrorList []*Error -``` - -ErrorList is a list of *Errors. - -#### func (*ErrorList) Add - -```go -func (self *ErrorList) Add(position file.Position, msg string) -``` -Add adds an Error with given position and message to an ErrorList. - -#### func (ErrorList) Err - -```go -func (self ErrorList) Err() error -``` -Err returns an error equivalent to this ErrorList. If the list is empty, Err -returns nil. - -#### func (ErrorList) Error - -```go -func (self ErrorList) Error() string -``` -Error implements the Error interface. - -#### func (ErrorList) Len - -```go -func (self ErrorList) Len() int -``` - -#### func (ErrorList) Less - -```go -func (self ErrorList) Less(i, j int) bool -``` - -#### func (*ErrorList) Reset - -```go -func (self *ErrorList) Reset() -``` -Reset resets an ErrorList to no errors. - -#### func (ErrorList) Sort - -```go -func (self ErrorList) Sort() -``` - -#### func (ErrorList) Swap - -```go -func (self ErrorList) Swap(i, j int) -``` - -#### type Mode - -```go -type Mode uint -``` - -A Mode value is a set of flags (or 0). They control optional parser -functionality. - -```go -const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) -) -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/parser/dbg.go b/vendor/github.com/robertkrimen/otto/parser/dbg.go deleted file mode 100644 index 3c5f2f698..000000000 --- a/vendor/github.com/robertkrimen/otto/parser/dbg.go +++ /dev/null @@ -1,9 +0,0 @@ -// This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) for github.com/robertkrimen/dbg - -package parser - -import ( - Dbg "github.com/robertkrimen/otto/dbg" -) - -var dbg, dbgf = Dbg.New() diff --git a/vendor/github.com/robertkrimen/otto/parser/error.go b/vendor/github.com/robertkrimen/otto/parser/error.go index e0f74a5cf..94d5a27b1 100644 --- a/vendor/github.com/robertkrimen/otto/parser/error.go +++ b/vendor/github.com/robertkrimen/otto/parser/error.go @@ -9,9 +9,8 @@ import ( ) const ( - err_UnexpectedToken = "Unexpected token %v" - err_UnexpectedEndOfInput = "Unexpected end of input" - err_UnexpectedEscape = "Unexpected escape" + errUnexpectedToken = "Unexpected token %v" + errUnexpectedEndOfInput = "Unexpected end of input" ) // UnexpectedNumber: 'Unexpected number', @@ -21,7 +20,7 @@ const ( // NewlineAfterThrow: 'Illegal newline after throw', // InvalidRegExp: 'Invalid regular expression', // UnterminatedRegExp: 'Invalid regular expression: missing /', -// InvalidLHSInAssignment: 'Invalid left-hand side in assignment', +// InvalidLHSInAssignment: 'invalid left-hand side in assignment', // InvalidLHSInForIn: 'Invalid left-hand side in for-in', // MultipleDefaultsInSwitch: 'More than one default clause in switch statement', // NoCatchOrFinally: 'Missing catch or finally after try', @@ -50,33 +49,33 @@ const ( // An Error represents a parsing error. It includes the position where the error occurred and a message/description. type Error struct { - Position file.Position Message string + Position file.Position } // FIXME Should this be "SyntaxError"? -func (self Error) Error() string { - filename := self.Position.Filename +func (e Error) Error() string { + filename := e.Position.Filename if filename == "" { filename = "(anonymous)" } return fmt.Sprintf("%s: Line %d:%d %s", filename, - self.Position.Line, - self.Position.Column, - self.Message, + e.Position.Line, + e.Position.Column, + e.Message, ) } -func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error { - idx := file.Idx(0) +func (p *parser) error(place interface{}, msg string, msgValues ...interface{}) { + var idx file.Idx switch place := place.(type) { case int: - idx = self.idxOf(place) + idx = p.idxOf(place) case file.Idx: if place == 0 { - idx = self.idxOf(self.chrOffset) + idx = p.idxOf(p.chrOffset) } else { idx = place } @@ -84,58 +83,69 @@ func (self *_parser) error(place interface{}, msg string, msgValues ...interface panic(fmt.Errorf("error(%T, ...)", place)) } - position := self.position(idx) + position := p.position(idx) msg = fmt.Sprintf(msg, msgValues...) - self.errors.Add(position, msg) - return self.errors[len(self.errors)-1] + p.errors.Add(position, msg) } -func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error { +func (p *parser) errorUnexpected(idx file.Idx, chr rune) { if chr == -1 { - return self.error(idx, err_UnexpectedEndOfInput) + p.error(idx, errUnexpectedEndOfInput) + return } - return self.error(idx, err_UnexpectedToken, token.ILLEGAL) + p.error(idx, errUnexpectedToken, token.ILLEGAL) } -func (self *_parser) errorUnexpectedToken(tkn token.Token) error { - switch tkn { - case token.EOF: - return self.error(file.Idx(0), err_UnexpectedEndOfInput) +func (p *parser) errorUnexpectedToken(tkn token.Token) { + if tkn == token.EOF { + p.error(file.Idx(0), errUnexpectedEndOfInput) + return } value := tkn.String() switch tkn { case token.BOOLEAN, token.NULL: - value = self.literal + p.error(p.idx, errUnexpectedToken, p.literal) case token.IDENTIFIER: - return self.error(self.idx, "Unexpected identifier") + p.error(p.idx, "Unexpected identifier") case token.KEYWORD: // TODO Might be a future reserved word - return self.error(self.idx, "Unexpected reserved word") + p.error(p.idx, "Unexpected reserved word") case token.NUMBER: - return self.error(self.idx, "Unexpected number") + p.error(p.idx, "Unexpected number") case token.STRING: - return self.error(self.idx, "Unexpected string") + p.error(p.idx, "Unexpected string") + default: + p.error(p.idx, errUnexpectedToken, value) } - return self.error(self.idx, err_UnexpectedToken, value) } // ErrorList is a list of *Errors. -// -type ErrorList []*Error +type ErrorList []*Error //nolint:errname // Add adds an Error with given position and message to an ErrorList. -func (self *ErrorList) Add(position file.Position, msg string) { - *self = append(*self, &Error{position, msg}) +func (el *ErrorList) Add(position file.Position, msg string) { + *el = append(*el, &Error{Position: position, Message: msg}) } // Reset resets an ErrorList to no errors. -func (self *ErrorList) Reset() { *self = (*self)[0:0] } +func (el *ErrorList) Reset() { + *el = (*el)[0:0] +} -func (self ErrorList) Len() int { return len(self) } -func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] } -func (self ErrorList) Less(i, j int) bool { - x := &self[i].Position - y := &self[j].Position +// Len implement sort.Interface. +func (el *ErrorList) Len() int { + return len(*el) +} + +// Swap implement sort.Interface. +func (el *ErrorList) Swap(i, j int) { + (*el)[i], (*el)[j] = (*el)[j], (*el)[i] +} + +// Less implement sort.Interface. +func (el *ErrorList) Less(i, j int) bool { + x := (*el)[i].Position + y := (*el)[j].Position if x.Filename < y.Filename { return true } @@ -150,26 +160,28 @@ func (self ErrorList) Less(i, j int) bool { return false } -func (self ErrorList) Sort() { - sort.Sort(self) +// Sort sorts el. +func (el *ErrorList) Sort() { + sort.Sort(el) } // Error implements the Error interface. -func (self ErrorList) Error() string { - switch len(self) { +func (el *ErrorList) Error() string { + switch len(*el) { case 0: return "no errors" case 1: - return self[0].Error() + return (*el)[0].Error() + default: + return fmt.Sprintf("%s (and %d more errors)", (*el)[0].Error(), len(*el)-1) } - return fmt.Sprintf("%s (and %d more errors)", self[0].Error(), len(self)-1) } // Err returns an error equivalent to this ErrorList. // If the list is empty, Err returns nil. -func (self ErrorList) Err() error { - if len(self) == 0 { +func (el *ErrorList) Err() error { + if len(*el) == 0 { return nil } - return self + return el } diff --git a/vendor/github.com/robertkrimen/otto/parser/expression.go b/vendor/github.com/robertkrimen/otto/parser/expression.go index 63a169d40..2c8e2994c 100644 --- a/vendor/github.com/robertkrimen/otto/parser/expression.go +++ b/vendor/github.com/robertkrimen/otto/parser/expression.go @@ -8,36 +8,36 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_parser) parseIdentifier() *ast.Identifier { - literal := self.literal - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) +func (p *parser) parseIdentifier() *ast.Identifier { + literal := p.literal + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) } - self.next() + p.next() exp := &ast.Identifier{ Name: literal, Idx: idx, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp } -func (self *_parser) parsePrimaryExpression() ast.Expression { - literal := self.literal - idx := self.idx - switch self.token { +func (p *parser) parsePrimaryExpression() ast.Expression { + literal := p.literal + idx := p.idx + switch p.token { case token.IDENTIFIER: - self.next() + p.next() if len(literal) > 1 { tkn, strict := token.IsKeyword(literal) if tkn == token.KEYWORD { if !strict { - self.error(idx, "Unexpected reserved word") + p.error(idx, "Unexpected reserved word") } } } @@ -46,13 +46,13 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Idx: idx, } case token.NULL: - self.next() + p.next() return &ast.NullLiteral{ Idx: idx, Literal: literal, } case token.BOOLEAN: - self.next() + p.next() value := false switch literal { case "true": @@ -60,7 +60,7 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { case "false": value = false default: - self.error(idx, "Illegal boolean literal") + p.error(idx, "Illegal boolean literal") } return &ast.BooleanLiteral{ Idx: idx, @@ -68,10 +68,10 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.STRING: - self.next() + p.next() value, err := parseStringLiteral(literal[1 : len(literal)-1]) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } return &ast.StringLiteral{ Idx: idx, @@ -79,10 +79,10 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.NUMBER: - self.next() + p.next() value, err := parseNumberLiteral(literal) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) value = 0 } return &ast.NumberLiteral{ @@ -91,79 +91,75 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.SLASH, token.QUOTIENT_ASSIGN: - return self.parseRegExpLiteral() + return p.parseRegExpLiteral() case token.LEFT_BRACE: - return self.parseObjectLiteral() + return p.parseObjectLiteral() case token.LEFT_BRACKET: - return self.parseArrayLiteral() + return p.parseArrayLiteral() case token.LEFT_PARENTHESIS: - self.expect(token.LEFT_PARENTHESIS) - expression := self.parseExpression() - if self.mode&StoreComments != 0 { - self.comments.Unset() + p.expect(token.LEFT_PARENTHESIS) + expression := p.parseExpression() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.RIGHT_PARENTHESIS) return expression case token.THIS: - self.next() + p.next() return &ast.ThisExpression{ Idx: idx, } case token.FUNCTION: - return self.parseFunction(false) + return p.parseFunction(false) } - self.errorUnexpectedToken(self.token) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.errorUnexpectedToken(p.token) + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } -func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { - - offset := self.chrOffset - 1 // Opening slash already gotten - if self.token == token.QUOTIENT_ASSIGN { - offset -= 1 // = +func (p *parser) parseRegExpLiteral() *ast.RegExpLiteral { + offset := p.chrOffset - 1 // Opening slash already gotten + if p.token == token.QUOTIENT_ASSIGN { + offset-- // = } - idx := self.idxOf(offset) + idx := p.idxOf(offset) - pattern, err := self.scanString(offset) - endOffset := self.chrOffset + pattern, err := p.scanString(offset) + endOffset := p.chrOffset - self.next() + p.next() if err == nil { pattern = pattern[1 : len(pattern)-1] } flags := "" - if self.token == token.IDENTIFIER { // gim - - flags = self.literal - self.next() - endOffset = self.chrOffset - 1 + if p.token == token.IDENTIFIER { // gim + flags = p.literal + endOffset = p.chrOffset + p.next() } var value string // TODO 15.10 - { - // Test during parsing that this is a valid regular expression - // Sorry, (?=) and (?!) are invalid (for now) - pattern, err := TransformRegExp(pattern) + // Test during parsing that this is a valid regular expression + // Sorry, (?=) and (?!) are invalid (for now) + pat, err := TransformRegExp(pattern) + if err != nil { + if pat == "" || p.mode&IgnoreRegExpErrors == 0 { + p.error(idx, "Invalid regular expression: %s", err.Error()) + } + } else { + _, err = regexp.Compile(pat) if err != nil { - if pattern == "" || self.mode&IgnoreRegExpErrors == 0 { - self.error(idx, "Invalid regular expression: %s", err.Error()) - } + // We should not get here, ParseRegExp should catch any errors + p.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp error" } else { - _, err = regexp.Compile(pattern) - if err != nil { - // We should not get here, ParseRegExp should catch any errors - self.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp error" - } else { - value = pattern - } + value = pat } } - literal := self.str[offset:endOffset] + literal := p.str[offset:endOffset] return &ast.RegExpLiteral{ Idx: idx, @@ -174,75 +170,73 @@ func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { } } -func (self *_parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression { - - if self.token != token.IDENTIFIER { - idx := self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} +func (p *parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression { + if p.token != token.IDENTIFIER { + idx := p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } - literal := self.literal - idx := self.idx - self.next() + literal := p.literal + idx := p.idx + p.next() node := &ast.VariableExpression{ Name: literal, Idx: idx, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(node) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(node) } if declarationList != nil { *declarationList = append(*declarationList, node) } - if self.token == token.ASSIGN { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.ASSIGN { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - node.Initializer = self.parseAssignmentExpression() + p.next() + node.Initializer = p.parseAssignmentExpression() } return node } -func (self *_parser) parseVariableDeclarationList(var_ file.Idx) []ast.Expression { - +func (p *parser) parseVariableDeclarationList(idx file.Idx) []ast.Expression { var declarationList []*ast.VariableExpression // Avoid bad expressions var list []ast.Expression for { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) } - decl := self.parseVariableDeclaration(&declarationList) + decl := p.parseVariableDeclaration(&declarationList) list = append(list, decl) - if self.token != token.COMMA { + if p.token != token.COMMA { break } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() } - self.scope.declare(&ast.VariableDeclaration{ - Var: var_, + p.scope.declare(&ast.VariableDeclaration{ + Var: idx, List: declarationList, }) return list } -func (self *_parser) parseObjectPropertyKey() (string, string) { - idx, tkn, literal := self.idx, self.token, self.literal +func (p *parser) parseObjectPropertyKey() (string, string) { + idx, tkn, literal := p.idx, p.token, p.literal value := "" - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.KEY) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.KEY) } - self.next() + p.next() switch tkn { case token.IDENTIFIER: @@ -251,7 +245,7 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { var err error _, err = parseNumberLiteral(literal) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } else { value = literal } @@ -259,7 +253,7 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { var err error value, err = parseStringLiteral(literal[1 : len(literal)-1]) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } default: // null, false, class, etc. @@ -270,33 +264,33 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { return literal, value } -func (self *_parser) parseObjectProperty() ast.Property { - literal, value := self.parseObjectPropertyKey() - if literal == "get" && self.token != token.COLON { - idx := self.idx - _, value := self.parseObjectPropertyKey() - parameterList := self.parseFunctionParameterList() +func (p *parser) parseObjectProperty() ast.Property { + literal, value := p.parseObjectPropertyKey() + if literal == "get" && p.token != token.COLON { + idx := p.idx + _, value = p.parseObjectPropertyKey() + parameterList := p.parseFunctionParameterList() node := &ast.FunctionLiteral{ Function: idx, ParameterList: parameterList, } - self.parseFunctionBlock(node) + p.parseFunctionBlock(node) return ast.Property{ Key: value, Kind: "get", Value: node, } - } else if literal == "set" && self.token != token.COLON { - idx := self.idx - _, value := self.parseObjectPropertyKey() - parameterList := self.parseFunctionParameterList() + } else if literal == "set" && p.token != token.COLON { + idx := p.idx + _, value = p.parseObjectPropertyKey() + parameterList := p.parseFunctionParameterList() node := &ast.FunctionLiteral{ Function: idx, ParameterList: parameterList, } - self.parseFunctionBlock(node) + p.parseFunctionBlock(node) return ast.Property{ Key: value, Kind: "set", @@ -304,40 +298,40 @@ func (self *_parser) parseObjectProperty() ast.Property { } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.COLON) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.COLON) } - self.expect(token.COLON) + p.expect(token.COLON) exp := ast.Property{ Key: value, Kind: "value", - Value: self.parseAssignmentExpression(), + Value: p.parseAssignmentExpression(), } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp.Value) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp.Value) } return exp } -func (self *_parser) parseObjectLiteral() ast.Expression { +func (p *parser) parseObjectLiteral() ast.Expression { var value []ast.Property - idx0 := self.expect(token.LEFT_BRACE) - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - value = append(value, self.parseObjectProperty()) - if self.token == token.COMMA { - if self.mode&StoreComments != 0 { - self.comments.Unset() + idx0 := p.expect(token.LEFT_BRACE) + for p.token != token.RIGHT_BRACE && p.token != token.EOF { + value = append(value, p.parseObjectProperty()) + if p.token == token.COMMA { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() continue } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.FINAL) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.FINAL) } - idx1 := self.expect(token.RIGHT_BRACE) + idx1 := p.expect(token.RIGHT_BRACE) return &ast.ObjectLiteral{ LeftBrace: idx0, @@ -346,37 +340,37 @@ func (self *_parser) parseObjectLiteral() ast.Expression { } } -func (self *_parser) parseArrayLiteral() ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) +func (p *parser) parseArrayLiteral() ast.Expression { + idx0 := p.expect(token.LEFT_BRACKET) var value []ast.Expression - for self.token != token.RIGHT_BRACKET && self.token != token.EOF { - if self.token == token.COMMA { + for p.token != token.RIGHT_BRACKET && p.token != token.EOF { + if p.token == token.COMMA { // This kind of comment requires a special empty expression node. - empty := &ast.EmptyExpression{self.idx, self.idx} + empty := &ast.EmptyExpression{Begin: p.idx, End: p.idx} - if self.mode&StoreComments != 0 { - self.comments.SetExpression(empty) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.SetExpression(empty) + p.comments.Unset() } value = append(value, empty) - self.next() + p.next() continue } - exp := self.parseAssignmentExpression() + exp := p.parseAssignmentExpression() value = append(value, exp) - if self.token != token.RIGHT_BRACKET { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token != token.RIGHT_BRACKET { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COMMA) + p.expect(token.COMMA) } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.FINAL) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.FINAL) } - idx1 := self.expect(token.RIGHT_BRACKET) + idx1 := p.expect(token.RIGHT_BRACKET) return &ast.ArrayLiteral{ LeftBracket: idx0, @@ -385,36 +379,34 @@ func (self *_parser) parseArrayLiteral() ast.Expression { } } -func (self *_parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { - if self.mode&StoreComments != 0 { - self.comments.Unset() +func (p *parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { //nolint:nonamedreturns + if p.mode&StoreComments != 0 { + p.comments.Unset() } - idx0 = self.expect(token.LEFT_PARENTHESIS) - if self.token != token.RIGHT_PARENTHESIS { - for { - exp := self.parseAssignmentExpression() - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) - } - argumentList = append(argumentList, exp) - if self.token != token.COMMA { - break - } - if self.mode&StoreComments != 0 { - self.comments.Unset() - } - self.next() + idx0 = p.expect(token.LEFT_PARENTHESIS) + for p.token != token.RIGHT_PARENTHESIS { + exp := p.parseAssignmentExpression() + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) + } + argumentList = append(argumentList, exp) + if p.token != token.COMMA { + break + } + if p.mode&StoreComments != 0 { + p.comments.Unset() } + p.next() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - idx1 = self.expect(token.RIGHT_PARENTHESIS) + idx1 = p.expect(token.RIGHT_PARENTHESIS) return } -func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { - argumentList, idx0, idx1 := self.parseArgumentList() +func (p *parser) parseCallExpression(left ast.Expression) ast.Expression { + argumentList, idx0, idx1 := p.parseArgumentList() exp := &ast.CallExpression{ Callee: left, LeftParenthesis: idx0, @@ -422,25 +414,25 @@ func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { RightParenthesis: idx1, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp } -func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { - period := self.expect(token.PERIOD) +func (p *parser) parseDotMember(left ast.Expression) ast.Expression { + period := p.expect(token.PERIOD) - literal := self.literal - idx := self.idx + literal := p.literal + idx := p.idx if !matchIdentifier.MatchString(literal) { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: period, To: self.idx} + p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadExpression{From: period, To: p.idx} } - self.next() + p.next() return &ast.DotExpression{ Left: left, @@ -451,10 +443,10 @@ func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { } } -func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) - member := self.parseExpression() - idx1 := self.expect(token.RIGHT_BRACKET) +func (p *parser) parseBracketMember(left ast.Expression) ast.Expression { + idx0 := p.expect(token.LEFT_BRACKET) + member := p.parseExpression() + idx1 := p.expect(token.RIGHT_BRACKET) return &ast.BracketExpression{ LeftBracket: idx0, Left: left, @@ -463,125 +455,121 @@ func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { } } -func (self *_parser) parseNewExpression() ast.Expression { - idx := self.expect(token.NEW) - callee := self.parseLeftHandSideExpression() +func (p *parser) parseNewExpression() ast.Expression { + idx := p.expect(token.NEW) + callee := p.parseLeftHandSideExpression() node := &ast.NewExpression{ New: idx, Callee: callee, } - if self.token == token.LEFT_PARENTHESIS { - argumentList, idx0, idx1 := self.parseArgumentList() + if p.token == token.LEFT_PARENTHESIS { + argumentList, idx0, idx1 := p.parseArgumentList() node.ArgumentList = argumentList node.LeftParenthesis = idx0 node.RightParenthesis = idx1 } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(node) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(node) } return node } -func (self *_parser) parseLeftHandSideExpression() ast.Expression { - +func (p *parser) parseLeftHandSideExpression() ast.Expression { var left ast.Expression - if self.token == token.NEW { - left = self.parseNewExpression() + if p.token == token.NEW { + left = p.parseNewExpression() } else { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parsePrimaryExpression() + left = p.parsePrimaryExpression() } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(left) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(left) } for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACKET { - left = self.parseBracketMember(left) - } else { - break + switch p.token { + case token.PERIOD: + left = p.parseDotMember(left) + case token.LEFT_BRACKET: + left = p.parseBracketMember(left) + default: + return left } } - - return left } -func (self *_parser) parseLeftHandSideExpressionAllowCall() ast.Expression { - - allowIn := self.scope.allowIn - self.scope.allowIn = true +func (p *parser) parseLeftHandSideExpressionAllowCall() ast.Expression { + allowIn := p.scope.allowIn + p.scope.allowIn = true defer func() { - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn }() var left ast.Expression - if self.token == token.NEW { + if p.token == token.NEW { var newComments []*ast.Comment - if self.mode&StoreComments != 0 { - newComments = self.comments.FetchAll() - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + newComments = p.comments.FetchAll() + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parseNewExpression() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(left, newComments, ast.LEADING) + left = p.parseNewExpression() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(left, newComments, ast.LEADING) } } else { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parsePrimaryExpression() + left = p.parsePrimaryExpression() } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(left) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(left) } for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACKET { - left = self.parseBracketMember(left) - } else if self.token == token.LEFT_PARENTHESIS { - left = self.parseCallExpression(left) - } else { - break + switch p.token { + case token.PERIOD: + left = p.parseDotMember(left) + case token.LEFT_BRACKET: + left = p.parseBracketMember(left) + case token.LEFT_PARENTHESIS: + left = p.parseCallExpression(left) + default: + return left } } - - return left } -func (self *_parser) parsePostfixExpression() ast.Expression { - operand := self.parseLeftHandSideExpressionAllowCall() +func (p *parser) parsePostfixExpression() ast.Expression { + operand := p.parseLeftHandSideExpressionAllowCall() - switch self.token { + switch p.token { case token.INCREMENT, token.DECREMENT: // Make sure there is no line terminator here - if self.implicitSemicolon { + if p.implicitSemicolon { break } - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() switch operand.(type) { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: default: - self.error(idx, "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.error(idx, "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } exp := &ast.UnaryExpression{ Operator: tkn, @@ -590,8 +578,8 @@ func (self *_parser) parsePostfixExpression() ast.Expression { Postfix: true, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp @@ -600,38 +588,37 @@ func (self *_parser) parsePostfixExpression() ast.Expression { return operand } -func (self *_parser) parseUnaryExpression() ast.Expression { - - switch self.token { +func (p *parser) parseUnaryExpression() ast.Expression { + switch p.token { case token.PLUS, token.MINUS, token.NOT, token.BITWISE_NOT: fallthrough case token.DELETE, token.VOID, token.TYPEOF: - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() return &ast.UnaryExpression{ Operator: tkn, Idx: idx, - Operand: self.parseUnaryExpression(), + Operand: p.parseUnaryExpression(), } case token.INCREMENT, token.DECREMENT: - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - operand := self.parseUnaryExpression() + p.next() + operand := p.parseUnaryExpression() switch operand.(type) { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: default: - self.error(idx, "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.error(idx, "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } return &ast.UnaryExpression{ Operator: tkn, @@ -640,20 +627,20 @@ func (self *_parser) parseUnaryExpression() ast.Expression { } } - return self.parsePostfixExpression() + return p.parsePostfixExpression() } -func (self *_parser) parseMultiplicativeExpression() ast.Expression { - next := self.parseUnaryExpression +func (p *parser) parseMultiplicativeExpression() ast.Expression { + next := p.parseUnaryExpression left := next() - for self.token == token.MULTIPLY || self.token == token.SLASH || - self.token == token.REMAINDER { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.MULTIPLY || p.token == token.SLASH || + p.token == token.REMAINDER { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -665,16 +652,16 @@ func (self *_parser) parseMultiplicativeExpression() ast.Expression { return left } -func (self *_parser) parseAdditiveExpression() ast.Expression { - next := self.parseMultiplicativeExpression +func (p *parser) parseAdditiveExpression() ast.Expression { + next := p.parseMultiplicativeExpression left := next() - for self.token == token.PLUS || self.token == token.MINUS { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.PLUS || p.token == token.MINUS { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -686,17 +673,17 @@ func (self *_parser) parseAdditiveExpression() ast.Expression { return left } -func (self *_parser) parseShiftExpression() ast.Expression { - next := self.parseAdditiveExpression +func (p *parser) parseShiftExpression() ast.Expression { + next := p.parseAdditiveExpression left := next() - for self.token == token.SHIFT_LEFT || self.token == token.SHIFT_RIGHT || - self.token == token.UNSIGNED_SHIFT_RIGHT { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.SHIFT_LEFT || p.token == token.SHIFT_RIGHT || + p.token == token.UNSIGNED_SHIFT_RIGHT { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -708,58 +695,58 @@ func (self *_parser) parseShiftExpression() ast.Expression { return left } -func (self *_parser) parseRelationalExpression() ast.Expression { - next := self.parseShiftExpression +func (p *parser) parseRelationalExpression() ast.Expression { + next := p.parseShiftExpression left := next() - allowIn := self.scope.allowIn - self.scope.allowIn = true + allowIn := p.scope.allowIn + p.scope.allowIn = true defer func() { - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn }() - switch self.token { + switch p.token { case token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL: - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), Comparison: true, } return exp case token.INSTANCEOF: - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), } return exp case token.IN: if !allowIn { return left } - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), } return exp } @@ -767,17 +754,17 @@ func (self *_parser) parseRelationalExpression() ast.Expression { return left } -func (self *_parser) parseEqualityExpression() ast.Expression { - next := self.parseRelationalExpression +func (p *parser) parseEqualityExpression() ast.Expression { + next := p.parseRelationalExpression left := next() - for self.token == token.EQUAL || self.token == token.NOT_EQUAL || - self.token == token.STRICT_EQUAL || self.token == token.STRICT_NOT_EQUAL { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.EQUAL || p.token == token.NOT_EQUAL || + p.token == token.STRICT_EQUAL || p.token == token.STRICT_NOT_EQUAL { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -790,16 +777,16 @@ func (self *_parser) parseEqualityExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseAndExpression() ast.Expression { - next := self.parseEqualityExpression +func (p *parser) parseBitwiseAndExpression() ast.Expression { + next := p.parseEqualityExpression left := next() - for self.token == token.AND { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.AND { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -811,16 +798,16 @@ func (self *_parser) parseBitwiseAndExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { - next := self.parseBitwiseAndExpression +func (p *parser) parseBitwiseExclusiveOrExpression() ast.Expression { + next := p.parseBitwiseAndExpression left := next() - for self.token == token.EXCLUSIVE_OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.EXCLUSIVE_OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -832,16 +819,16 @@ func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseOrExpression() ast.Expression { - next := self.parseBitwiseExclusiveOrExpression +func (p *parser) parseBitwiseOrExpression() ast.Expression { + next := p.parseBitwiseExclusiveOrExpression left := next() - for self.token == token.OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -853,16 +840,16 @@ func (self *_parser) parseBitwiseOrExpression() ast.Expression { return left } -func (self *_parser) parseLogicalAndExpression() ast.Expression { - next := self.parseBitwiseOrExpression +func (p *parser) parseLogicalAndExpression() ast.Expression { + next := p.parseBitwiseOrExpression left := next() - for self.token == token.LOGICAL_AND { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.LOGICAL_AND { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -874,16 +861,16 @@ func (self *_parser) parseLogicalAndExpression() ast.Expression { return left } -func (self *_parser) parseLogicalOrExpression() ast.Expression { - next := self.parseLogicalAndExpression +func (p *parser) parseLogicalOrExpression() ast.Expression { + next := p.parseLogicalAndExpression left := next() - for self.token == token.LOGICAL_OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.LOGICAL_OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -895,24 +882,24 @@ func (self *_parser) parseLogicalOrExpression() ast.Expression { return left } -func (self *_parser) parseConditionlExpression() ast.Expression { - left := self.parseLogicalOrExpression() +func (p *parser) parseConditionalExpression() ast.Expression { + left := p.parseLogicalOrExpression() - if self.token == token.QUESTION_MARK { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.QUESTION_MARK { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() - consequent := self.parseAssignmentExpression() - if self.mode&StoreComments != 0 { - self.comments.Unset() + consequent := p.parseAssignmentExpression() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COLON) + p.expect(token.COLON) exp := &ast.ConditionalExpression{ Test: left, Consequent: consequent, - Alternate: self.parseAssignmentExpression(), + Alternate: p.parseAssignmentExpression(), } return exp @@ -921,12 +908,12 @@ func (self *_parser) parseConditionlExpression() ast.Expression { return left } -func (self *_parser) parseAssignmentExpression() ast.Expression { - left := self.parseConditionlExpression() +func (p *parser) parseAssignmentExpression() ast.Expression { + left := p.parseConditionalExpression() var operator token.Token - switch self.token { + switch p.token { case token.ASSIGN: - operator = self.token + operator = p.token case token.ADD_ASSIGN: operator = token.PLUS case token.SUBTRACT_ASSIGN: @@ -954,27 +941,27 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { } if operator != 0 { - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() switch left.(type) { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: default: - self.error(left.Idx0(), "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.error(left.Idx0(), "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } exp := &ast.AssignExpression{ Left: left, Operator: operator, - Right: self.parseAssignmentExpression(), + Right: p.parseAssignmentExpression(), } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp @@ -983,17 +970,17 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { return left } -func (self *_parser) parseExpression() ast.Expression { - next := self.parseAssignmentExpression +func (p *parser) parseExpression() ast.Expression { + next := p.parseAssignmentExpression left := next() - if self.token == token.COMMA { + if p.token == token.COMMA { sequence := []ast.Expression{left} for { - if self.token != token.COMMA { + if p.token != token.COMMA { break } - self.next() + p.next() sequence = append(sequence, next()) } return &ast.SequenceExpression{ diff --git a/vendor/github.com/robertkrimen/otto/parser/lexer.go b/vendor/github.com/robertkrimen/otto/parser/lexer.go index d9d69e124..dab21d966 100644 --- a/vendor/github.com/robertkrimen/otto/parser/lexer.go +++ b/vendor/github.com/robertkrimen/otto/parser/lexer.go @@ -15,7 +15,7 @@ import ( "github.com/robertkrimen/otto/token" ) -type _chr struct { +type chr struct { //nolint:unused value rune width int } @@ -38,6 +38,53 @@ func digitValue(chr rune) int { return 16 // Larger than any legal digit value } +// See https://www.unicode.org/reports/tr31/ for reference on ID_Start and ID_Continue. +var includeIDStart = []*unicode.RangeTable{ + unicode.Lu, + unicode.Ll, + unicode.Lt, + unicode.Lm, + unicode.Lo, + unicode.Nl, + unicode.Other_ID_Start, +} + +var includeIDContinue = []*unicode.RangeTable{ + unicode.Lu, + unicode.Ll, + unicode.Lt, + unicode.Lm, + unicode.Lo, + unicode.Nl, + unicode.Other_ID_Start, + unicode.Mn, + unicode.Mc, + unicode.Nd, + unicode.Pc, + unicode.Other_ID_Continue, +} + +var exclude = []*unicode.RangeTable{ + unicode.Pattern_Syntax, + unicode.Pattern_White_Space, +} + +func unicodeIDStart(r rune) bool { + if unicode.In(r, exclude...) { + return false + } + + return unicode.In(r, includeIDStart...) +} + +func unicodeIDContinue(r rune) bool { + if unicode.In(r, exclude...) { + return false + } + + return unicode.In(r, includeIDContinue...) +} + func isDigit(chr rune, base int) bool { return digitValue(chr) < base } @@ -45,59 +92,60 @@ func isDigit(chr rune, base int) bool { func isIdentifierStart(chr rune) bool { return chr == '$' || chr == '_' || chr == '\\' || 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' || - chr >= utf8.RuneSelf && unicode.IsLetter(chr) + chr >= utf8.RuneSelf && unicodeIDStart(chr) } func isIdentifierPart(chr rune) bool { return chr == '$' || chr == '_' || chr == '\\' || 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' || '0' <= chr && chr <= '9' || - chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr)) + chr >= utf8.RuneSelf && unicodeIDContinue(chr) } -func (self *_parser) scanIdentifier() (string, error) { - offset := self.chrOffset +func (p *parser) scanIdentifier() (string, error) { + offset := p.chrOffset parse := false - for isIdentifierPart(self.chr) { - if self.chr == '\\' { - distance := self.chrOffset - offset - self.read() - if self.chr != 'u' { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) + for isIdentifierPart(p.chr) { + if p.chr == '\\' { + distance := p.chrOffset - offset + p.read() + if p.chr != 'u' { + return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr)) } parse = true var value rune - for j := 0; j < 4; j++ { - self.read() - decimal, ok := hex2decimal(byte(self.chr)) + for range 4 { + p.read() + decimal, ok := hex2decimal(byte(p.chr)) if !ok { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) + return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr)) } value = value<<4 | decimal } - if value == '\\' { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) - } else if distance == 0 { + switch { + case value == '\\': + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) + case distance == 0: if !isIdentifierStart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) } - } else if distance > 0 { + case distance > 0: if !isIdentifierPart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) } } } - self.read() + p.read() } - literal := string(self.str[offset:self.chrOffset]) + literal := p.str[offset:p.chrOffset] if parse { return parseStringLiteral(literal) } return literal, nil } -// 7.2 -func isLineWhiteSpace(chr rune) bool { +// 7.2. +func isLineWhiteSpace(chr rune) bool { //nolint:unused, deadcode switch chr { case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff': return true @@ -109,7 +157,7 @@ func isLineWhiteSpace(chr rune) bool { return unicode.IsSpace(chr) } -// 7.3 +// 7.3. func isLineTerminator(chr rune) bool { switch chr { case '\u000a', '\u000d', '\u2028', '\u2029': @@ -118,20 +166,19 @@ func isLineTerminator(chr rune) bool { return false } -func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { - - self.implicitSemicolon = false +func (p *parser) scan() (tkn token.Token, literal string, idx file.Idx) { //nolint:nonamedreturns + p.implicitSemicolon = false for { - self.skipWhiteSpace() + p.skipWhiteSpace() - idx = self.idxOf(self.chrOffset) + idx = p.idxOf(p.chrOffset) insertSemicolon := false - switch chr := self.chr; { + switch chr := p.chr; { case isIdentifierStart(chr): var err error - literal, err = self.scanIdentifier() + literal, err = p.scanIdentifier() if err != nil { tkn = token.ILLEGAL break @@ -142,25 +189,21 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { tkn, strict = token.IsKeyword(literal) switch tkn { - case 0: // Not a keyword - if literal == "true" || literal == "false" { - self.insertSemicolon = true - tkn = token.BOOLEAN - return - } else if literal == "null" { - self.insertSemicolon = true - tkn = token.NULL - return + switch literal { + case "true", "false": + p.insertSemicolon = true + return token.BOOLEAN, literal, idx + case "null": + p.insertSemicolon = true + return token.NULL, literal, idx } - case token.KEYWORD: - tkn = token.KEYWORD if strict { // TODO If strict and in strict mode, then this is not a break break } - return + return token.KEYWORD, literal, idx case token.THIS, @@ -169,41 +212,39 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { token.RETURN, token.CONTINUE, token.DEBUGGER: - self.insertSemicolon = true - return + p.insertSemicolon = true + return tkn, literal, idx default: - return - + return tkn, literal, idx } } - self.insertSemicolon = true - tkn = token.IDENTIFIER - return + p.insertSemicolon = true + return token.IDENTIFIER, literal, idx case '0' <= chr && chr <= '9': - self.insertSemicolon = true - tkn, literal = self.scanNumericLiteral(false) - return + p.insertSemicolon = true + tkn, literal = p.scanNumericLiteral(false) + return tkn, literal, idx default: - self.read() + p.read() switch chr { case -1: - if self.insertSemicolon { - self.insertSemicolon = false - self.implicitSemicolon = true + if p.insertSemicolon { + p.insertSemicolon = false + p.implicitSemicolon = true } tkn = token.EOF case '\r', '\n', '\u2028', '\u2029': - self.insertSemicolon = false - self.implicitSemicolon = true - self.comments.AtLineBreak() + p.insertSemicolon = false + p.implicitSemicolon = true + p.comments.AtLineBreak() continue case ':': tkn = token.COLON case '.': - if digitValue(self.chr) < 10 { + if digitValue(p.chr) < 10 { insertSemicolon = true - tkn, literal = self.scanNumericLiteral(true) + tkn, literal = p.scanNumericLiteral(true) } else { tkn = token.PERIOD } @@ -227,68 +268,69 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { tkn = token.RIGHT_BRACE insertSemicolon = true case '+': - tkn = self.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT) + tkn = p.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT) if tkn == token.INCREMENT { insertSemicolon = true } case '-': - tkn = self.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT) + tkn = p.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT) if tkn == token.DECREMENT { insertSemicolon = true } case '*': - tkn = self.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) + tkn = p.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) case '/': - if self.chr == '/' { - if self.mode&StoreComments != 0 { - literal := string(self.readSingleLineComment()) - self.comments.AddComment(ast.NewComment(literal, self.idx)) + switch p.chr { + case '/': + if p.mode&StoreComments != 0 { + comment := string(p.readSingleLineComment()) + p.comments.AddComment(ast.NewComment(comment, idx)) continue } - self.skipSingleLineComment() + p.skipSingleLineComment() continue - } else if self.chr == '*' { - if self.mode&StoreComments != 0 { - literal = string(self.readMultiLineComment()) - self.comments.AddComment(ast.NewComment(literal, self.idx)) + case '*': + if p.mode&StoreComments != 0 { + comment := string(p.readMultiLineComment()) + p.comments.AddComment(ast.NewComment(comment, idx)) continue } - self.skipMultiLineComment() + p.skipMultiLineComment() continue - } else { + default: // Could be division, could be RegExp literal - tkn = self.switch2(token.SLASH, token.QUOTIENT_ASSIGN) + tkn = p.switch2(token.SLASH, token.QUOTIENT_ASSIGN) insertSemicolon = true } case '%': - tkn = self.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) + tkn = p.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) case '^': - tkn = self.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN) + tkn = p.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN) case '<': - tkn = self.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN) + tkn = p.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN) case '>': - tkn = self.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN) + tkn = p.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN) case '=': - tkn = self.switch2(token.ASSIGN, token.EQUAL) - if tkn == token.EQUAL && self.chr == '=' { - self.read() + tkn = p.switch2(token.ASSIGN, token.EQUAL) + if tkn == token.EQUAL && p.chr == '=' { + p.read() tkn = token.STRICT_EQUAL } case '!': - tkn = self.switch2(token.NOT, token.NOT_EQUAL) - if tkn == token.NOT_EQUAL && self.chr == '=' { - self.read() + tkn = p.switch2(token.NOT, token.NOT_EQUAL) + if tkn == token.NOT_EQUAL && p.chr == '=' { + p.read() tkn = token.STRICT_NOT_EQUAL } case '&': - if self.chr == '^' { - self.read() - tkn = self.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) + if p.chr == '^' { + p.read() + tkn = p.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) } else { - tkn = self.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) + tkn = p.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) } case '|': - tkn = self.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) + tkn = p.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) case '~': tkn = token.BITWISE_NOT case '?': @@ -297,49 +339,49 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { insertSemicolon = true tkn = token.STRING var err error - literal, err = self.scanString(self.chrOffset - 1) + literal, err = p.scanString(p.chrOffset - 1) if err != nil { tkn = token.ILLEGAL } default: - self.errorUnexpected(idx, chr) + p.errorUnexpected(idx, chr) tkn = token.ILLEGAL } } - self.insertSemicolon = insertSemicolon - return + p.insertSemicolon = insertSemicolon + return tkn, literal, idx } } -func (self *_parser) switch2(tkn0, tkn1 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch2(tkn0, tkn1 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } return tkn0 } -func (self *_parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() + if p.chr == chr2 { + p.read() return tkn2 } return tkn0 } -func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr2 { + p.read() + if p.chr == '=' { + p.read() return tkn3 } return tkn2 @@ -347,21 +389,21 @@ func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token return tkn0 } -func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr2 { + p.read() + if p.chr == '=' { + p.read() return tkn3 } - if self.chr == chr3 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr3 { + p.read() + if p.chr == '=' { + p.read() return tkn5 } return tkn4 @@ -371,137 +413,137 @@ func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token return tkn0 } -func (self *_parser) chrAt(index int) _chr { - value, width := utf8.DecodeRuneInString(self.str[index:]) - return _chr{ +func (p *parser) chrAt(index int) chr { //nolint:unused + value, width := utf8.DecodeRuneInString(p.str[index:]) + return chr{ value: value, width: width, } } -func (self *_parser) _peek() rune { - if self.offset+1 < self.length { - return rune(self.str[self.offset+1]) +func (p *parser) peek() rune { + if p.offset+1 < p.length { + return rune(p.str[p.offset+1]) } return -1 } -func (self *_parser) read() { - if self.offset < self.length { - self.chrOffset = self.offset - chr, width := rune(self.str[self.offset]), 1 +func (p *parser) read() { + if p.offset < p.length { + p.chrOffset = p.offset + chr, width := rune(p.str[p.offset]), 1 if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) + chr, width = utf8.DecodeRuneInString(p.str[p.offset:]) if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") + p.error(p.chrOffset, "Invalid UTF-8 character") } } - self.offset += width - self.chr = chr + p.offset += width + p.chr = chr } else { - self.chrOffset = self.length - self.chr = -1 // EOF + p.chrOffset = p.length + p.chr = -1 // EOF } } -// This is here since the functions are so similar -func (self *_RegExp_parser) read() { - if self.offset < self.length { - self.chrOffset = self.offset - chr, width := rune(self.str[self.offset]), 1 +// This is here since the functions are so similar. +func (p *regExpParser) read() { + if p.offset < p.length { + p.chrOffset = p.offset + chr, width := rune(p.str[p.offset]), 1 if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) + chr, width = utf8.DecodeRuneInString(p.str[p.offset:]) if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") + p.error(p.chrOffset, "Invalid UTF-8 character") } } - self.offset += width - self.chr = chr + p.offset += width + p.chr = chr } else { - self.chrOffset = self.length - self.chr = -1 // EOF + p.chrOffset = p.length + p.chr = -1 // EOF } } -func (self *_parser) readSingleLineComment() (result []rune) { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { - return +func (p *parser) readSingleLineComment() []rune { + var result []rune + for p.chr != -1 { + p.read() + if isLineTerminator(p.chr) { + return result } - result = append(result, self.chr) + result = append(result, p.chr) } // Get rid of the trailing -1 - result = result[:len(result)-1] - - return -} - -func (self *_parser) readMultiLineComment() (result []rune) { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() - return + return result[:len(result)-1] +} + +func (p *parser) readMultiLineComment() []rune { + var result []rune + p.read() + for p.chr >= 0 { + chr := p.chr + p.read() + if chr == '*' && p.chr == '/' { + p.read() + return result } result = append(result, chr) } - self.errorUnexpected(0, self.chr) + p.errorUnexpected(0, p.chr) - return + return result } -func (self *_parser) skipSingleLineComment() { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { +func (p *parser) skipSingleLineComment() { + for p.chr != -1 { + p.read() + if isLineTerminator(p.chr) { return } } } -func (self *_parser) skipMultiLineComment() { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() +func (p *parser) skipMultiLineComment() { + p.read() + for p.chr >= 0 { + chr := p.chr + p.read() + if chr == '*' && p.chr == '/' { + p.read() return } } - self.errorUnexpected(0, self.chr) + p.errorUnexpected(0, p.chr) } -func (self *_parser) skipWhiteSpace() { +func (p *parser) skipWhiteSpace() { for { - switch self.chr { + switch p.chr { case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff': - self.read() + p.read() continue case '\r': - if self._peek() == '\n' { - self.comments.AtLineBreak() - self.read() + if p.peek() == '\n' { + p.comments.AtLineBreak() + p.read() } fallthrough case '\u2028', '\u2029', '\n': - if self.insertSemicolon { + if p.insertSemicolon { return } - self.comments.AtLineBreak() - self.read() + p.comments.AtLineBreak() + p.read() continue } - if self.chr >= utf8.RuneSelf { - if unicode.IsSpace(self.chr) { - self.read() + if p.chr >= utf8.RuneSelf { + if unicode.IsSpace(p.chr) { + p.read() continue } } @@ -509,141 +551,135 @@ func (self *_parser) skipWhiteSpace() { } } -func (self *_parser) skipLineWhiteSpace() { - for isLineWhiteSpace(self.chr) { - self.read() - } -} - -func (self *_parser) scanMantissa(base int) { - for digitValue(self.chr) < base { - self.read() +func (p *parser) scanMantissa(base int) { + for digitValue(p.chr) < base { + p.read() } } -func (self *_parser) scanEscape(quote rune) { - +func (p *parser) scanEscape(quote rune) { var length, base uint32 - switch self.chr { - //case '0', '1', '2', '3', '4', '5', '6', '7': + switch p.chr { // Octal: // length, base, limit = 3, 8, 255 case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0': - self.read() + p.read() return case '\r', '\n', '\u2028', '\u2029': - self.scanNewline() + p.scanNewline() return case 'x': - self.read() + p.read() length, base = 2, 16 case 'u': - self.read() + p.read() length, base = 4, 16 default: - self.read() // Always make progress + p.read() // Always make progress return } var value uint32 - for ; length > 0 && self.chr != quote && self.chr >= 0; length-- { - digit := uint32(digitValue(self.chr)) + for ; length > 0 && p.chr != quote && p.chr >= 0; length-- { + digit := uint32(digitValue(p.chr)) if digit >= base { break } value = value*base + digit - self.read() + p.read() } } -func (self *_parser) scanString(offset int) (string, error) { +func (p *parser) scanString(offset int) (string, error) { // " ' / - quote := rune(self.str[offset]) + quote := rune(p.str[offset]) - for self.chr != quote { - chr := self.chr + for p.chr != quote { + chr := p.chr if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 { goto newline } - self.read() - if chr == '\\' { + p.read() + switch { + case chr == '\\': if quote == '/' { - if self.chr == '\n' || self.chr == '\r' || self.chr == '\u2028' || self.chr == '\u2029' || self.chr < 0 { + if p.chr == '\n' || p.chr == '\r' || p.chr == '\u2028' || p.chr == '\u2029' || p.chr < 0 { goto newline } - self.read() + p.read() } else { - self.scanEscape(quote) + p.scanEscape(quote) } - } else if chr == '[' && quote == '/' { + case chr == '[' && quote == '/': // Allow a slash (/) in a bracket character class ([...]) // TODO Fix this, this is hacky... quote = -1 - } else if chr == ']' && quote == -1 { + case chr == ']' && quote == -1: quote = '/' } } // " ' / - self.read() + p.read() - return string(self.str[offset:self.chrOffset]), nil + return p.str[offset:p.chrOffset], nil newline: - self.scanNewline() + p.scanNewline() err := "String not terminated" if quote == '/' { err = "Invalid regular expression: missing /" - self.error(self.idxOf(offset), err) + p.error(p.idxOf(offset), err) } return "", errors.New(err) } -func (self *_parser) scanNewline() { - if self.chr == '\r' { - self.read() - if self.chr != '\n' { +func (p *parser) scanNewline() { + if p.chr == '\r' { + p.read() + if p.chr != '\n' { return } } - self.read() + p.read() } -func hex2decimal(chr byte) (value rune, ok bool) { - { - chr := rune(chr) - switch { - case '0' <= chr && chr <= '9': - return chr - '0', true - case 'a' <= chr && chr <= 'f': - return chr - 'a' + 10, true - case 'A' <= chr && chr <= 'F': - return chr - 'A' + 10, true - } - return +func hex2decimal(chr byte) (rune, bool) { + r := rune(chr) + switch { + case '0' <= r && r <= '9': + return r - '0', true + case 'a' <= r && r <= 'f': + return r - 'a' + 10, true + case 'A' <= r && r <= 'F': + return r - 'A' + 10, true + default: + return 0, false } } -func parseNumberLiteral(literal string) (value interface{}, err error) { +func parseNumberLiteral(literal string) (value interface{}, err error) { //nolint:nonamedreturns // TODO Is Uint okay? What about -MAX_UINT value, err = strconv.ParseInt(literal, 0, 64) if err == nil { - return + return value, nil } parseIntErr := err // Save this first error, just in case value, err = strconv.ParseFloat(literal, 64) if err == nil { - return - } else if err.(*strconv.NumError).Err == strconv.ErrRange { + return value, nil + } else if errors.Is(err, strconv.ErrRange) { // Infinity, etc. return value, nil } + // TODO(steve): Fix as this is assigning to err so we know the type. + // Need to understand what this was trying to do? err = parseIntErr - if err.(*strconv.NumError).Err == strconv.ErrRange { + if errors.Is(err, strconv.ErrRange) { if len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') { // Could just be a very large number (e.g. 0x8000000000000000) var value float64 @@ -651,7 +687,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { for _, chr := range literal { digit := digitValue(chr) if digit >= 16 { - goto error + return nil, fmt.Errorf("illegal numeric literal: %v (>= 16)", digit) } value = value*16 + float64(digit) } @@ -659,8 +695,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { } } -error: - return nil, errors.New("Illegal numeric literal") + return nil, errors.New("illegal numeric literal") } func parseStringLiteral(literal string) (string, error) { @@ -729,7 +764,7 @@ func parseStringLiteral(literal string) (string, error) { if len(str) < size { return "", fmt.Errorf("invalid escape: \\%s: len(%q) != %d", string(chr), str, size) } - for j := 0; j < size; j++ { + for j := range size { decimal, ok := hex2decimal(str[j]) if !ok { return "", fmt.Errorf("invalid escape: \\%s: %q", string(chr), str[:size]) @@ -757,8 +792,8 @@ func parseStringLiteral(literal string) (string, error) { if len(str) < j+1 { break } - chr := str[j] - if '0' > chr || chr > '7' { + + if ch := str[j]; '0' > ch || ch > '7' { break } decimal := rune(str[j]) - '0' @@ -788,79 +823,79 @@ func parseStringLiteral(literal string) (string, error) { return buffer.String(), nil } -func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { - - offset := self.chrOffset +func (p *parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { + offset := p.chrOffset tkn := token.NUMBER if decimalPoint { offset-- - self.scanMantissa(10) + p.scanMantissa(10) goto exponent } - if self.chr == '0' { - offset := self.chrOffset - self.read() - if self.chr == 'x' || self.chr == 'X' { + if p.chr == '0' { + chrOffset := p.chrOffset + p.read() + switch p.chr { + case 'x', 'X': // Hexadecimal - self.read() - if isDigit(self.chr, 16) { - self.read() + p.read() + if isDigit(p.chr, 16) { + p.read() } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] + return token.ILLEGAL, p.str[chrOffset:p.chrOffset] } - self.scanMantissa(16) + p.scanMantissa(16) - if self.chrOffset-offset <= 2 { + if p.chrOffset-chrOffset <= 2 { // Only "0x" or "0X" - self.error(0, "Illegal hexadecimal number") + p.error(0, "Illegal hexadecimal number") } goto hexadecimal - } else if self.chr == '.' { + case '.': // Float goto float - } else { + default: // Octal, Float - if self.chr == 'e' || self.chr == 'E' { + if p.chr == 'e' || p.chr == 'E' { goto exponent } - self.scanMantissa(8) - if self.chr == '8' || self.chr == '9' { - return token.ILLEGAL, self.str[offset:self.chrOffset] + p.scanMantissa(8) + if p.chr == '8' || p.chr == '9' { + return token.ILLEGAL, p.str[chrOffset:p.chrOffset] } goto octal } } - self.scanMantissa(10) + p.scanMantissa(10) float: - if self.chr == '.' { - self.read() - self.scanMantissa(10) + if p.chr == '.' { + p.read() + p.scanMantissa(10) } exponent: - if self.chr == 'e' || self.chr == 'E' { - self.read() - if self.chr == '-' || self.chr == '+' { - self.read() + if p.chr == 'e' || p.chr == 'E' { + p.read() + if p.chr == '-' || p.chr == '+' { + p.read() } - if isDecimalDigit(self.chr) { - self.read() - self.scanMantissa(10) + if isDecimalDigit(p.chr) { + p.read() + p.scanMantissa(10) } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] + return token.ILLEGAL, p.str[offset:p.chrOffset] } } hexadecimal: octal: - if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) { - return token.ILLEGAL, self.str[offset:self.chrOffset] + if isIdentifierStart(p.chr) || isDecimalDigit(p.chr) { + return token.ILLEGAL, p.str[offset:p.chrOffset] } - return tkn, self.str[offset:self.chrOffset] + return tkn, p.str[offset:p.chrOffset] } diff --git a/vendor/github.com/robertkrimen/otto/parser/parser.go b/vendor/github.com/robertkrimen/otto/parser/parser.go index 75b7c500c..f0b710d3f 100644 --- a/vendor/github.com/robertkrimen/otto/parser/parser.go +++ b/vendor/github.com/robertkrimen/otto/parser/parser.go @@ -1,44 +1,43 @@ /* Package parser implements a parser for JavaScript. - import ( - "github.com/robertkrimen/otto/parser" - ) + import ( + "github.com/robertkrimen/otto/parser" + ) Parse and return an AST - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } + filename := "" // A filename is optional + src := ` + // Sample xyzzy example + (function(){ + if (3.14159 > 0) { + console.log("Hello, World."); + return; + } - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` + var xyzzy = NaN; + console.log("Nothing happens."); + return xyzzy; + })(); + ` - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) + // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList + program, err := parser.ParseFile(nil, filename, src, 0) -Warning +# Warning The parser and AST interfaces are still works-in-progress (particularly where node types are concerned) and may change in the future. - */ package parser import ( "bytes" "encoding/base64" - "errors" + "fmt" "io" - "io/ioutil" + "os" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" @@ -50,48 +49,43 @@ import ( type Mode uint const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) - StoreComments // Store the comments from source to the comments map -) - -type _parser struct { - str string - length int - base int - - chr rune // The current character - chrOffset int // The offset of current character - offset int // The offset after current character (may be greater than 1) - - idx file.Idx // The index of token - token token.Token // The token - literal string // The literal of the token, if any + // IgnoreRegExpErrors ignores RegExp compatibility errors (allow backtracking). + IgnoreRegExpErrors Mode = 1 << iota - scope *_scope - insertSemicolon bool // If we see a newline, then insert an implicit semicolon - implicitSemicolon bool // An implicit semicolon exists - - errors ErrorList + // StoreComments stores the comments from source to the comments map. + StoreComments +) - recover struct { - // Scratch when trying to seek to the next statement, etc. +type parser struct { + comments *ast.Comments + file *file.File + scope *scope + literal string + str string + errors ErrorList + recover struct { idx file.Idx count int } - - mode Mode - - file *file.File - - comments *ast.Comments + idx file.Idx + token token.Token + offset int + chrOffset int + mode Mode + base int + length int + chr rune + insertSemicolon bool + implicitSemicolon bool // Scratch when trying to seek to the next statement, etc. } +// Parser is implemented by types which can parse JavaScript Code. type Parser interface { Scan() (tkn token.Token, literal string, idx file.Idx) } -func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser { - return &_parser{ +func newParser(filename, src string, base int, sm *sourcemap.Consumer) *parser { + return &parser{ chr: ' ', // This is set so we can start scanning by skipping whitespace str: src, length: len(src), @@ -101,11 +95,12 @@ func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser } } -// Returns a new Parser. +// NewParser returns a new Parser. func NewParser(filename, src string) Parser { - return _newParser(filename, src, 1, nil) + return newParser(filename, src, 1, nil) } +// ReadSource reads code from src if not nil, otherwise reads from filename. func ReadSource(filename string, src interface{}) ([]byte, error) { if src != nil { switch src := src.(type) { @@ -123,15 +118,17 @@ func ReadSource(filename string, src interface{}) ([]byte, error) { return nil, err } return bfr.Bytes(), nil + default: + return nil, fmt.Errorf("invalid src type %T", src) } - return nil, errors.New("invalid source") } - return ioutil.ReadFile(filename) + return os.ReadFile(filename) //nolint:gosec } +// ReadSourceMap reads the source map from src if not nil, otherwise is a noop. func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) { if src == nil { - return nil, nil + return nil, nil //nolint:nilnil } switch src := src.(type) { @@ -140,9 +137,7 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error case []byte: return sourcemap.Parse(filename, src) case *bytes.Buffer: - if src != nil { - return sourcemap.Parse(filename, src.Bytes()) - } + return sourcemap.Parse(filename, src.Bytes()) case io.Reader: var bfr bytes.Buffer if _, err := io.Copy(&bfr, src); err != nil { @@ -151,11 +146,12 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error return sourcemap.Parse(filename, bfr.Bytes()) case *sourcemap.Consumer: return src, nil + default: + return nil, fmt.Errorf("invalid sourcemap type %T", src) } - - return nil, errors.New("invalid sourcemap type") } +// ParseFileWithSourceMap parses the sourcemap returning the resulting Program. func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSource, sourcemapSource interface{}, mode Mode) (*ast.Program, error) { src, err := ReadSource(filename, javascriptSource) if err != nil { @@ -168,7 +164,7 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo if bytes.HasPrefix(lastLine, []byte("//# sourceMappingURL=data:application/json")) { bits := bytes.SplitN(lastLine, []byte(","), 2) if len(bits) == 2 { - if d, err := base64.StdEncoding.DecodeString(string(bits[1])); err == nil { + if d, errDecode := base64.StdEncoding.DecodeString(string(bits[1])); errDecode == nil { sourcemapSource = d } } @@ -185,10 +181,10 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo base = fileSet.AddFile(filename, string(src)) } - parser := _newParser(filename, string(src), base, sm) - parser.mode = mode - program, err := parser.parse() - program.Comments = parser.comments.CommentMap + p := newParser(filename, string(src), base, sm) + p.mode = mode + program, err := p.parse() + program.Comments = p.comments.CommentMap return program, err } @@ -203,9 +199,8 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo // // src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8. // -// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList -// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) -// +// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList +// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) { return ParseFileWithSourceMap(fileSet, filename, src, nil, mode) } @@ -214,13 +209,11 @@ func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mod // corresponding ast.FunctionLiteral node. // // The parameter list, if any, should be a comma-separated list of identifiers. -// func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { - src := "(function(" + parameterList + ") {\n" + body + "\n})" - parser := _newParser("", src, 1, nil) - program, err := parser.parse() + p := newParser("", src, 1, nil) + program, err := p.parse() if err != nil { return nil, err } @@ -231,75 +224,75 @@ func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { // Scan reads a single token from the source at the current offset, increments the offset and // returns the token.Token token, a string literal representing the value of the token (if applicable) // and it's current file.Idx index. -func (self *_parser) Scan() (tkn token.Token, literal string, idx file.Idx) { - return self.scan() +func (p *parser) Scan() (token.Token, string, file.Idx) { + return p.scan() } -func (self *_parser) slice(idx0, idx1 file.Idx) string { - from := int(idx0) - self.base - to := int(idx1) - self.base - if from >= 0 && to <= len(self.str) { - return self.str[from:to] +func (p *parser) slice(idx0, idx1 file.Idx) string { + from := int(idx0) - p.base + to := int(idx1) - p.base + if from >= 0 && to <= len(p.str) { + return p.str[from:to] } return "" } -func (self *_parser) parse() (*ast.Program, error) { - self.next() - program := self.parseProgram() +func (p *parser) parse() (*ast.Program, error) { + p.next() + program := p.parseProgram() if false { - self.errors.Sort() + p.errors.Sort() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(program, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(program, p.comments.FetchAll(), ast.TRAILING) } - return program, self.errors.Err() + return program, p.errors.Err() } -func (self *_parser) next() { - self.token, self.literal, self.idx = self.scan() +func (p *parser) next() { + p.token, p.literal, p.idx = p.scan() } -func (self *_parser) optionalSemicolon() { - if self.token == token.SEMICOLON { - self.next() +func (p *parser) optionalSemicolon() { + if p.token == token.SEMICOLON { + p.next() return } - if self.implicitSemicolon { - self.implicitSemicolon = false + if p.implicitSemicolon { + p.implicitSemicolon = false return } - if self.token != token.EOF && self.token != token.RIGHT_BRACE { - self.expect(token.SEMICOLON) + if p.token != token.EOF && p.token != token.RIGHT_BRACE { + p.expect(token.SEMICOLON) } } -func (self *_parser) semicolon() { - if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE { - if self.implicitSemicolon { - self.implicitSemicolon = false +func (p *parser) semicolon() { + if p.token != token.RIGHT_PARENTHESIS && p.token != token.RIGHT_BRACE { + if p.implicitSemicolon { + p.implicitSemicolon = false return } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) } } -func (self *_parser) idxOf(offset int) file.Idx { - return file.Idx(self.base + offset) +func (p *parser) idxOf(offset int) file.Idx { + return file.Idx(p.base + offset) } -func (self *_parser) expect(value token.Token) file.Idx { - idx := self.idx - if self.token != value { - self.errorUnexpectedToken(self.token) +func (p *parser) expect(value token.Token) file.Idx { + idx := p.idx + if p.token != value { + p.errorUnexpectedToken(p.token) } - self.next() + p.next() return idx } @@ -309,17 +302,17 @@ func lineCount(str string) (int, int) { for index, chr := range str { switch chr { case '\r': - line += 1 + line++ last = index pair = true continue case '\n': if !pair { - line += 1 + line++ } last = index case '\u2028', '\u2029': - line += 1 + line++ last = index + 2 } pair = false @@ -327,11 +320,11 @@ func lineCount(str string) (int, int) { return line, last } -func (self *_parser) position(idx file.Idx) file.Position { +func (p *parser) position(idx file.Idx) file.Position { position := file.Position{} - offset := int(idx) - self.base - str := self.str[:offset] - position.Filename = self.file.Name() + offset := int(idx) - p.base + str := p.str[:offset] + position.Filename = p.file.Name() line, last := lineCount(str) position.Line = 1 + line if last >= 0 { diff --git a/vendor/github.com/robertkrimen/otto/parser/regexp.go b/vendor/github.com/robertkrimen/otto/parser/regexp.go index f614dae74..df4a51b37 100644 --- a/vendor/github.com/robertkrimen/otto/parser/regexp.go +++ b/vendor/github.com/robertkrimen/otto/parser/regexp.go @@ -6,18 +6,15 @@ import ( "strconv" ) -type _RegExp_parser struct { - str string - length int - - chr rune // The current character - chrOffset int // The offset of current character - offset int // The offset after current character (may be greater than 1) - - errors []error - invalid bool // The input is an invalid JavaScript RegExp - - goRegexp *bytes.Buffer +type regExpParser struct { + goRegexp *bytes.Buffer + str string + errors []error + length int + chrOffset int + offset int + chr rune + invalid bool } // TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern. @@ -34,136 +31,134 @@ type _RegExp_parser struct { // If the pattern is valid, but incompatible (contains a lookahead or backreference), // then this function returns the transformation (a non-empty string) AND an error. func TransformRegExp(pattern string) (string, error) { - if pattern == "" { return "", nil } // TODO If without \, if without (?=, (?!, then another shortcut - parser := _RegExp_parser{ + p := regExpParser{ str: pattern, length: len(pattern), goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)), } - parser.read() // Pull in the first character - parser.scan() + p.read() // Pull in the first character + p.scan() var err error - if len(parser.errors) > 0 { - err = parser.errors[0] + if len(p.errors) > 0 { + err = p.errors[0] } - if parser.invalid { + if p.invalid { return "", err } // Might not be re2 compatible, but is still a valid JavaScript RegExp - return parser.goRegexp.String(), err + return p.goRegexp.String(), err } -func (self *_RegExp_parser) scan() { - for self.chr != -1 { - switch self.chr { +func (p *regExpParser) scan() { + for p.chr != -1 { + switch p.chr { case '\\': - self.read() - self.scanEscape(false) + p.read() + p.scanEscape(false) case '(': - self.pass() - self.scanGroup() + p.pass() + p.scanGroup() case '[': - self.pass() - self.scanBracket() + p.pass() + p.scanBracket() case ')': - self.error(-1, "Unmatched ')'") - self.invalid = true - self.pass() + p.error(-1, "Unmatched ')'") + p.invalid = true + p.pass() default: - self.pass() + p.pass() } } } // (...) -func (self *_RegExp_parser) scanGroup() { - str := self.str[self.chrOffset:] +func (p *regExpParser) scanGroup() { + str := p.str[p.chrOffset:] if len(str) > 1 { // A possibility of (?= or (?! if str[0] == '?' { if str[1] == '=' || str[1] == '!' { - self.error(-1, "re2: Invalid (%s) ", self.str[self.chrOffset:self.chrOffset+2]) + p.error(-1, "re2: Invalid (%s) ", p.str[p.chrOffset:p.chrOffset+2]) } } } - for self.chr != -1 && self.chr != ')' { - switch self.chr { + for p.chr != -1 && p.chr != ')' { + switch p.chr { case '\\': - self.read() - self.scanEscape(false) + p.read() + p.scanEscape(false) case '(': - self.pass() - self.scanGroup() + p.pass() + p.scanGroup() case '[': - self.pass() - self.scanBracket() + p.pass() + p.scanBracket() default: - self.pass() + p.pass() continue } } - if self.chr != ')' { - self.error(-1, "Unterminated group") - self.invalid = true + if p.chr != ')' { + p.error(-1, "Unterminated group") + p.invalid = true return } - self.pass() + p.pass() } -// [...] -func (self *_RegExp_parser) scanBracket() { - for self.chr != -1 { - if self.chr == ']' { +// [...]. +func (p *regExpParser) scanBracket() { + for p.chr != -1 { + if p.chr == ']' { break - } else if self.chr == '\\' { - self.read() - self.scanEscape(true) + } else if p.chr == '\\' { + p.read() + p.scanEscape(true) continue } - self.pass() + p.pass() } - if self.chr != ']' { - self.error(-1, "Unterminated character class") - self.invalid = true + if p.chr != ']' { + p.error(-1, "Unterminated character class") + p.invalid = true return } - self.pass() + p.pass() } // \... -func (self *_RegExp_parser) scanEscape(inClass bool) { - offset := self.chrOffset +func (p *regExpParser) scanEscape(inClass bool) { + offset := p.chrOffset var length, base uint32 - switch self.chr { - + switch p.chr { case '0', '1', '2', '3', '4', '5', '6', '7': var value int64 size := 0 for { - digit := int64(digitValue(self.chr)) + digit := int64(digitValue(p.chr)) if digit >= 8 { // Not a valid digit break } value = value*8 + digit - self.read() - size += 1 + p.read() + size++ } if size == 1 { // The number of characters read - _, err := self.goRegexp.Write([]byte{'\\', byte(value) + '0'}) + _, err := p.goRegexp.Write([]byte{'\\', byte(value) + '0'}) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } if value != 0 { // An invalid backreference - self.error(-1, "re2: Invalid \\%d ", value) + p.error(-1, "re2: Invalid \\%d ", value) } return } @@ -174,49 +169,49 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { tmp = tmp[0:3] } tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) + _, err := p.goRegexp.Write(tmp) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } return case '8', '9': size := 0 for { - digit := digitValue(self.chr) + digit := digitValue(p.chr) if digit >= 10 { // Not a valid digit break } - self.read() - size += 1 + p.read() + size++ } - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - _, err = self.goRegexp.WriteString(self.str[offset:self.chrOffset]) + _, err = p.goRegexp.WriteString(p.str[offset:p.chrOffset]) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.error(-1, "re2: Invalid \\%s ", self.str[offset:self.chrOffset]) + p.error(-1, "re2: Invalid \\%s ", p.str[offset:p.chrOffset]) return case 'x': - self.read() + p.read() length, base = 2, 16 case 'u': - self.read() + p.read() length, base = 4, 16 case 'b': if inClass { - _, err := self.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) + _, err := p.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.read() + p.read() return } fallthrough @@ -233,24 +228,25 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { fallthrough case 'f', 'n', 'r', 't', 'v': - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.pass() + p.pass() return case 'c': - self.read() + p.read() var value int64 - if 'a' <= self.chr && self.chr <= 'z' { - value = int64(self.chr) - 'a' + 1 - } else if 'A' <= self.chr && self.chr <= 'Z' { - value = int64(self.chr) - 'A' + 1 - } else { - err := self.goRegexp.WriteByte('c') + switch { + case 'a' <= p.chr && p.chr <= 'z': + value = int64(p.chr) - 'a' + 1 + case 'A' <= p.chr && p.chr <= 'Z': + value = int64(p.chr) - 'A' + 1 + default: + err := p.goRegexp.WriteByte('c') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } return } @@ -261,98 +257,93 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { tmp = tmp[0:3] } tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) + _, err := p.goRegexp.Write(tmp) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.read() + p.read() return default: // $ is an identifier character, so we have to have // a special case for it here - if self.chr == '$' || !isIdentifierPart(self.chr) { + if p.chr == '$' || !isIdentifierPart(p.chr) { // A non-identifier character needs escaping - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - } else { + } else { //nolint:staticcheck // Unescape the character for re2 } - self.pass() + p.pass() return } // Otherwise, we're a \u.... or \x... - valueOffset := self.chrOffset + valueOffset := p.chrOffset var value uint32 - { - length := length - for ; length > 0; length-- { - digit := uint32(digitValue(self.chr)) - if digit >= base { - // Not a valid digit - goto skip - } - value = value*base + digit - self.read() + for length := length; length > 0; length-- { + digit := uint32(digitValue(p.chr)) + if digit >= base { + // Not a valid digit + goto skip } + value = value*base + digit + p.read() } - if length == 4 { - _, err := self.goRegexp.Write([]byte{ + switch length { + case 4: + if _, err := p.goRegexp.Write([]byte{ '\\', 'x', '{', - self.str[valueOffset+0], - self.str[valueOffset+1], - self.str[valueOffset+2], - self.str[valueOffset+3], + p.str[valueOffset+0], + p.str[valueOffset+1], + p.str[valueOffset+2], + p.str[valueOffset+3], '}', - }) - if err != nil { - self.errors = append(self.errors, err) + }); err != nil { + p.errors = append(p.errors, err) } - } else if length == 2 { - _, err := self.goRegexp.Write([]byte{ + case 2: + if _, err := p.goRegexp.Write([]byte{ '\\', 'x', - self.str[valueOffset+0], - self.str[valueOffset+1], - }) - if err != nil { - self.errors = append(self.errors, err) + p.str[valueOffset+0], + p.str[valueOffset+1], + }); err != nil { + p.errors = append(p.errors, err) } - } else { + default: // Should never, ever get here... - self.error(-1, "re2: Illegal branch in scanEscape") + p.error(-1, "re2: Illegal branch in scanEscape") goto skip } return skip: - _, err := self.goRegexp.WriteString(self.str[offset:self.chrOffset]) + _, err := p.goRegexp.WriteString(p.str[offset:p.chrOffset]) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } } -func (self *_RegExp_parser) pass() { - if self.chr != -1 { - _, err := self.goRegexp.WriteRune(self.chr) +func (p *regExpParser) pass() { + if p.chr != -1 { + _, err := p.goRegexp.WriteRune(p.chr) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } } - self.read() + p.read() } // TODO Better error reporting, use the offset, etc. -func (self *_RegExp_parser) error(offset int, msg string, msgValues ...interface{}) error { +func (p *regExpParser) error(offset int, msg string, msgValues ...interface{}) { //nolint:unparam err := fmt.Errorf(msg, msgValues...) - self.errors = append(self.errors, err) - return err + p.errors = append(p.errors, err) } diff --git a/vendor/github.com/robertkrimen/otto/parser/scope.go b/vendor/github.com/robertkrimen/otto/parser/scope.go index e1dbdda13..9f49e47bf 100644 --- a/vendor/github.com/robertkrimen/otto/parser/scope.go +++ b/vendor/github.com/robertkrimen/otto/parser/scope.go @@ -4,41 +4,40 @@ import ( "github.com/robertkrimen/otto/ast" ) -type _scope struct { - outer *_scope +type scope struct { + outer *scope + declarationList []ast.Declaration + labels []string allowIn bool inIteration bool inSwitch bool inFunction bool - declarationList []ast.Declaration - - labels []string } -func (self *_parser) openScope() { - self.scope = &_scope{ - outer: self.scope, +func (p *parser) openScope() { + p.scope = &scope{ + outer: p.scope, allowIn: true, } } -func (self *_parser) closeScope() { - self.scope = self.scope.outer +func (p *parser) closeScope() { + p.scope = p.scope.outer } -func (self *_scope) declare(declaration ast.Declaration) { - self.declarationList = append(self.declarationList, declaration) +func (p *scope) declare(declaration ast.Declaration) { + p.declarationList = append(p.declarationList, declaration) } -func (self *_scope) hasLabel(name string) bool { - for _, label := range self.labels { +func (p *scope) hasLabel(name string) bool { + for _, label := range p.labels { if label == name { return true } } - if self.outer != nil && !self.inFunction { + if p.outer != nil && !p.inFunction { // Crossing a function boundary to look for a label is verboten - return self.outer.hasLabel(name) + return p.outer.hasLabel(name) } return false } diff --git a/vendor/github.com/robertkrimen/otto/parser/statement.go b/vendor/github.com/robertkrimen/otto/parser/statement.go index 804cdfdc0..e6469773f 100644 --- a/vendor/github.com/robertkrimen/otto/parser/statement.go +++ b/vendor/github.com/robertkrimen/otto/parser/statement.go @@ -5,234 +5,233 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_parser) parseBlockStatement() *ast.BlockStatement { +func (p *parser) parseBlockStatement() *ast.BlockStatement { node := &ast.BlockStatement{} // Find comments before the leading brace - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.LEADING) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.LEADING) + p.comments.Unset() } - node.LeftBrace = self.expect(token.LEFT_BRACE) - node.List = self.parseStatementList() + node.LeftBrace = p.expect(token.LEFT_BRACE) + node.List = p.parseStatementList() - if self.mode&StoreComments != 0 { - self.comments.Unset() - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.FINAL) - self.comments.AfterBlock() + if p.mode&StoreComments != 0 { + p.comments.Unset() + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.FINAL) + p.comments.AfterBlock() } - node.RightBrace = self.expect(token.RIGHT_BRACE) + node.RightBrace = p.expect(token.RIGHT_BRACE) // Find comments after the trailing brace - if self.mode&StoreComments != 0 { - self.comments.ResetLineBreak() - self.comments.CommentMap.AddComments(node, self.comments.Fetch(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.ResetLineBreak() + p.comments.CommentMap.AddComments(node, p.comments.Fetch(), ast.TRAILING) } return node } -func (self *_parser) parseEmptyStatement() ast.Statement { - idx := self.expect(token.SEMICOLON) +func (p *parser) parseEmptyStatement() ast.Statement { + idx := p.expect(token.SEMICOLON) return &ast.EmptyStatement{Semicolon: idx} } -func (self *_parser) parseStatementList() (list []ast.Statement) { - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - statement := self.parseStatement() +func (p *parser) parseStatementList() (list []ast.Statement) { //nolint:nonamedreturns + for p.token != token.RIGHT_BRACE && p.token != token.EOF { + statement := p.parseStatement() list = append(list, statement) } - return + return list } -func (self *_parser) parseStatement() ast.Statement { - - if self.token == token.EOF { - self.errorUnexpectedToken(self.token) - return &ast.BadStatement{From: self.idx, To: self.idx + 1} +func (p *parser) parseStatement() ast.Statement { + if p.token == token.EOF { + p.errorUnexpectedToken(p.token) + return &ast.BadStatement{From: p.idx, To: p.idx + 1} } - if self.mode&StoreComments != 0 { - self.comments.ResetLineBreak() + if p.mode&StoreComments != 0 { + p.comments.ResetLineBreak() } - switch self.token { + switch p.token { case token.SEMICOLON: - return self.parseEmptyStatement() + return p.parseEmptyStatement() case token.LEFT_BRACE: - return self.parseBlockStatement() + return p.parseBlockStatement() case token.IF: - return self.parseIfStatement() + return p.parseIfStatement() case token.DO: - statement := self.parseDoWhileStatement() - self.comments.PostProcessNode(statement) + statement := p.parseDoWhileStatement() + p.comments.PostProcessNode(statement) return statement case token.WHILE: - return self.parseWhileStatement() + return p.parseWhileStatement() case token.FOR: - return self.parseForOrForInStatement() + return p.parseForOrForInStatement() case token.BREAK: - return self.parseBreakStatement() + return p.parseBreakStatement() case token.CONTINUE: - return self.parseContinueStatement() + return p.parseContinueStatement() case token.DEBUGGER: - return self.parseDebuggerStatement() + return p.parseDebuggerStatement() case token.WITH: - return self.parseWithStatement() + return p.parseWithStatement() case token.VAR: - return self.parseVariableStatement() + return p.parseVariableStatement() case token.FUNCTION: - return self.parseFunctionStatement() + return p.parseFunctionStatement() case token.SWITCH: - return self.parseSwitchStatement() + return p.parseSwitchStatement() case token.RETURN: - return self.parseReturnStatement() + return p.parseReturnStatement() case token.THROW: - return self.parseThrowStatement() + return p.parseThrowStatement() case token.TRY: - return self.parseTryStatement() + return p.parseTryStatement() } var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - expression := self.parseExpression() + expression := p.parseExpression() - if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && self.token == token.COLON { + if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && p.token == token.COLON { // LabelledStatement - colon := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + colon := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() // : + p.next() // : label := identifier.Name - for _, value := range self.scope.labels { + for _, value := range p.scope.labels { if label == value { - self.error(identifier.Idx0(), "Label '%s' already exists", label) + p.error(identifier.Idx0(), "Label '%s' already exists", label) } } var labelComments []*ast.Comment - if self.mode&StoreComments != 0 { - labelComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + labelComments = p.comments.FetchAll() } - self.scope.labels = append(self.scope.labels, label) // Push the label - statement := self.parseStatement() - self.scope.labels = self.scope.labels[:len(self.scope.labels)-1] // Pop the label + p.scope.labels = append(p.scope.labels, label) // Push the label + statement := p.parseStatement() + p.scope.labels = p.scope.labels[:len(p.scope.labels)-1] // Pop the label exp := &ast.LabelledStatement{ Label: identifier, Colon: colon, Statement: statement, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING) } return exp } - self.optionalSemicolon() + p.optionalSemicolon() statement := &ast.ExpressionStatement{ Expression: expression, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(statement, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(statement, comments, ast.LEADING) } return statement } -func (self *_parser) parseTryStatement() ast.Statement { +func (p *parser) parseTryStatement() ast.Statement { var tryComments []*ast.Comment - if self.mode&StoreComments != 0 { - tryComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + tryComments = p.comments.FetchAll() } node := &ast.TryStatement{ - Try: self.expect(token.TRY), - Body: self.parseBlockStatement(), + Try: p.expect(token.TRY), + Body: p.parseBlockStatement(), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, tryComments, ast.LEADING) - self.comments.CommentMap.AddComments(node.Body, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, tryComments, ast.LEADING) + p.comments.CommentMap.AddComments(node.Body, p.comments.FetchAll(), ast.TRAILING) } - if self.token == token.CATCH { - catch := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.CATCH { + catch := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() + } + p.next() + p.expect(token.LEFT_PARENTHESIS) + if p.token != token.IDENTIFIER { + p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadStatement{From: catch, To: p.idx} } - self.next() - self.expect(token.LEFT_PARENTHESIS) - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadStatement{From: catch, To: self.idx} - } else { - identifier := self.parseIdentifier() - self.expect(token.RIGHT_PARENTHESIS) - node.Catch = &ast.CatchStatement{ - Catch: catch, - Parameter: identifier, - Body: self.parseBlockStatement(), - } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node.Catch.Body, self.comments.FetchAll(), ast.TRAILING) - } + identifier := p.parseIdentifier() + p.expect(token.RIGHT_PARENTHESIS) + node.Catch = &ast.CatchStatement{ + Catch: catch, + Parameter: identifier, + Body: p.parseBlockStatement(), + } + + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node.Catch.Body, p.comments.FetchAll(), ast.TRAILING) } } - if self.token == token.FINALLY { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.FINALLY { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - if self.mode&StoreComments != 0 { - tryComments = self.comments.FetchAll() + p.next() + if p.mode&StoreComments != 0 { + tryComments = p.comments.FetchAll() } - node.Finally = self.parseBlockStatement() + node.Finally = p.parseBlockStatement() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING) } } if node.Catch == nil && node.Finally == nil { - self.error(node.Try, "Missing catch or finally after try") + p.error(node.Try, "Missing catch or finally after try") return &ast.BadStatement{From: node.Try, To: node.Body.Idx1()} } return node } -func (self *_parser) parseFunctionParameterList() *ast.ParameterList { - opening := self.expect(token.LEFT_PARENTHESIS) - if self.mode&StoreComments != 0 { - self.comments.Unset() +func (p *parser) parseFunctionParameterList() *ast.ParameterList { + opening := p.expect(token.LEFT_PARENTHESIS) + if p.mode&StoreComments != 0 { + p.comments.Unset() } var list []*ast.Identifier - for self.token != token.RIGHT_PARENTHESIS && self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) + for p.token != token.RIGHT_PARENTHESIS && p.token != token.EOF { + if p.token != token.IDENTIFIER { + p.expect(token.IDENTIFIER) } else { - identifier := self.parseIdentifier() + identifier := p.parseIdentifier() list = append(list, identifier) } - if self.token != token.RIGHT_PARENTHESIS { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token != token.RIGHT_PARENTHESIS { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COMMA) + p.expect(token.COMMA) } } - closing := self.expect(token.RIGHT_PARENTHESIS) + closing := p.expect(token.RIGHT_PARENTHESIS) return &ast.ParameterList{ Opening: opening, @@ -241,288 +240,272 @@ func (self *_parser) parseFunctionParameterList() *ast.ParameterList { } } -func (self *_parser) parseParameterList() (list []string) { - for self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - } - list = append(list, self.literal) - self.next() - if self.token != token.EOF { - self.expect(token.COMMA) - } - } - return -} - -func (self *_parser) parseFunctionStatement() *ast.FunctionStatement { +func (p *parser) parseFunctionStatement() *ast.FunctionStatement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } function := &ast.FunctionStatement{ - Function: self.parseFunction(true), + Function: p.parseFunction(true), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(function, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(function, comments, ast.LEADING) } return function } -func (self *_parser) parseFunction(declaration bool) *ast.FunctionLiteral { - +func (p *parser) parseFunction(declaration bool) *ast.FunctionLiteral { node := &ast.FunctionLiteral{ - Function: self.expect(token.FUNCTION), + Function: p.expect(token.FUNCTION), } var name *ast.Identifier - if self.token == token.IDENTIFIER { - name = self.parseIdentifier() + if p.token == token.IDENTIFIER { + name = p.parseIdentifier() if declaration { - self.scope.declare(&ast.FunctionDeclaration{ + p.scope.declare(&ast.FunctionDeclaration{ Function: node, }) } } else if declaration { // Use expect error handling - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } node.Name = name - node.ParameterList = self.parseFunctionParameterList() - self.parseFunctionBlock(node) - node.Source = self.slice(node.Idx0(), node.Idx1()) + node.ParameterList = p.parseFunctionParameterList() + p.parseFunctionBlock(node) + node.Source = p.slice(node.Idx0(), node.Idx1()) return node } -func (self *_parser) parseFunctionBlock(node *ast.FunctionLiteral) { - { - self.openScope() - inFunction := self.scope.inFunction - self.scope.inFunction = true - defer func() { - self.scope.inFunction = inFunction - self.closeScope() - }() - node.Body = self.parseBlockStatement() - node.DeclarationList = self.scope.declarationList - } +func (p *parser) parseFunctionBlock(node *ast.FunctionLiteral) { + p.openScope() + inFunction := p.scope.inFunction + p.scope.inFunction = true + defer func() { + p.scope.inFunction = inFunction + p.closeScope() + }() + node.Body = p.parseBlockStatement() + node.DeclarationList = p.scope.declarationList } -func (self *_parser) parseDebuggerStatement() ast.Statement { - idx := self.expect(token.DEBUGGER) +func (p *parser) parseDebuggerStatement() ast.Statement { + idx := p.expect(token.DEBUGGER) node := &ast.DebuggerStatement{ Debugger: idx, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.TRAILING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseReturnStatement() ast.Statement { - idx := self.expect(token.RETURN) +func (p *parser) parseReturnStatement() ast.Statement { + idx := p.expect(token.RETURN) var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - if !self.scope.inFunction { - self.error(idx, "Illegal return statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + if !p.scope.inFunction { + p.error(idx, "Illegal return statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } node := &ast.ReturnStatement{ Return: idx, } - if !self.implicitSemicolon && self.token != token.SEMICOLON && self.token != token.RIGHT_BRACE && self.token != token.EOF { - node.Argument = self.parseExpression() + if !p.implicitSemicolon && p.token != token.SEMICOLON && p.token != token.RIGHT_BRACE && p.token != token.EOF { + node.Argument = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseThrowStatement() ast.Statement { +func (p *parser) parseThrowStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.THROW) + idx := p.expect(token.THROW) - if self.implicitSemicolon { - if self.chr == -1 { // Hackish - self.error(idx, "Unexpected end of input") + if p.implicitSemicolon { + if p.chr == -1 { // Hackish + p.error(idx, "Unexpected end of input") } else { - self.error(idx, "Illegal newline after throw") + p.error(idx, "Illegal newline after throw") } - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } node := &ast.ThrowStatement{ - Throw: self.idx, - Argument: self.parseExpression(), + Throw: idx, + Argument: p.parseExpression(), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseSwitchStatement() ast.Statement { +func (p *parser) parseSwitchStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.SWITCH) - if self.mode&StoreComments != 0 { - comments = append(comments, self.comments.FetchAll()...) + idx := p.expect(token.SWITCH) + if p.mode&StoreComments != 0 { + comments = append(comments, p.comments.FetchAll()...) } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.SwitchStatement{ - Discriminant: self.parseExpression(), + Switch: idx, + Discriminant: p.parseExpression(), Default: -1, } - self.expect(token.RIGHT_PARENTHESIS) - if self.mode&StoreComments != 0 { - comments = append(comments, self.comments.FetchAll()...) + p.expect(token.RIGHT_PARENTHESIS) + if p.mode&StoreComments != 0 { + comments = append(comments, p.comments.FetchAll()...) } - self.expect(token.LEFT_BRACE) + p.expect(token.LEFT_BRACE) - inSwitch := self.scope.inSwitch - self.scope.inSwitch = true + inSwitch := p.scope.inSwitch + p.scope.inSwitch = true defer func() { - self.scope.inSwitch = inSwitch + p.scope.inSwitch = inSwitch }() - for index := 0; self.token != token.EOF; index++ { - if self.token == token.RIGHT_BRACE { - self.next() + for index := 0; p.token != token.EOF; index++ { + if p.token == token.RIGHT_BRACE { + node.RightBrace = p.idx + p.next() break } - clause := self.parseCaseStatement() + clause := p.parseCaseStatement() if clause.Test == nil { if node.Default != -1 { - self.error(clause.Case, "Already saw a default in switch") + p.error(clause.Case, "Already saw a default in switch") } node.Default = index } node.Body = append(node.Body, clause) } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } return node } -func (self *_parser) parseWithStatement() ast.Statement { +func (p *parser) parseWithStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.WITH) + idx := p.expect(token.WITH) var withComments []*ast.Comment - if self.mode&StoreComments != 0 { - withComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + withComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.WithStatement{ - Object: self.parseExpression(), + With: idx, + Object: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.RIGHT_PARENTHESIS) - if self.mode&StoreComments != 0 { - //comments = append(comments, self.comments.FetchAll()...) - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, withComments, ast.WITH) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, withComments, ast.WITH) } - node.Body = self.parseStatement() + node.Body = p.parseStatement() return node } -func (self *_parser) parseCaseStatement() *ast.CaseStatement { +func (p *parser) parseCaseStatement() *ast.CaseStatement { node := &ast.CaseStatement{ - Case: self.idx, + Case: p.idx, } var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() - self.comments.Unset() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() + p.comments.Unset() } - if self.token == token.DEFAULT { - self.next() + if p.token == token.DEFAULT { + p.next() } else { - self.expect(token.CASE) - node.Test = self.parseExpression() + p.expect(token.CASE) + node.Test = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COLON) + p.expect(token.COLON) for { - if self.token == token.EOF || - self.token == token.RIGHT_BRACE || - self.token == token.CASE || - self.token == token.DEFAULT { + if p.token == token.EOF || + p.token == token.RIGHT_BRACE || + p.token == token.CASE || + p.token == token.DEFAULT { break } - consequent := self.parseStatement() + consequent := p.parseStatement() node.Consequent = append(node.Consequent, consequent) } // Link the comments to the case statement - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } return node } -func (self *_parser) parseIterationStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true +func (p *parser) parseIterationStatement() ast.Statement { + inIteration := p.scope.inIteration + p.scope.inIteration = true defer func() { - self.scope.inIteration = inIteration + p.scope.inIteration = inIteration }() - return self.parseStatement() + return p.parseStatement() } -func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { - +func (p *parser) parseForIn(into ast.Expression) *ast.ForInStatement { // Already have consumed " in" - source := self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) - body := self.parseIterationStatement() + source := p.parseExpression() + p.expect(token.RIGHT_PARENTHESIS) + body := p.parseIterationStatement() forin := &ast.ForInStatement{ Into: into, @@ -533,25 +516,24 @@ func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { return forin } -func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { - +func (p *parser) parseFor(initializer ast.Expression) *ast.ForStatement { // Already have consumed " ;" var test, update ast.Expression - if self.token != token.SEMICOLON { - test = self.parseExpression() + if p.token != token.SEMICOLON { + test = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) - if self.token != token.RIGHT_PARENTHESIS { - update = self.parseExpression() + if p.token != token.RIGHT_PARENTHESIS { + update = p.parseExpression() } - self.expect(token.RIGHT_PARENTHESIS) - body := self.parseIterationStatement() + p.expect(token.RIGHT_PARENTHESIS) + body := p.parseIterationStatement() forstatement := &ast.ForStatement{ Initializer: initializer, @@ -563,55 +545,54 @@ func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { return forstatement } -func (self *_parser) parseForOrForInStatement() ast.Statement { +func (p *parser) parseForOrForInStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.FOR) + idx := p.expect(token.FOR) var forComments []*ast.Comment - if self.mode&StoreComments != 0 { - forComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + forComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) var left []ast.Expression forIn := false - if self.token != token.SEMICOLON { - - allowIn := self.scope.allowIn - self.scope.allowIn = false - if self.token == token.VAR { - var_ := self.idx + if p.token != token.SEMICOLON { + allowIn := p.scope.allowIn + p.scope.allowIn = false + if p.token == token.VAR { + tokenIdx := p.idx var varComments []*ast.Comment - if self.mode&StoreComments != 0 { - varComments = self.comments.FetchAll() - self.comments.Unset() + if p.mode&StoreComments != 0 { + varComments = p.comments.FetchAll() + p.comments.Unset() } - self.next() - list := self.parseVariableDeclarationList(var_) - if len(list) == 1 && self.token == token.IN { - if self.mode&StoreComments != 0 { - self.comments.Unset() + p.next() + list := p.parseVariableDeclarationList(tokenIdx) + if len(list) == 1 && p.token == token.IN { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() // in + p.next() // in forIn = true left = []ast.Expression{list[0]} // There is only one declaration } else { left = list } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING) } } else { - left = append(left, self.parseExpression()) - if self.token == token.IN { - self.next() + left = append(left, p.parseExpression()) + if p.token == token.IN { + p.next() forIn = true } } - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn } if forIn { @@ -619,207 +600,212 @@ func (self *_parser) parseForOrForInStatement() ast.Statement { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression, *ast.VariableExpression: // These are all acceptable default: - self.error(idx, "Invalid left-hand side in for-in") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Invalid left-hand side in for-in") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } - forin := self.parseForIn(left[0]) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(forin, comments, ast.LEADING) - self.comments.CommentMap.AddComments(forin, forComments, ast.FOR) + forin := p.parseForIn(left[0]) + forin.For = idx + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(forin, comments, ast.LEADING) + p.comments.CommentMap.AddComments(forin, forComments, ast.FOR) } return forin } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) initializer := &ast.SequenceExpression{Sequence: left} - forstatement := self.parseFor(initializer) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING) - self.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR) + forstatement := p.parseFor(initializer) + forstatement.For = idx + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING) + p.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR) } return forstatement } -func (self *_parser) parseVariableStatement() *ast.VariableStatement { +func (p *parser) parseVariableStatement() *ast.VariableStatement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.VAR) + idx := p.expect(token.VAR) - list := self.parseVariableDeclarationList(idx) + list := p.parseVariableDeclarationList(idx) statement := &ast.VariableStatement{ Var: idx, List: list, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(statement, comments, ast.LEADING) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(statement, comments, ast.LEADING) + p.comments.Unset() } - self.semicolon() + p.semicolon() return statement } -func (self *_parser) parseDoWhileStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true +func (p *parser) parseDoWhileStatement() ast.Statement { + inIteration := p.scope.inIteration + p.scope.inIteration = true defer func() { - self.scope.inIteration = inIteration + p.scope.inIteration = inIteration }() var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.DO) + idx := p.expect(token.DO) var doComments []*ast.Comment - if self.mode&StoreComments != 0 { - doComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + doComments = p.comments.FetchAll() } - node := &ast.DoWhileStatement{} - if self.token == token.LEFT_BRACE { - node.Body = self.parseBlockStatement() + node := &ast.DoWhileStatement{Do: idx} + if p.token == token.LEFT_BRACE { + node.Body = p.parseBlockStatement() } else { - node.Body = self.parseStatement() + node.Body = p.parseStatement() } - self.expect(token.WHILE) + p.expect(token.WHILE) var whileComments []*ast.Comment - if self.mode&StoreComments != 0 { - whileComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + whileComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) - node.Test = self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) + node.Test = p.parseExpression() + node.RightParenthesis = p.expect(token.RIGHT_PARENTHESIS) + + p.implicitSemicolon = true + p.optionalSemicolon() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, doComments, ast.DO) - self.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, doComments, ast.DO) + p.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) } return node } -func (self *_parser) parseWhileStatement() ast.Statement { +func (p *parser) parseWhileStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.WHILE) + idx := p.expect(token.WHILE) var whileComments []*ast.Comment - if self.mode&StoreComments != 0 { - whileComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + whileComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.WhileStatement{ - Test: self.parseExpression(), + While: idx, + Test: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) - node.Body = self.parseIterationStatement() + p.expect(token.RIGHT_PARENTHESIS) + node.Body = p.parseIterationStatement() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) } return node } -func (self *_parser) parseIfStatement() ast.Statement { +func (p *parser) parseIfStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.IF) + pos := p.expect(token.IF) var ifComments []*ast.Comment - if self.mode&StoreComments != 0 { - ifComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + ifComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.IfStatement{ - If: self.idx, - Test: self.parseExpression(), + If: pos, + Test: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) - if self.token == token.LEFT_BRACE { - node.Consequent = self.parseBlockStatement() + p.expect(token.RIGHT_PARENTHESIS) + if p.token == token.LEFT_BRACE { + node.Consequent = p.parseBlockStatement() } else { - node.Consequent = self.parseStatement() + node.Consequent = p.parseStatement() } - if self.token == token.ELSE { - self.next() - node.Alternate = self.parseStatement() + if p.token == token.ELSE { + p.next() + node.Alternate = p.parseStatement() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, ifComments, ast.IF) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, ifComments, ast.IF) } return node } -func (self *_parser) parseSourceElement() ast.Statement { - statement := self.parseStatement() - //self.comments.Unset() +func (p *parser) parseSourceElement() ast.Statement { + statement := p.parseStatement() return statement } -func (self *_parser) parseSourceElements() []ast.Statement { +func (p *parser) parseSourceElements() []ast.Statement { body := []ast.Statement(nil) for { - if self.token != token.STRING { + if p.token != token.STRING { break } - body = append(body, self.parseSourceElement()) + body = append(body, p.parseSourceElement()) } - for self.token != token.EOF { - body = append(body, self.parseSourceElement()) + for p.token != token.EOF { + body = append(body, p.parseSourceElement()) } return body } -func (self *_parser) parseProgram() *ast.Program { - self.openScope() - defer self.closeScope() +func (p *parser) parseProgram() *ast.Program { + p.openScope() + defer p.closeScope() return &ast.Program{ - Body: self.parseSourceElements(), - DeclarationList: self.scope.declarationList, - File: self.file, + Body: p.parseSourceElements(), + DeclarationList: p.scope.declarationList, + File: p.file, } } -func (self *_parser) parseBreakStatement() ast.Statement { +func (p *parser) parseBreakStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.BREAK) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { + idx := p.expect(token.BREAK) + semicolon := p.implicitSemicolon + if p.token == token.SEMICOLON { semicolon = true - self.next() + p.next() } - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration && !self.scope.inSwitch { + if semicolon || p.token == token.RIGHT_BRACE { + p.implicitSemicolon = false + if !p.scope.inIteration && !p.scope.inSwitch { goto illegal } breakStatement := &ast.BranchStatement{ @@ -827,52 +813,52 @@ func (self *_parser) parseBreakStatement() ast.Statement { Token: token.BREAK, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) - self.comments.CommentMap.AddComments(breakStatement, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) + p.comments.CommentMap.AddComments(breakStatement, p.comments.FetchAll(), ast.TRAILING) } return breakStatement } - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) + if p.token == token.IDENTIFIER { + identifier := p.parseIdentifier() + if !p.scope.hasLabel(identifier.Name) { + p.error(idx, "Undefined label '%s'", identifier.Name) return &ast.BadStatement{From: idx, To: identifier.Idx1()} } - self.semicolon() + p.semicolon() breakStatement := &ast.BranchStatement{ Idx: idx, Token: token.BREAK, Label: identifier, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) } return breakStatement } - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) illegal: - self.error(idx, "Illegal break statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Illegal break statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } -func (self *_parser) parseContinueStatement() ast.Statement { - idx := self.expect(token.CONTINUE) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { +func (p *parser) parseContinueStatement() ast.Statement { + idx := p.expect(token.CONTINUE) + semicolon := p.implicitSemicolon + if p.token == token.SEMICOLON { semicolon = true - self.next() + p.next() } - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration { + if semicolon || p.token == token.RIGHT_BRACE { + p.implicitSemicolon = false + if !p.scope.inIteration { goto illegal } return &ast.BranchStatement{ @@ -881,16 +867,16 @@ func (self *_parser) parseContinueStatement() ast.Statement { } } - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) + if p.token == token.IDENTIFIER { + identifier := p.parseIdentifier() + if !p.scope.hasLabel(identifier.Name) { + p.error(idx, "Undefined label '%s'", identifier.Name) return &ast.BadStatement{From: idx, To: identifier.Idx1()} } - if !self.scope.inIteration { + if !p.scope.inIteration { goto illegal } - self.semicolon() + p.semicolon() return &ast.BranchStatement{ Idx: idx, Token: token.CONTINUE, @@ -898,18 +884,18 @@ func (self *_parser) parseContinueStatement() ast.Statement { } } - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) illegal: - self.error(idx, "Illegal continue statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Illegal continue statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } -// Find the next statement after an error (recover) -func (self *_parser) nextStatement() { +// Find the next statement after an error (recover). +func (p *parser) nextStatement() { for { - switch self.token { + switch p.token { case token.BREAK, token.CONTINUE, token.FOR, token.IF, token.RETURN, token.SWITCH, token.VAR, token.DO, token.TRY, token.WITH, @@ -918,13 +904,13 @@ func (self *_parser) nextStatement() { // sync or if it has not reached 10 next calls without // progress. Otherwise consume at least one token to // avoid an endless parser loop - if self.idx == self.recover.idx && self.recover.count < 10 { - self.recover.count++ + if p.idx == p.recover.idx && p.recover.count < 10 { + p.recover.count++ return } - if self.idx > self.recover.idx { - self.recover.idx = self.idx - self.recover.count = 0 + if p.idx > p.recover.idx { + p.recover.idx = p.idx + p.recover.count = 0 return } // Reaching here indicates a parser bug, likely an @@ -935,6 +921,6 @@ func (self *_parser) nextStatement() { case token.EOF: return } - self.next() + p.next() } } diff --git a/vendor/github.com/robertkrimen/otto/property.go b/vendor/github.com/robertkrimen/otto/property.go index 5445eccde..768d6e567 100644 --- a/vendor/github.com/robertkrimen/otto/property.go +++ b/vendor/github.com/robertkrimen/otto/property.go @@ -2,88 +2,87 @@ package otto // property -type _propertyMode int +type propertyMode int const ( - modeWriteMask _propertyMode = 0700 - modeEnumerateMask = 0070 - modeConfigureMask = 0007 - modeOnMask = 0111 - modeOffMask = 0000 - modeSetMask = 0222 // If value is 2, then mode is neither "On" nor "Off" + modeWriteMask propertyMode = 0o700 + modeEnumerateMask propertyMode = 0o070 + modeConfigureMask propertyMode = 0o007 + modeOnMask propertyMode = 0o111 + modeSetMask propertyMode = 0o222 // If value is 2, then mode is neither "On" nor "Off" ) -type _propertyGetSet [2]*_object +type propertyGetSet [2]*object -var _nilGetSetObject _object = _object{} +var nilGetSetObject = object{} -type _property struct { +type property struct { value interface{} - mode _propertyMode + mode propertyMode } -func (self _property) writable() bool { - return self.mode&modeWriteMask == modeWriteMask&modeOnMask +func (p property) writable() bool { + return p.mode&modeWriteMask == modeWriteMask&modeOnMask } -func (self *_property) writeOn() { - self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask) +func (p *property) writeOn() { + p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask) } -func (self *_property) writeOff() { - self.mode &= ^modeWriteMask +func (p *property) writeOff() { + p.mode &= ^modeWriteMask } -func (self *_property) writeClear() { - self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask) +func (p *property) writeClear() { + p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask) } -func (self _property) writeSet() bool { - return 0 == self.mode&modeWriteMask&modeSetMask +func (p property) writeSet() bool { + return p.mode&modeWriteMask&modeSetMask == 0 } -func (self _property) enumerable() bool { - return self.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask +func (p property) enumerable() bool { + return p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask } -func (self *_property) enumerateOn() { - self.mode = (self.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask) +func (p *property) enumerateOn() { + p.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask) } -func (self *_property) enumerateOff() { - self.mode &= ^modeEnumerateMask +func (p *property) enumerateOff() { + p.mode &= ^modeEnumerateMask } -func (self _property) enumerateSet() bool { - return 0 == self.mode&modeEnumerateMask&modeSetMask +func (p property) enumerateSet() bool { + return p.mode&modeEnumerateMask&modeSetMask == 0 } -func (self _property) configurable() bool { - return self.mode&modeConfigureMask == modeConfigureMask&modeOnMask +func (p property) configurable() bool { + return p.mode&modeConfigureMask == modeConfigureMask&modeOnMask } -func (self *_property) configureOn() { - self.mode = (self.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask) +func (p *property) configureOn() { + p.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask) } -func (self *_property) configureOff() { - self.mode &= ^modeConfigureMask +func (p *property) configureOff() { + p.mode &= ^modeConfigureMask } -func (self _property) configureSet() bool { - return 0 == self.mode&modeConfigureMask&modeSetMask +func (p property) configureSet() bool { //nolint:unused + return p.mode&modeConfigureMask&modeSetMask == 0 } -func (self _property) copy() *_property { - property := self - return &property +func (p property) copy() *property { //nolint:unused + cpy := p + return &cpy } -func (self _property) get(this *_object) Value { - switch value := self.value.(type) { +func (p property) get(this *object) Value { + switch value := p.value.(type) { case Value: return value - case _propertyGetSet: + case propertyGetSet: if value[0] != nil { return value[0].call(toValue(this), nil, false, nativeFrame) } @@ -91,130 +90,129 @@ func (self _property) get(this *_object) Value { return Value{} } -func (self _property) isAccessorDescriptor() bool { - setGet, test := self.value.(_propertyGetSet) +func (p property) isAccessorDescriptor() bool { + setGet, test := p.value.(propertyGetSet) return test && (setGet[0] != nil || setGet[1] != nil) } -func (self _property) isDataDescriptor() bool { - if self.writeSet() { // Either "On" or "Off" +func (p property) isDataDescriptor() bool { + if p.writeSet() { // Either "On" or "Off" return true } - value, valid := self.value.(Value) + value, valid := p.value.(Value) return valid && !value.isEmpty() } -func (self _property) isGenericDescriptor() bool { - return !(self.isDataDescriptor() || self.isAccessorDescriptor()) +func (p property) isGenericDescriptor() bool { + return !(p.isDataDescriptor() || p.isAccessorDescriptor()) } -func (self _property) isEmpty() bool { - return self.mode == 0222 && self.isGenericDescriptor() +func (p property) isEmpty() bool { + return p.mode == 0o222 && p.isGenericDescriptor() } // _enumerableValue, _enumerableTrue, _enumerableFalse? // .enumerableValue() .enumerableExists() -func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { - objectDescriptor := value._object() +func toPropertyDescriptor(rt *runtime, value Value) property { + objectDescriptor := value.object() if objectDescriptor == nil { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("toPropertyDescriptor on nil")) } - { - descriptor.mode = modeSetMask // Initially nothing is set - if objectDescriptor.hasProperty("enumerable") { - if objectDescriptor.get("enumerable").bool() { - descriptor.enumerateOn() - } else { - descriptor.enumerateOff() - } + var descriptor property + descriptor.mode = modeSetMask // Initially nothing is set + if objectDescriptor.hasProperty("enumerable") { + if objectDescriptor.get("enumerable").bool() { + descriptor.enumerateOn() + } else { + descriptor.enumerateOff() } + } - if objectDescriptor.hasProperty("configurable") { - if objectDescriptor.get("configurable").bool() { - descriptor.configureOn() - } else { - descriptor.configureOff() - } + if objectDescriptor.hasProperty("configurable") { + if objectDescriptor.get("configurable").bool() { + descriptor.configureOn() + } else { + descriptor.configureOff() } + } - if objectDescriptor.hasProperty("writable") { - if objectDescriptor.get("writable").bool() { - descriptor.writeOn() - } else { - descriptor.writeOff() - } + if objectDescriptor.hasProperty("writable") { + if objectDescriptor.get("writable").bool() { + descriptor.writeOn() + } else { + descriptor.writeOff() } } - var getter, setter *_object + var getter, setter *object getterSetter := false if objectDescriptor.hasProperty("get") { - value := objectDescriptor.get("get") - if value.IsDefined() { - if !value.isCallable() { - panic(rt.panicTypeError()) + val := objectDescriptor.get("get") + if val.IsDefined() { + if !val.isCallable() { + panic(rt.panicTypeError("toPropertyDescriptor get not callable")) } - getter = value._object() + getter = val.object() getterSetter = true } else { - getter = &_nilGetSetObject + getter = &nilGetSetObject getterSetter = true } } if objectDescriptor.hasProperty("set") { - value := objectDescriptor.get("set") - if value.IsDefined() { - if !value.isCallable() { - panic(rt.panicTypeError()) + val := objectDescriptor.get("set") + if val.IsDefined() { + if !val.isCallable() { + panic(rt.panicTypeError("toPropertyDescriptor set not callable")) } - setter = value._object() + setter = val.object() getterSetter = true } else { - setter = &_nilGetSetObject + setter = &nilGetSetObject getterSetter = true } } if getterSetter { if descriptor.writeSet() { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("toPropertyDescriptor descriptor writeSet")) } - descriptor.value = _propertyGetSet{getter, setter} + descriptor.value = propertyGetSet{getter, setter} } if objectDescriptor.hasProperty("value") { if getterSetter { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("toPropertyDescriptor value getterSetter")) } descriptor.value = objectDescriptor.get("value") } - return + return descriptor } -func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object { - object := self.newObject() +func (rt *runtime) fromPropertyDescriptor(descriptor property) *object { + obj := rt.newObject() if descriptor.isDataDescriptor() { - object.defineProperty("value", descriptor.value.(Value), 0111, false) - object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false) + obj.defineProperty("value", descriptor.value.(Value), 0o111, false) + obj.defineProperty("writable", boolValue(descriptor.writable()), 0o111, false) } else if descriptor.isAccessorDescriptor() { - getSet := descriptor.value.(_propertyGetSet) + getSet := descriptor.value.(propertyGetSet) get := Value{} if getSet[0] != nil { - get = toValue_object(getSet[0]) + get = objectValue(getSet[0]) } set := Value{} if getSet[1] != nil { - set = toValue_object(getSet[1]) + set = objectValue(getSet[1]) } - object.defineProperty("get", get, 0111, false) - object.defineProperty("set", set, 0111, false) + obj.defineProperty("get", get, 0o111, false) + obj.defineProperty("set", set, 0o111, false) } - object.defineProperty("enumerable", toValue_bool(descriptor.enumerable()), 0111, false) - object.defineProperty("configurable", toValue_bool(descriptor.configurable()), 0111, false) - return object + obj.defineProperty("enumerable", boolValue(descriptor.enumerable()), 0o111, false) + obj.defineProperty("configurable", boolValue(descriptor.configurable()), 0o111, false) + return obj } diff --git a/vendor/github.com/robertkrimen/otto/registry/README.markdown b/vendor/github.com/robertkrimen/otto/registry/README.markdown deleted file mode 100644 index ba2d38909..000000000 --- a/vendor/github.com/robertkrimen/otto/registry/README.markdown +++ /dev/null @@ -1,51 +0,0 @@ -# registry --- - import "github.com/robertkrimen/otto/registry" - -Package registry is an expirmental package to facillitate altering the otto -runtime via import. - -This interface can change at any time. - -## Usage - -#### func Apply - -```go -func Apply(callback func(Entry)) -``` - -#### type Entry - -```go -type Entry struct { -} -``` - - -#### func Register - -```go -func Register(source func() string) *Entry -``` - -#### func (*Entry) Disable - -```go -func (self *Entry) Disable() -``` - -#### func (*Entry) Enable - -```go -func (self *Entry) Enable() -``` - -#### func (Entry) Source - -```go -func (self Entry) Source() string -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/registry/registry.go b/vendor/github.com/robertkrimen/otto/registry/registry.go index 966638ac4..f20b5ff32 100644 --- a/vendor/github.com/robertkrimen/otto/registry/registry.go +++ b/vendor/github.com/robertkrimen/otto/registry/registry.go @@ -1,17 +1,17 @@ -/* -Package registry is an expirmental package to facillitate altering the otto runtime via import. - -This interface can change at any time. -*/ +// Package registry is an experimental package to facilitate altering the otto runtime via import. +// +// This interface can change at any time. package registry var registry []*Entry = make([]*Entry, 0) +// Entry represents a registry entry. type Entry struct { - active bool source func() string + active bool } +// newEntry returns a new Entry for source. func newEntry(source func() string) *Entry { return &Entry{ active: true, @@ -19,18 +19,22 @@ func newEntry(source func() string) *Entry { } } -func (self *Entry) Enable() { - self.active = true +// Enable enables the entry. +func (e *Entry) Enable() { + e.active = true } -func (self *Entry) Disable() { - self.active = false +// Disable disables the entry. +func (e *Entry) Disable() { + e.active = false } -func (self Entry) Source() string { - return self.source() +// Source returns the source of the entry. +func (e Entry) Source() string { + return e.source() } +// Apply applies callback to all registry entries. func Apply(callback func(Entry)) { for _, entry := range registry { if !entry.active { @@ -40,6 +44,7 @@ func Apply(callback func(Entry)) { } } +// Register registers a new Entry for source. func Register(source func() string) *Entry { entry := newEntry(source) registry = append(registry, entry) diff --git a/vendor/github.com/robertkrimen/otto/result.go b/vendor/github.com/robertkrimen/otto/result.go index 63642e7d0..abda3353c 100644 --- a/vendor/github.com/robertkrimen/otto/result.go +++ b/vendor/github.com/robertkrimen/otto/result.go @@ -1,30 +1,28 @@ package otto -import () - -type _resultKind int +type resultKind int const ( - resultNormal _resultKind = iota + _ resultKind = iota resultReturn resultBreak resultContinue ) -type _result struct { - kind _resultKind +type result struct { value Value target string + kind resultKind } -func newReturnResult(value Value) _result { - return _result{resultReturn, value, ""} +func newReturnResult(value Value) result { + return result{kind: resultReturn, value: value, target: ""} } -func newContinueResult(target string) _result { - return _result{resultContinue, emptyValue, target} +func newContinueResult(target string) result { + return result{kind: resultContinue, value: emptyValue, target: target} } -func newBreakResult(target string) _result { - return _result{resultBreak, emptyValue, target} +func newBreakResult(target string) result { + return result{kind: resultBreak, value: emptyValue, target: target} } diff --git a/vendor/github.com/robertkrimen/otto/runtime.go b/vendor/github.com/robertkrimen/otto/runtime.go index 9941278f6..702623673 100644 --- a/vendor/github.com/robertkrimen/otto/runtime.go +++ b/vendor/github.com/robertkrimen/otto/runtime.go @@ -2,12 +2,13 @@ package otto import ( "encoding" + "encoding/json" "errors" "fmt" "math" "path" "reflect" - "runtime" + goruntime "runtime" "strconv" "strings" "sync" @@ -16,179 +17,177 @@ import ( "github.com/robertkrimen/otto/parser" ) -type _global struct { - Object *_object // Object( ... ), new Object( ... ) - 1 (length) - Function *_object // Function( ... ), new Function( ... ) - 1 - Array *_object // Array( ... ), new Array( ... ) - 1 - String *_object // String( ... ), new String( ... ) - 1 - Boolean *_object // Boolean( ... ), new Boolean( ... ) - 1 - Number *_object // Number( ... ), new Number( ... ) - 1 - Math *_object - Date *_object // Date( ... ), new Date( ... ) - 7 - RegExp *_object // RegExp( ... ), new RegExp( ... ) - 2 - Error *_object // Error( ... ), new Error( ... ) - 1 - EvalError *_object - TypeError *_object - RangeError *_object - ReferenceError *_object - SyntaxError *_object - URIError *_object - JSON *_object - - ObjectPrototype *_object // Object.prototype - FunctionPrototype *_object // Function.prototype - ArrayPrototype *_object // Array.prototype - StringPrototype *_object // String.prototype - BooleanPrototype *_object // Boolean.prototype - NumberPrototype *_object // Number.prototype - DatePrototype *_object // Date.prototype - RegExpPrototype *_object // RegExp.prototype - ErrorPrototype *_object // Error.prototype - EvalErrorPrototype *_object - TypeErrorPrototype *_object - RangeErrorPrototype *_object - ReferenceErrorPrototype *_object - SyntaxErrorPrototype *_object - URIErrorPrototype *_object +type global struct { + Object *object // Object( ... ), new Object( ... ) - 1 (length) + Function *object // Function( ... ), new Function( ... ) - 1 + Array *object // Array( ... ), new Array( ... ) - 1 + String *object // String( ... ), new String( ... ) - 1 + Boolean *object // Boolean( ... ), new Boolean( ... ) - 1 + Number *object // Number( ... ), new Number( ... ) - 1 + Math *object + Date *object // Date( ... ), new Date( ... ) - 7 + RegExp *object // RegExp( ... ), new RegExp( ... ) - 2 + Error *object // Error( ... ), new Error( ... ) - 1 + EvalError *object + TypeError *object + RangeError *object + ReferenceError *object + SyntaxError *object + URIError *object + JSON *object + + ObjectPrototype *object // Object.prototype + FunctionPrototype *object // Function.prototype + ArrayPrototype *object // Array.prototype + StringPrototype *object // String.prototype + BooleanPrototype *object // Boolean.prototype + NumberPrototype *object // Number.prototype + DatePrototype *object // Date.prototype + RegExpPrototype *object // RegExp.prototype + ErrorPrototype *object // Error.prototype + EvalErrorPrototype *object + TypeErrorPrototype *object + RangeErrorPrototype *object + ReferenceErrorPrototype *object + SyntaxErrorPrototype *object + URIErrorPrototype *object } -type _runtime struct { - global _global - globalObject *_object - globalStash *_objectStash - scope *_scope +type runtime struct { + global global + globalObject *object + globalStash *objectStash + scope *scope otto *Otto - eval *_object // The builtin eval, for determine indirect versus direct invocation + eval *object debugger func(*Otto) random func() float64 + labels []string stackLimit int traceLimit int - - labels []string // FIXME - lck sync.Mutex + lck sync.Mutex } -func (self *_runtime) enterScope(scope *_scope) { - scope.outer = self.scope - if self.scope != nil { - if self.stackLimit != 0 && self.scope.depth+1 >= self.stackLimit { - panic(self.panicRangeError("Maximum call stack size exceeded")) +func (rt *runtime) enterScope(scop *scope) { + scop.outer = rt.scope + if rt.scope != nil { + if rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit { + panic(rt.panicRangeError("Maximum call stack size exceeded")) } - scope.depth = self.scope.depth + 1 + scop.depth = rt.scope.depth + 1 } - self.scope = scope + rt.scope = scop } -func (self *_runtime) leaveScope() { - self.scope = self.scope.outer +func (rt *runtime) leaveScope() { + rt.scope = rt.scope.outer } -// FIXME This is used in two places (cloning) -func (self *_runtime) enterGlobalScope() { - self.enterScope(newScope(self.globalStash, self.globalStash, self.globalObject)) +// FIXME This is used in two places (cloning). +func (rt *runtime) enterGlobalScope() { + rt.enterScope(newScope(rt.globalStash, rt.globalStash, rt.globalObject)) } -func (self *_runtime) enterFunctionScope(outer _stash, this Value) *_fnStash { +func (rt *runtime) enterFunctionScope(outer stasher, this Value) *fnStash { if outer == nil { - outer = self.globalStash + outer = rt.globalStash } - stash := self.newFunctionStash(outer) - var thisObject *_object + stash := rt.newFunctionStash(outer) + var thisObject *object switch this.kind { case valueUndefined, valueNull: - thisObject = self.globalObject + thisObject = rt.globalObject default: - thisObject = self.toObject(this) + thisObject = rt.toObject(this) } - self.enterScope(newScope(stash, stash, thisObject)) + rt.enterScope(newScope(stash, stash, thisObject)) return stash } -func (self *_runtime) putValue(reference _reference, value Value) { +func (rt *runtime) putValue(reference referencer, value Value) { name := reference.putValue(value) if name != "" { // Why? -- If reference.base == nil // strict = false - self.globalObject.defineProperty(name, value, 0111, false) + rt.globalObject.defineProperty(name, value, 0o111, false) } } -func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exception bool) { +func (rt *runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, isException bool) { //nolint:nonamedreturns // resultValue = The value of the block (e.g. the last statement) // throw = Something was thrown // throwValue = The value of what was thrown // other = Something that changes flow (return, break, continue) that is not a throw - // Otherwise, some sort of unknown panic happened, we'll just propagate it + // Otherwise, some sort of unknown panic happened, we'll just propagate it. defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() + if excep, ok := caught.(*exception); ok { + caught = excep.eject() } switch caught := caught.(type) { - case _error: - exception = true - tryValue = toValue_object(self.newError(caught.name, caught.messageValue(), 0)) + case ottoError: + isException = true + tryValue = objectValue(rt.newErrorObjectError(caught)) case Value: - exception = true + isException = true tryValue = caught default: - panic(caught) + isException = true + tryValue = toValue(caught) } } }() - tryValue = inner() - return + return inner(), false } -// toObject - -func (self *_runtime) toObject(value Value) *_object { +func (rt *runtime) toObject(value Value) *object { switch value.kind { case valueEmpty, valueUndefined, valueNull: - panic(self.panicTypeError()) + panic(rt.panicTypeError("toObject unsupported kind %s", value.kind)) case valueBoolean: - return self.newBoolean(value) + return rt.newBoolean(value) case valueString: - return self.newString(value) + return rt.newString(value) case valueNumber: - return self.newNumber(value) + return rt.newNumber(value) case valueObject: - return value._object() + return value.object() + default: + panic(rt.panicTypeError("toObject unknown kind %s", value.kind)) } - panic(self.panicTypeError()) } -func (self *_runtime) objectCoerce(value Value) (*_object, error) { +func (rt *runtime) objectCoerce(value Value) (*object, error) { switch value.kind { case valueUndefined: return nil, errors.New("undefined") case valueNull: return nil, errors.New("null") case valueBoolean: - return self.newBoolean(value), nil + return rt.newBoolean(value), nil case valueString: - return self.newString(value), nil + return rt.newString(value), nil case valueNumber: - return self.newNumber(value), nil + return rt.newNumber(value), nil case valueObject: - return value._object(), nil + return value.object(), nil + default: + panic(rt.panicTypeError("objectCoerce unknown kind %s", value.kind)) } - panic(self.panicTypeError()) } -func checkObjectCoercible(rt *_runtime, value Value) { +func checkObjectCoercible(rt *runtime, value Value) { isObject, mustCoerce := testObjectCoercible(value) if !isObject && !mustCoerce { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("checkObjectCoercible not object or mustCoerce")) } } -// testObjectCoercible - -func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { +// testObjectCoercible. +func testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint:nonamedreturns switch value.kind { case valueReference, valueEmpty, valueNull, valueUndefined: return false, false @@ -197,21 +196,21 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { case valueObject: return true, false default: - panic("this should never happen") + panic(fmt.Sprintf("testObjectCoercible unknown kind %s", value.kind)) } } -func (self *_runtime) safeToValue(value interface{}) (Value, error) { +func (rt *runtime) safeToValue(value interface{}) (Value, error) { result := Value{} err := catchPanic(func() { - result = self.toValue(value) + result = rt.toValue(value) }) return result, err } // convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics. // This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily. -func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { +func (rt *runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { val := reflect.ValueOf(v.export()) if val.Kind() == t.Kind() { @@ -230,20 +229,20 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { return reflect.ValueOf(f64) case reflect.Float32: if reflect.Zero(t).OverflowFloat(f64) { - panic(self.panicRangeError("converting float64 to float32 would overflow")) + panic(rt.panicRangeError("converting float64 to float32 would overflow")) } return val.Convert(t) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: i64 := int64(f64) if float64(i64) != f64 { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t))) } // The float represents an integer val = reflect.ValueOf(i64) default: - panic(self.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t))) + panic(rt.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t))) } } @@ -253,17 +252,19 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if reflect.Zero(t).OverflowInt(i64) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if i64 < 0 { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t))) } if reflect.Zero(t).OverflowUint(uint64(i64)) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) + case reflect.Float32, reflect.Float64: + return val.Convert(t) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: @@ -271,111 +272,165 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if reflect.Zero(t).OverflowUint(u64) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) + case reflect.Float32, reflect.Float64: + return val.Convert(t) } } - panic(self.panicTypeError(fmt.Sprintf("unsupported type %v for numeric conversion", val.Type()))) + panic(rt.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t))) } -var typeOfValue = reflect.TypeOf(Value{}) +func fieldIndexByName(t reflect.Type, name string) []int { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + + for i := range t.NumField() { + f := t.Field(i) + + if !validGoStructName(f.Name) { + continue + } + + if f.Anonymous { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + + if f.Type.Kind() == reflect.Struct { + if a := fieldIndexByName(f.Type, name); a != nil { + return append([]int{i}, a...) + } + } + } + + if a := strings.SplitN(f.Tag.Get("json"), ",", 2); a[0] != "" { + if a[0] == "-" { + continue + } + + if a[0] == name { + return []int{i} + } + } + + if f.Name == name { + return []int{i} + } + } + + return nil +} + +var ( + typeOfValue = reflect.TypeOf(Value{}) + typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{}) +) // convertCallParameter converts request val to type t if possible. // If the conversion fails due to overflow or type miss-match then it panics. // If no conversion is known then the original value is returned. -func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Value { +func (rt *runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) { if t == typeOfValue { - return reflect.ValueOf(v) + return reflect.ValueOf(v), nil + } + + if t == typeOfJSONRawMessage { + if d, err := json.Marshal(v.export()); err == nil { + return reflect.ValueOf(d), nil + } } if v.kind == valueObject { - if gso, ok := v._object().value.(*_goStructObject); ok { + if gso, ok := v.object().value.(*goStructObject); ok { if gso.value.Type().AssignableTo(t) { // please see TestDynamicFunctionReturningInterface for why this exists if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) { - return gso.value.Convert(t) - } else { - return gso.value + return gso.value.Convert(t), nil } + return gso.value, nil } } - if gao, ok := v._object().value.(*_goArrayObject); ok { + if gao, ok := v.object().value.(*goArrayObject); ok { if gao.value.Type().AssignableTo(t) { // please see TestDynamicFunctionReturningInterface for why this exists if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) { - return gao.value.Convert(t) - } else { - return gao.value + return gao.value.Convert(t), nil } + return gao.value, nil } } } - if t.Kind() == reflect.Interface { + tk := t.Kind() + + if tk == reflect.Interface { e := v.export() if e == nil { - return reflect.Zero(t) + return reflect.Zero(t), nil } iv := reflect.ValueOf(e) if iv.Type().AssignableTo(t) { - return iv + return iv, nil } } - tk := t.Kind() - if tk == reflect.Ptr { switch v.kind { case valueEmpty, valueNull, valueUndefined: - return reflect.Zero(t) + return reflect.Zero(t), nil default: var vv reflect.Value - if err := catchPanic(func() { vv = self.convertCallParameter(v, t.Elem()) }); err == nil { - if vv.CanAddr() { - return vv.Addr() - } + vv, err := rt.convertCallParameter(v, t.Elem()) + if err != nil { + return reflect.Zero(t), fmt.Errorf("can't convert to %s: %w", t, err) + } - pv := reflect.New(vv.Type()) - pv.Elem().Set(vv) - return pv + if vv.CanAddr() { + return vv.Addr(), nil } + + pv := reflect.New(vv.Type()) + pv.Elem().Set(vv) + return pv, nil } } switch tk { case reflect.Bool: - return reflect.ValueOf(v.bool()) + return reflect.ValueOf(v.bool()), nil case reflect.String: switch v.kind { case valueString: - return reflect.ValueOf(v.value) + return reflect.ValueOf(v.value), nil case valueNumber: - return reflect.ValueOf(fmt.Sprintf("%v", v.value)) + return reflect.ValueOf(fmt.Sprintf("%v", v.value)), nil } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: - switch v.kind { - case valueNumber: - return self.convertNumeric(v, t) + if v.kind == valueNumber { + return rt.convertNumeric(v, t), nil } case reflect.Slice: - if o := v._object(); o != nil { - if lv := o.get("length"); lv.IsNumber() { + if o := v.object(); o != nil { + if lv := o.get(propertyLength); lv.IsNumber() { l := lv.number().int64 s := reflect.MakeSlice(t, int(l), int(l)) tt := t.Elem() - if o.class == "Array" { - for i := int64(0); i < l; i++ { + switch o.class { + case classArrayName: + for i := range l { p, ok := o.property[strconv.FormatInt(i, 10)] if !ok { continue @@ -386,22 +441,24 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu continue } - ev := self.convertCallParameter(e, tt) + ev, err := rt.convertCallParameter(e, tt) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err) + } s.Index(int(i)).Set(ev) } - } else if o.class == "GoArray" { - + case classGoArrayName, classGoSliceName: var gslice bool switch o.value.(type) { - case *_goSliceObject: + case *goSliceObject: gslice = true - case *_goArrayObject: + case *goArrayObject: gslice = false } - for i := int64(0); i < l; i++ { - var p *_property + for i := range l { + var p *property if gslice { p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10)) } else { @@ -416,32 +473,46 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu continue } - ev := self.convertCallParameter(e, tt) + ev, err := rt.convertCallParameter(e, tt) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err) + } s.Index(int(i)).Set(ev) } } - return s + return s, nil } } case reflect.Map: - if o := v._object(); o != nil && t.Key().Kind() == reflect.String { + if o := v.object(); o != nil && t.Key().Kind() == reflect.String { m := reflect.MakeMap(t) + var err error + o.enumerate(false, func(k string) bool { - m.SetMapIndex(reflect.ValueOf(k), self.convertCallParameter(o.get(k), t.Elem())) + v, verr := rt.convertCallParameter(o.get(k), t.Elem()) + if verr != nil { + err = fmt.Errorf("couldn't convert property %q of %s: %w", k, t, verr) + return false + } + m.SetMapIndex(reflect.ValueOf(k), v) return true }) - return m + if err != nil { + return reflect.Zero(t), err + } + + return m, nil } case reflect.Func: if t.NumOut() > 1 { - panic(self.panicTypeError("converting JavaScript values to Go functions with more than one return value is currently not supported")) + return reflect.Zero(t), errors.New("converting JavaScript values to Go functions with more than one return value is currently not supported") } - if o := v._object(); o != nil && o.class == "Function" { + if o := v.object(); o != nil && o.class == classFunctionName { return reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value { l := make([]interface{}, len(args)) for i, a := range args { @@ -459,53 +530,32 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu return nil } - return []reflect.Value{self.convertCallParameter(rv, t.Out(0))} - }) + r, err := rt.convertCallParameter(rv, t.Out(0)) + if err != nil { + panic(rt.panicTypeError("convertCallParameter Func: %s", err)) + } + + return []reflect.Value{r} + }), nil } case reflect.Struct: - if o := v._object(); o != nil && o.class == "Object" { + if o := v.object(); o != nil && o.class == classObjectName { s := reflect.New(t) for _, k := range o.propertyOrder { - var f *reflect.StructField - - for i := 0; i < t.NumField(); i++ { - ff := t.Field(i) - - if j := ff.Tag.Get("json"); j != "" { - if j == "-" { - continue - } - - a := strings.Split(j, ",") - - if a[0] == k { - f = &ff - break - } - } - - if ff.Name == k { - f = &ff - break - } - - if strings.EqualFold(ff.Name, k) { - f = &ff - } - } + idx := fieldIndexByName(t, k) - if f == nil { - panic(self.panicTypeError("can't convert object; field %q was supplied but does not exist on target %v", k, t)) + if idx == nil { + return reflect.Zero(t), fmt.Errorf("can't convert property %q of %s: field does not exist", k, t) } ss := s - for _, i := range f.Index { + for _, i := range idx { if ss.Kind() == reflect.Ptr { if ss.IsNil() { if !ss.CanSet() { - panic(self.panicTypeError("can't set embedded pointer to unexported struct: %v", ss.Type().Elem())) + return reflect.Zero(t), fmt.Errorf("can't convert property %q of %s: %s is unexported", k, t, ss.Type().Elem()) } ss.Set(reflect.New(ss.Type().Elem())) @@ -517,42 +567,48 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu ss = ss.Field(i) } - ss.Set(self.convertCallParameter(o.get(k), ss.Type())) + v, err := rt.convertCallParameter(o.get(k), ss.Type()) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %w", k, t, err) + } + + ss.Set(v) } - return s.Elem() + return s.Elem(), nil } } if tk == reflect.String { - if o := v._object(); o != nil && o.hasProperty("toString") { + if o := v.object(); o != nil && o.hasProperty("toString") { if fn := o.get("toString"); fn.IsFunction() { sv, err := fn.Call(v) if err != nil { - panic(err) + return reflect.Zero(t), fmt.Errorf("couldn't call toString: %w", err) } - var r reflect.Value - if err := catchPanic(func() { r = self.convertCallParameter(sv, t) }); err == nil { - return r + r, err := rt.convertCallParameter(sv, t) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %w", err) } + return r, nil } } - return reflect.ValueOf(v.String()) + return reflect.ValueOf(v.String()), nil } if v.kind == valueString { var s encoding.TextUnmarshaler - if reflect.PtrTo(t).Implements(reflect.TypeOf(&s).Elem()) { + if reflect.PointerTo(t).Implements(reflect.TypeOf(&s).Elem()) { r := reflect.New(t) if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil { - panic(self.panicSyntaxError("can't convert to %s: %s", t.String(), err.Error())) + return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %w", t.String(), err) } - return r.Elem() + return r.Elem(), nil } } @@ -572,10 +628,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu s = v.Class() } - panic(self.panicTypeError("can't convert from %q to %q", s, t.String())) + return reflect.Zero(t), fmt.Errorf("can't convert from %q to %q", s, t) } -func (self *_runtime) toValue(value interface{}) Value { +func (rt *runtime) toValue(value interface{}) Value { + rv, ok := value.(reflect.Value) + if ok { + value = rv.Interface() + } + switch value := value.(type) { case Value: return value @@ -583,165 +644,171 @@ func (self *_runtime) toValue(value interface{}) Value { var name, file string var line int pc := reflect.ValueOf(value).Pointer() - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) if fn != nil { name = fn.Name() file, line = fn.FileLine(pc) file = path.Base(file) } - return toValue_object(self.newNativeFunction(name, file, line, value)) - case _nativeFunction: + return objectValue(rt.newNativeFunction(name, file, line, value)) + case nativeFunction: var name, file string var line int pc := reflect.ValueOf(value).Pointer() - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) if fn != nil { name = fn.Name() file, line = fn.FileLine(pc) file = path.Base(file) } - return toValue_object(self.newNativeFunction(name, file, line, value)) - case Object, *Object, _object, *_object: + return objectValue(rt.newNativeFunction(name, file, line, value)) + case Object, *Object, object, *object: // Nothing happens. // FIXME We should really figure out what can come here. // This catch-all is ugly. default: - { - value := reflect.ValueOf(value) - - switch value.Kind() { - case reflect.Ptr: - switch reflect.Indirect(value).Kind() { - case reflect.Struct: - return toValue_object(self.newGoStructObject(value)) - case reflect.Array: - return toValue_object(self.newGoArray(value)) - } + val := reflect.ValueOf(value) + if ok && val.Kind() == rv.Kind() { + // Use passed in rv which may be writable. + val = rv + } + + switch val.Kind() { + case reflect.Ptr: + switch reflect.Indirect(val).Kind() { case reflect.Struct: - return toValue_object(self.newGoStructObject(value)) - case reflect.Map: - return toValue_object(self.newGoMapObject(value)) - case reflect.Slice: - return toValue_object(self.newGoSlice(value)) + return objectValue(rt.newGoStructObject(val)) case reflect.Array: - return toValue_object(self.newGoArray(value)) - case reflect.Func: - var name, file string - var line int - if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr { - pc := v.Pointer() - fn := runtime.FuncForPC(pc) - if fn != nil { - name = fn.Name() - file, line = fn.FileLine(pc) - file = path.Base(file) - } + return objectValue(rt.newGoArray(val)) + } + case reflect.Struct: + return objectValue(rt.newGoStructObject(val)) + case reflect.Map: + return objectValue(rt.newGoMapObject(val)) + case reflect.Slice: + return objectValue(rt.newGoSlice(val)) + case reflect.Array: + return objectValue(rt.newGoArray(val)) + case reflect.Func: + var name, file string + var line int + if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr { + pc := v.Pointer() + fn := goruntime.FuncForPC(pc) + if fn != nil { + name = fn.Name() + file, line = fn.FileLine(pc) + file = path.Base(file) } + } - typ := value.Type() + typ := val.Type() - return toValue_object(self.newNativeFunction(name, file, line, func(c FunctionCall) Value { - nargs := typ.NumIn() + return objectValue(rt.newNativeFunction(name, file, line, func(c FunctionCall) Value { + nargs := typ.NumIn() - if len(c.ArgumentList) != nargs { - if typ.IsVariadic() { - if len(c.ArgumentList) < nargs-1 { - panic(self.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList)))) - } - } else { - panic(self.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList)))) + if len(c.ArgumentList) != nargs { + if typ.IsVariadic() { + if len(c.ArgumentList) < nargs-1 { + panic(rt.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList)))) } + } else { + panic(rt.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList)))) } + } - in := make([]reflect.Value, len(c.ArgumentList)) + in := make([]reflect.Value, len(c.ArgumentList)) - callSlice := false + callSlice := false - for i, a := range c.ArgumentList { - var t reflect.Type + for i, a := range c.ArgumentList { + var t reflect.Type - n := i - if n >= nargs-1 && typ.IsVariadic() { - if n > nargs-1 { - n = nargs - 1 - } - - t = typ.In(n).Elem() - } else { - t = typ.In(n) + n := i + if n >= nargs-1 && typ.IsVariadic() { + if n > nargs-1 { + n = nargs - 1 } - // if this is a variadic Go function, and the caller has supplied - // exactly the number of JavaScript arguments required, and this - // is the last JavaScript argument, try treating the it as the - // actual set of variadic Go arguments. if that succeeds, break - // out of the loop. - if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 { - var v reflect.Value - if err := catchPanic(func() { v = self.convertCallParameter(a, typ.In(n)) }); err == nil { - in[i] = v - callSlice = true - break - } - } + t = typ.In(n).Elem() + } else { + t = typ.In(n) + } - in[i] = self.convertCallParameter(a, t) + // if this is a variadic Go function, and the caller has supplied + // exactly the number of JavaScript arguments required, and this + // is the last JavaScript argument, try treating the it as the + // actual set of variadic Go arguments. if that succeeds, break + // out of the loop. + if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 { + if v, err := rt.convertCallParameter(a, typ.In(n)); err == nil { + in[i] = v + callSlice = true + break + } } - var out []reflect.Value - if callSlice { - out = value.CallSlice(in) - } else { - out = value.Call(in) + v, err := rt.convertCallParameter(a, t) + if err != nil { + panic(rt.panicTypeError(err.Error())) } - switch len(out) { - case 0: - return Value{} - case 1: - return self.toValue(out[0].Interface()) - default: - s := make([]interface{}, len(out)) - for i, v := range out { - s[i] = self.toValue(v.Interface()) - } + in[i] = v + } - return self.toValue(s) + var out []reflect.Value + if callSlice { + out = val.CallSlice(in) + } else { + out = val.Call(in) + } + + switch len(out) { + case 0: + return Value{} + case 1: + return rt.toValue(out[0].Interface()) + default: + s := make([]interface{}, len(out)) + for i, v := range out { + s[i] = rt.toValue(v.Interface()) } - })) - } + + return rt.toValue(s) + } + })) } } return toValue(value) } -func (runtime *_runtime) newGoSlice(value reflect.Value) *_object { - self := runtime.newGoSliceObject(value) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newGoSlice(value reflect.Value) *object { + obj := rt.newGoSliceObject(value) + obj.prototype = rt.global.ArrayPrototype + return obj } -func (runtime *_runtime) newGoArray(value reflect.Value) *_object { - self := runtime.newGoArrayObject(value) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newGoArray(value reflect.Value) *object { + obj := rt.newGoArrayObject(value) + obj.prototype = rt.global.ArrayPrototype + return obj } -func (runtime *_runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) { +func (rt *runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) { return parser.ParseFileWithSourceMap(nil, filename, src, sm, 0) } -func (runtime *_runtime) cmpl_parse(filename string, src, sm interface{}) (*_nodeProgram, error) { +func (rt *runtime) cmplParse(filename string, src, sm interface{}) (*nodeProgram, error) { program, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0) if err != nil { return nil, err } - return cmpl_parse(program), nil + return cmplParse(program), nil } -func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Program, error) { +func (rt *runtime) parseSource(src, sm interface{}) (*nodeProgram, *ast.Program, error) { switch src := src.(type) { case *ast.Program: return nil, src, nil @@ -749,22 +816,22 @@ func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Prog return src.program, nil, nil } - program, err := self.parse("", src, sm) + program, err := rt.parse("", src, sm) return nil, program, err } -func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, error) { +func (rt *runtime) cmplRunOrEval(src, sm interface{}, eval bool) (Value, error) { result := Value{} - cmpl_program, program, err := self.parseSource(src, sm) + node, program, err := rt.parseSource(src, sm) if err != nil { return result, err } - if cmpl_program == nil { - cmpl_program = cmpl_parse(program) + if node == nil { + node = cmplParse(program) } err = catchPanic(func() { - result = self.cmpl_evaluate_nodeProgram(cmpl_program, eval) + result = rt.cmplEvaluateNodeProgram(node, eval) }) switch result.kind { case valueEmpty: @@ -775,33 +842,32 @@ func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, err return result, err } -func (self *_runtime) cmpl_run(src, sm interface{}) (Value, error) { - return self.cmpl_runOrEval(src, sm, false) +func (rt *runtime) cmplRun(src, sm interface{}) (Value, error) { + return rt.cmplRunOrEval(src, sm, false) } -func (self *_runtime) cmpl_eval(src, sm interface{}) (Value, error) { - return self.cmpl_runOrEval(src, sm, true) +func (rt *runtime) cmplEval(src, sm interface{}) (Value, error) { + return rt.cmplRunOrEval(src, sm, true) } -func (self *_runtime) parseThrow(err error) { +func (rt *runtime) parseThrow(err error) { if err == nil { return } - switch err := err.(type) { - case parser.ErrorList: - { - err := err[0] - if err.Message == "Invalid left-hand side in assignment" { - panic(self.panicReferenceError(err.Message)) - } - panic(self.panicSyntaxError(err.Message)) + + var errl parser.ErrorList + if errors.Is(err, &errl) { + err := errl[0] + if err.Message == "invalid left-hand side in assignment" { + panic(rt.panicReferenceError(err.Message)) } + panic(rt.panicSyntaxError(err.Message)) } - panic(self.panicSyntaxError(err.Error())) + panic(rt.panicSyntaxError(err.Error())) } -func (self *_runtime) cmpl_parseOrThrow(src, sm interface{}) *_nodeProgram { - program, err := self.cmpl_parse("", src, sm) - self.parseThrow(err) // Will panic/throw appropriately +func (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram { + program, err := rt.cmplParse("", src, sm) + rt.parseThrow(err) // Will panic/throw appropriately return program } diff --git a/vendor/github.com/robertkrimen/otto/scope.go b/vendor/github.com/robertkrimen/otto/scope.go index 465e6b98c..c535c3166 100644 --- a/vendor/github.com/robertkrimen/otto/scope.go +++ b/vendor/github.com/robertkrimen/otto/scope.go @@ -1,33 +1,18 @@ package otto -// _scope: -// entryFile -// entryIdx -// top? -// outer => nil - -// _stash: -// lexical -// variable -// -// _thisStash (ObjectEnvironment) -// _fnStash -// _dclStash - -// An ECMA-262 ExecutionContext -type _scope struct { - lexical _stash - variable _stash - this *_object - eval bool // Replace this with kind? - outer *_scope +// An ECMA-262 ExecutionContext. +type scope struct { + lexical stasher + variable stasher + this *object + outer *scope + frame frame depth int - - frame _frame + eval bool } -func newScope(lexical _stash, variable _stash, this *_object) *_scope { - return &_scope{ +func newScope(lexical stasher, variable stasher, this *object) *scope { + return &scope{ lexical: lexical, variable: variable, this: this, diff --git a/vendor/github.com/robertkrimen/otto/script.go b/vendor/github.com/robertkrimen/otto/script.go index 2ae890ecd..077a916df 100644 --- a/vendor/github.com/robertkrimen/otto/script.go +++ b/vendor/github.com/robertkrimen/otto/script.go @@ -6,16 +6,16 @@ import ( "errors" ) +// ErrVersion is an error which represents a version mismatch. var ErrVersion = errors.New("version mismatch") var scriptVersion = "2014-04-13/1" // Script is a handle for some (reusable) JavaScript. // Passing a Script value to a run method will evaluate the JavaScript. -// type Script struct { version string - program *_nodeProgram + program *nodeProgram filename string src string } @@ -23,26 +23,24 @@ type Script struct { // Compile will parse the given source and return a Script value or nil and // an error if there was a problem during compilation. // -// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) -// vm.Run(script) -// -func (self *Otto) Compile(filename string, src interface{}) (*Script, error) { - return self.CompileWithSourceMap(filename, src, nil) +// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) +// vm.Run(script) +func (o *Otto) Compile(filename string, src interface{}) (*Script, error) { + return o.CompileWithSourceMap(filename, src, nil) } // CompileWithSourceMap does the same thing as Compile, but with the obvious // difference of applying a source map. -func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) { - program, err := self.runtime.parse(filename, src, sm) +func (o *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) { + program, err := o.runtime.parse(filename, src, sm) if err != nil { return nil, err } - cmpl_program := cmpl_parse(program) - + node := cmplParse(program) script := &Script{ version: scriptVersion, - program: cmpl_program, + program: node, filename: filename, src: program.File.Source(), } @@ -50,31 +48,30 @@ func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*S return script, nil } -func (self *Script) String() string { - return "// " + self.filename + "\n" + self.src +func (s *Script) String() string { + return "// " + s.filename + "\n" + s.src } // MarshalBinary will marshal a script into a binary form. A marshalled script // that is later unmarshalled can be executed on the same version of the otto runtime. // // The binary format can change at any time and should be considered unspecified and opaque. -// -func (self *Script) marshalBinary() ([]byte, error) { +func (s *Script) marshalBinary() ([]byte, error) { var bfr bytes.Buffer encoder := gob.NewEncoder(&bfr) - err := encoder.Encode(self.version) + err := encoder.Encode(s.version) if err != nil { return nil, err } - err = encoder.Encode(self.program) + err = encoder.Encode(s.program) if err != nil { return nil, err } - err = encoder.Encode(self.filename) + err = encoder.Encode(s.filename) if err != nil { return nil, err } - err = encoder.Encode(self.src) + err = encoder.Encode(s.src) if err != nil { return nil, err } @@ -86,34 +83,27 @@ func (self *Script) marshalBinary() ([]byte, error) { // will return an error. // // The binary format can change at any time and should be considered unspecified and opaque. -// -func (self *Script) unmarshalBinary(data []byte) error { +func (s *Script) unmarshalBinary(data []byte) (err error) { //nolint:nonamedreturns decoder := gob.NewDecoder(bytes.NewReader(data)) - err := decoder.Decode(&self.version) - if err != nil { - goto error + defer func() { + if err != nil { + s.version = "" + s.program = nil + s.filename = "" + s.src = "" + } + }() + if err = decoder.Decode(&s.version); err != nil { + return err } - if self.version != scriptVersion { - err = ErrVersion - goto error + if s.version != scriptVersion { + return ErrVersion } - err = decoder.Decode(&self.program) - if err != nil { - goto error + if err = decoder.Decode(&s.program); err != nil { + return err } - err = decoder.Decode(&self.filename) - if err != nil { - goto error - } - err = decoder.Decode(&self.src) - if err != nil { - goto error + if err = decoder.Decode(&s.filename); err != nil { + return err } - return nil -error: - self.version = "" - self.program = nil - self.filename = "" - self.src = "" - return err + return decoder.Decode(&s.src) } diff --git a/vendor/github.com/robertkrimen/otto/stash.go b/vendor/github.com/robertkrimen/otto/stash.go index 0d3ffa511..85ee26d81 100644 --- a/vendor/github.com/robertkrimen/otto/stash.go +++ b/vendor/github.com/robertkrimen/otto/stash.go @@ -4,172 +4,160 @@ import ( "fmt" ) -// ====== -// _stash -// ====== +// stasher is implemented by types which can stash data. +type stasher interface { + hasBinding(name string) bool // + createBinding(name string, deletable bool, value Value) // CreateMutableBinding + setBinding(name string, value Value, strict bool) // SetMutableBinding + getBinding(name string, throw bool) Value // GetBindingValue + deleteBinding(name string) bool // + setValue(name string, value Value, throw bool) // createBinding + setBinding -type _stash interface { - hasBinding(string) bool // - createBinding(string, bool, Value) // CreateMutableBinding - setBinding(string, Value, bool) // SetMutableBinding - getBinding(string, bool) Value // GetBindingValue - deleteBinding(string) bool // - setValue(string, Value, bool) // createBinding + setBinding + outer() stasher + runtime() *runtime - outer() _stash - runtime() *_runtime + newReference(name string, strict bool, atv at) referencer - newReference(string, bool, _at) _reference - - clone(clone *_clone) _stash + clone(cloner *cloner) stasher } -// ========== -// _objectStash -// ========== - -type _objectStash struct { - _runtime *_runtime - _outer _stash - object *_object +type objectStash struct { + rt *runtime + outr stasher + object *object } -func (self *_objectStash) runtime() *_runtime { - return self._runtime +func (s *objectStash) runtime() *runtime { + return s.rt } -func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash { - if object == nil { - object = runtime.newBaseObject() - object.class = "environment" +func (rt *runtime) newObjectStash(obj *object, outer stasher) *objectStash { + if obj == nil { + obj = rt.newBaseObject() + obj.class = "environment" } - return &_objectStash{ - _runtime: runtime, - _outer: outer, - object: object, + return &objectStash{ + rt: rt, + outr: outer, + object: obj, } } -func (in *_objectStash) clone(clone *_clone) _stash { - out, exists := clone.objectStash(in) +func (s *objectStash) clone(c *cloner) stasher { + out, exists := c.objectStash(s) if exists { return out } - *out = _objectStash{ - clone.runtime, - clone.stash(in._outer), - clone.object(in.object), + *out = objectStash{ + c.runtime, + c.stash(s.outr), + c.object(s.object), } return out } -func (self *_objectStash) hasBinding(name string) bool { - return self.object.hasProperty(name) +func (s *objectStash) hasBinding(name string) bool { + return s.object.hasProperty(name) } -func (self *_objectStash) createBinding(name string, deletable bool, value Value) { - if self.object.hasProperty(name) { +func (s *objectStash) createBinding(name string, deletable bool, value Value) { + if s.object.hasProperty(name) { panic(hereBeDragons()) } - mode := _propertyMode(0111) + mode := propertyMode(0o111) if !deletable { - mode = _propertyMode(0110) + mode = propertyMode(0o110) } // TODO False? - self.object.defineProperty(name, value, mode, false) + s.object.defineProperty(name, value, mode, false) } -func (self *_objectStash) setBinding(name string, value Value, strict bool) { - self.object.put(name, value, strict) +func (s *objectStash) setBinding(name string, value Value, strict bool) { + s.object.put(name, value, strict) } -func (self *_objectStash) setValue(name string, value Value, throw bool) { - if !self.hasBinding(name) { - self.createBinding(name, true, value) // Configurable by default +func (s *objectStash) setValue(name string, value Value, throw bool) { + if !s.hasBinding(name) { + s.createBinding(name, true, value) // Configurable by default } else { - self.setBinding(name, value, throw) + s.setBinding(name, value, throw) } } -func (self *_objectStash) getBinding(name string, throw bool) Value { - if self.object.hasProperty(name) { - return self.object.get(name) +func (s *objectStash) getBinding(name string, throw bool) Value { + if s.object.hasProperty(name) { + return s.object.get(name) } if throw { // strict? - panic(self._runtime.panicReferenceError("Not Defined", name)) + panic(s.rt.panicReferenceError("Not Defined", name)) } return Value{} } -func (self *_objectStash) deleteBinding(name string) bool { - return self.object.delete(name, false) +func (s *objectStash) deleteBinding(name string) bool { + return s.object.delete(name, false) } -func (self *_objectStash) outer() _stash { - return self._outer +func (s *objectStash) outer() stasher { + return s.outr } -func (self *_objectStash) newReference(name string, strict bool, at _at) _reference { - return newPropertyReference(self._runtime, self.object, name, strict, at) +func (s *objectStash) newReference(name string, strict bool, atv at) referencer { + return newPropertyReference(s.rt, s.object, name, strict, atv) } -// ========= -// _dclStash -// ========= - -type _dclStash struct { - _runtime *_runtime - _outer _stash - property map[string]_dclProperty +type dclStash struct { + rt *runtime + outr stasher + property map[string]dclProperty } -type _dclProperty struct { +type dclProperty struct { value Value mutable bool deletable bool readable bool } -func (runtime *_runtime) newDeclarationStash(outer _stash) *_dclStash { - return &_dclStash{ - _runtime: runtime, - _outer: outer, - property: map[string]_dclProperty{}, +func (rt *runtime) newDeclarationStash(outer stasher) *dclStash { + return &dclStash{ + rt: rt, + outr: outer, + property: map[string]dclProperty{}, } } -func (in *_dclStash) clone(clone *_clone) _stash { - out, exists := clone.dclStash(in) +func (s *dclStash) clone(c *cloner) stasher { + out, exists := c.dclStash(s) if exists { return out } - property := make(map[string]_dclProperty, len(in.property)) - for index, value := range in.property { - property[index] = clone.dclProperty(value) + prop := make(map[string]dclProperty, len(s.property)) + for index, value := range s.property { + prop[index] = c.dclProperty(value) } - *out = _dclStash{ - clone.runtime, - clone.stash(in._outer), - property, + *out = dclStash{ + c.runtime, + c.stash(s.outr), + prop, } return out } -func (self *_dclStash) hasBinding(name string) bool { - _, exists := self.property[name] +func (s *dclStash) hasBinding(name string) bool { + _, exists := s.property[name] return exists } -func (self *_dclStash) runtime() *_runtime { - return self._runtime +func (s *dclStash) runtime() *runtime { + return s.rt } -func (self *_dclStash) createBinding(name string, deletable bool, value Value) { - _, exists := self.property[name] - if exists { +func (s *dclStash) createBinding(name string, deletable bool, value Value) { + if _, exists := s.property[name]; exists { panic(fmt.Errorf("createBinding: %s: already exists", name)) } - self.property[name] = _dclProperty{ + s.property[name] = dclProperty{ value: value, mutable: true, deletable: deletable, @@ -177,62 +165,62 @@ func (self *_dclStash) createBinding(name string, deletable bool, value Value) { } } -func (self *_dclStash) setBinding(name string, value Value, strict bool) { - property, exists := self.property[name] +func (s *dclStash) setBinding(name string, value Value, strict bool) { + prop, exists := s.property[name] if !exists { panic(fmt.Errorf("setBinding: %s: missing", name)) } - if property.mutable { - property.value = value - self.property[name] = property + if prop.mutable { + prop.value = value + s.property[name] = prop } else { - self._runtime.typeErrorResult(strict) + s.rt.typeErrorResult(strict) } } -func (self *_dclStash) setValue(name string, value Value, throw bool) { - if !self.hasBinding(name) { - self.createBinding(name, false, value) // NOT deletable by default +func (s *dclStash) setValue(name string, value Value, throw bool) { + if !s.hasBinding(name) { + s.createBinding(name, false, value) // NOT deletable by default } else { - self.setBinding(name, value, throw) + s.setBinding(name, value, throw) } } -// FIXME This is called a __lot__ -func (self *_dclStash) getBinding(name string, throw bool) Value { - property, exists := self.property[name] +// FIXME This is called a __lot__. +func (s *dclStash) getBinding(name string, throw bool) Value { + prop, exists := s.property[name] if !exists { panic(fmt.Errorf("getBinding: %s: missing", name)) } - if !property.mutable && !property.readable { + if !prop.mutable && !prop.readable { if throw { // strict? - panic(self._runtime.panicTypeError()) + panic(s.rt.panicTypeError("getBinding property %s not mutable and not readable", name)) } return Value{} } - return property.value + return prop.value } -func (self *_dclStash) deleteBinding(name string) bool { - property, exists := self.property[name] +func (s *dclStash) deleteBinding(name string) bool { + prop, exists := s.property[name] if !exists { return true } - if !property.deletable { + if !prop.deletable { return false } - delete(self.property, name) + delete(s.property, name) return true } -func (self *_dclStash) outer() _stash { - return self._outer +func (s *dclStash) outer() stasher { + return s.outr } -func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference { - return &_stashReference{ +func (s *dclStash) newReference(name string, strict bool, _ at) referencer { + return &stashReference{ name: name, - base: self, + base: s, } } @@ -240,57 +228,62 @@ func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference // _fnStash // ======== -type _fnStash struct { - _dclStash - arguments *_object +type fnStash struct { + dclStash + arguments *object indexOfArgumentName map[string]string } -func (runtime *_runtime) newFunctionStash(outer _stash) *_fnStash { - return &_fnStash{ - _dclStash: _dclStash{ - _runtime: runtime, - _outer: outer, - property: map[string]_dclProperty{}, +func (rt *runtime) newFunctionStash(outer stasher) *fnStash { + return &fnStash{ + dclStash: dclStash{ + rt: rt, + outr: outer, + property: map[string]dclProperty{}, }, } } -func (in *_fnStash) clone(clone *_clone) _stash { - out, exists := clone.fnStash(in) +func (s *fnStash) clone(c *cloner) stasher { + out, exists := c.fnStash(s) if exists { return out } - dclStash := in._dclStash.clone(clone).(*_dclStash) - index := make(map[string]string, len(in.indexOfArgumentName)) - for name, value := range in.indexOfArgumentName { + dclStash := s.dclStash.clone(c).(*dclStash) + index := make(map[string]string, len(s.indexOfArgumentName)) + for name, value := range s.indexOfArgumentName { index[name] = value } - *out = _fnStash{ - _dclStash: *dclStash, - arguments: clone.object(in.arguments), + *out = fnStash{ + dclStash: *dclStash, + arguments: c.object(s.arguments), indexOfArgumentName: index, } return out } -func getStashProperties(stash _stash) (keys []string) { +// getStashProperties returns the properties from stash. +func getStashProperties(stash stasher) []string { switch vars := stash.(type) { - case *_dclStash: + case *dclStash: + keys := make([]string, 0, len(vars.property)) for k := range vars.property { keys = append(keys, k) } - case *_fnStash: + return keys + case *fnStash: + keys := make([]string, 0, len(vars.property)) for k := range vars.property { keys = append(keys, k) } - case *_objectStash: + return keys + case *objectStash: + keys := make([]string, 0, len(vars.object.property)) for k := range vars.object.property { keys = append(keys, k) } + return keys default: panic("unknown stash type") } - - return } diff --git a/vendor/github.com/robertkrimen/otto/token/Makefile b/vendor/github.com/robertkrimen/otto/token/Makefile deleted file mode 100644 index 1e85c7348..000000000 --- a/vendor/github.com/robertkrimen/otto/token/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -token_const.go: tokenfmt - ./$^ | gofmt > $@ diff --git a/vendor/github.com/robertkrimen/otto/token/README.markdown b/vendor/github.com/robertkrimen/otto/token/README.markdown deleted file mode 100644 index ff3b16104..000000000 --- a/vendor/github.com/robertkrimen/otto/token/README.markdown +++ /dev/null @@ -1,171 +0,0 @@ -# token --- - import "github.com/robertkrimen/otto/token" - -Package token defines constants representing the lexical tokens of JavaScript -(ECMA5). - -## Usage - -```go -const ( - ILLEGAL - EOF - COMMENT - KEYWORD - - STRING - BOOLEAN - NULL - NUMBER - IDENTIFIER - - PLUS // + - MINUS // - - MULTIPLY // * - SLASH // / - REMAINDER // % - - AND // & - OR // | - EXCLUSIVE_OR // ^ - SHIFT_LEFT // << - SHIFT_RIGHT // >> - UNSIGNED_SHIFT_RIGHT // >>> - AND_NOT // &^ - - ADD_ASSIGN // += - SUBTRACT_ASSIGN // -= - MULTIPLY_ASSIGN // *= - QUOTIENT_ASSIGN // /= - REMAINDER_ASSIGN // %= - - AND_ASSIGN // &= - OR_ASSIGN // |= - EXCLUSIVE_OR_ASSIGN // ^= - SHIFT_LEFT_ASSIGN // <<= - SHIFT_RIGHT_ASSIGN // >>= - UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>= - AND_NOT_ASSIGN // &^= - - LOGICAL_AND // && - LOGICAL_OR // || - INCREMENT // ++ - DECREMENT // -- - - EQUAL // == - STRICT_EQUAL // === - LESS // < - GREATER // > - ASSIGN // = - NOT // ! - - BITWISE_NOT // ~ - - NOT_EQUAL // != - STRICT_NOT_EQUAL // !== - LESS_OR_EQUAL // <= - GREATER_OR_EQUAL // >= - - LEFT_PARENTHESIS // ( - LEFT_BRACKET // [ - LEFT_BRACE // { - COMMA // , - PERIOD // . - - RIGHT_PARENTHESIS // ) - RIGHT_BRACKET // ] - RIGHT_BRACE // } - SEMICOLON // ; - COLON // : - QUESTION_MARK // ? - - IF - IN - DO - - VAR - FOR - NEW - TRY - - THIS - ELSE - CASE - VOID - WITH - - WHILE - BREAK - CATCH - THROW - - RETURN - TYPEOF - DELETE - SWITCH - - DEFAULT - FINALLY - - FUNCTION - CONTINUE - DEBUGGER - - INSTANCEOF -) -``` - -#### type Token - -```go -type Token int -``` - -Token is the set of lexical tokens in JavaScript (ECMA5). - -#### func IsKeyword - -```go -func IsKeyword(literal string) (Token, bool) -``` -IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token if -the literal is a future keyword (const, let, class, super, ...), or 0 if the -literal is not a keyword. - -If the literal is a keyword, IsKeyword returns a second value indicating if the -literal is considered a future keyword in strict-mode only. - -7.6.1.2 Future Reserved Words: - - const - class - enum - export - extends - import - super - -7.6.1.2 Future Reserved Words (strict): - - implements - interface - let - package - private - protected - public - static - -#### func (Token) String - -```go -func (tkn Token) String() string -``` -String returns the string corresponding to the token. For operators, delimiters, -and keywords the string is the actual token string (e.g., for the token PLUS, -the String() is "+"). For all other tokens the string corresponds to the token -name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER"). - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/token/token.go b/vendor/github.com/robertkrimen/otto/token/token.go index 0e941ac96..9fee9e1ef 100644 --- a/vendor/github.com/robertkrimen/otto/token/token.go +++ b/vendor/github.com/robertkrimen/otto/token/token.go @@ -13,66 +13,18 @@ type Token int // token string (e.g., for the token PLUS, the String() is // "+"). For all other tokens the string corresponds to the token // name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER"). -// func (tkn Token) String() string { - if 0 == tkn { + switch { + case tkn == 0: return "UNKNOWN" - } - if tkn < Token(len(token2string)) { + case tkn < Token(len(token2string)): return token2string[tkn] + default: + return "token(" + strconv.Itoa(int(tkn)) + ")" } - return "token(" + strconv.Itoa(int(tkn)) + ")" -} - -// This is not used for anything -func (tkn Token) precedence(in bool) int { - - switch tkn { - case LOGICAL_OR: - return 1 - - case LOGICAL_AND: - return 2 - - case OR, OR_ASSIGN: - return 3 - - case EXCLUSIVE_OR: - return 4 - - case AND, AND_ASSIGN, AND_NOT, AND_NOT_ASSIGN: - return 5 - - case EQUAL, - NOT_EQUAL, - STRICT_EQUAL, - STRICT_NOT_EQUAL: - return 6 - - case LESS, GREATER, LESS_OR_EQUAL, GREATER_OR_EQUAL, INSTANCEOF: - return 7 - - case IN: - if in { - return 7 - } - return 0 - - case SHIFT_LEFT, SHIFT_RIGHT, UNSIGNED_SHIFT_RIGHT: - fallthrough - case SHIFT_LEFT_ASSIGN, SHIFT_RIGHT_ASSIGN, UNSIGNED_SHIFT_RIGHT_ASSIGN: - return 8 - - case PLUS, MINUS, ADD_ASSIGN, SUBTRACT_ASSIGN: - return 9 - - case MULTIPLY, SLASH, REMAINDER, MULTIPLY_ASSIGN, QUOTIENT_ASSIGN, REMAINDER_ASSIGN: - return 11 - } - return 0 } -type _keyword struct { +type keyword struct { token Token futureKeyword bool strict bool @@ -86,31 +38,30 @@ type _keyword struct { // // 7.6.1.2 Future Reserved Words: // -// const -// class -// enum -// export -// extends -// import -// super +// const +// class +// enum +// export +// extends +// import +// super // // 7.6.1.2 Future Reserved Words (strict): // -// implements -// interface -// let -// package -// private -// protected -// public -// static -// +// implements +// interface +// let +// package +// private +// protected +// public +// static func IsKeyword(literal string) (Token, bool) { - if keyword, exists := keywordTable[literal]; exists { - if keyword.futureKeyword { - return KEYWORD, keyword.strict + if kw, exists := keywordTable[literal]; exists { + if kw.futureKeyword { + return KEYWORD, kw.strict } - return keyword.token, false + return kw.token, false } return 0, false } diff --git a/vendor/github.com/robertkrimen/otto/token/token_const.go b/vendor/github.com/robertkrimen/otto/token/token_const.go index b1d83c6de..09ba01781 100644 --- a/vendor/github.com/robertkrimen/otto/token/token_const.go +++ b/vendor/github.com/robertkrimen/otto/token/token_const.go @@ -1,25 +1,28 @@ +// Code generated by tools/gen-tokens. DO NOT EDIT. + package token const ( _ Token = iota + // Control. ILLEGAL EOF COMMENT KEYWORD - + // Types. STRING BOOLEAN NULL NUMBER IDENTIFIER - + // Maths. PLUS // + MINUS // - MULTIPLY // * SLASH // / REMAINDER // % - + // Logical and bitwise operators. AND // & OR // | EXCLUSIVE_OR // ^ @@ -27,13 +30,13 @@ const ( SHIFT_RIGHT // >> UNSIGNED_SHIFT_RIGHT // >>> AND_NOT // &^ - + // Math assignments. ADD_ASSIGN // += SUBTRACT_ASSIGN // -= MULTIPLY_ASSIGN // *= QUOTIENT_ASSIGN // /= REMAINDER_ASSIGN // %= - + // Math and bitwise assignments. AND_ASSIGN // &= OR_ASSIGN // |= EXCLUSIVE_OR_ASSIGN // ^= @@ -41,74 +44,73 @@ const ( SHIFT_RIGHT_ASSIGN // >>= UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>= AND_NOT_ASSIGN // &^= - + // Logical operators and decrement / increment. LOGICAL_AND // && LOGICAL_OR // || INCREMENT // ++ DECREMENT // -- - + // Comparison operators. EQUAL // == STRICT_EQUAL // === LESS // < GREATER // > ASSIGN // = NOT // ! - + // Bitwise not. BITWISE_NOT // ~ - + // Comparison operators. NOT_EQUAL // != STRICT_NOT_EQUAL // !== LESS_OR_EQUAL // <= GREATER_OR_EQUAL // >= - + // Left operators. LEFT_PARENTHESIS // ( LEFT_BRACKET // [ LEFT_BRACE // { COMMA // , PERIOD // . - + // Right operators. RIGHT_PARENTHESIS // ) RIGHT_BRACKET // ] RIGHT_BRACE // } SEMICOLON // ; COLON // : QUESTION_MARK // ? - - firstKeyword + // Basic flow - keywords below here. + _ IF IN DO - + // Declarations. VAR FOR NEW TRY - + // Advanced flow. THIS ELSE CASE VOID WITH - + // Loops. WHILE BREAK CATCH THROW - + // Functions. RETURN TYPEOF DELETE SWITCH - + // Fallback identifiers. DEFAULT FINALLY - + // Miscellaneous. FUNCTION CONTINUE DEBUGGER - + // Instance of. INSTANCEOF - lastKeyword ) var token2string = [...]string{ @@ -199,149 +201,149 @@ var token2string = [...]string{ INSTANCEOF: "instanceof", } -var keywordTable = map[string]_keyword{ - "if": _keyword{ +var keywordTable = map[string]keyword{ + "if": { token: IF, }, - "in": _keyword{ + "in": { token: IN, }, - "do": _keyword{ + "do": { token: DO, }, - "var": _keyword{ + "var": { token: VAR, }, - "for": _keyword{ + "for": { token: FOR, }, - "new": _keyword{ + "new": { token: NEW, }, - "try": _keyword{ + "try": { token: TRY, }, - "this": _keyword{ + "this": { token: THIS, }, - "else": _keyword{ + "else": { token: ELSE, }, - "case": _keyword{ + "case": { token: CASE, }, - "void": _keyword{ + "void": { token: VOID, }, - "with": _keyword{ + "with": { token: WITH, }, - "while": _keyword{ + "while": { token: WHILE, }, - "break": _keyword{ + "break": { token: BREAK, }, - "catch": _keyword{ + "catch": { token: CATCH, }, - "throw": _keyword{ + "throw": { token: THROW, }, - "return": _keyword{ + "return": { token: RETURN, }, - "typeof": _keyword{ + "typeof": { token: TYPEOF, }, - "delete": _keyword{ + "delete": { token: DELETE, }, - "switch": _keyword{ + "switch": { token: SWITCH, }, - "default": _keyword{ + "default": { token: DEFAULT, }, - "finally": _keyword{ + "finally": { token: FINALLY, }, - "function": _keyword{ + "function": { token: FUNCTION, }, - "continue": _keyword{ + "continue": { token: CONTINUE, }, - "debugger": _keyword{ + "debugger": { token: DEBUGGER, }, - "instanceof": _keyword{ + "instanceof": { token: INSTANCEOF, }, - "const": _keyword{ + "const": { token: KEYWORD, futureKeyword: true, }, - "class": _keyword{ + "class": { token: KEYWORD, futureKeyword: true, }, - "enum": _keyword{ + "enum": { token: KEYWORD, futureKeyword: true, }, - "export": _keyword{ + "export": { token: KEYWORD, futureKeyword: true, }, - "extends": _keyword{ + "extends": { token: KEYWORD, futureKeyword: true, }, - "import": _keyword{ + "import": { token: KEYWORD, futureKeyword: true, }, - "super": _keyword{ + "super": { token: KEYWORD, futureKeyword: true, }, - "implements": _keyword{ + "implements": { token: KEYWORD, futureKeyword: true, strict: true, }, - "interface": _keyword{ + "interface": { token: KEYWORD, futureKeyword: true, strict: true, }, - "let": _keyword{ + "let": { token: KEYWORD, futureKeyword: true, strict: true, }, - "package": _keyword{ + "package": { token: KEYWORD, futureKeyword: true, strict: true, }, - "private": _keyword{ + "private": { token: KEYWORD, futureKeyword: true, strict: true, }, - "protected": _keyword{ + "protected": { token: KEYWORD, futureKeyword: true, strict: true, }, - "public": _keyword{ + "public": { token: KEYWORD, futureKeyword: true, strict: true, }, - "static": _keyword{ + "static": { token: KEYWORD, futureKeyword: true, strict: true, diff --git a/vendor/github.com/robertkrimen/otto/token/tokenfmt b/vendor/github.com/robertkrimen/otto/token/tokenfmt deleted file mode 100644 index 63dd5d9e6..000000000 --- a/vendor/github.com/robertkrimen/otto/token/tokenfmt +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -my (%token, @order, @keywords); - -{ - my $keywords; - my @const; - push @const, <<_END_; -package token - -const( - _ Token = iota -_END_ - - for (split m/\n/, <<_END_) { -ILLEGAL -EOF -COMMENT -KEYWORD - -STRING -BOOLEAN -NULL -NUMBER -IDENTIFIER - -PLUS + -MINUS - -MULTIPLY * -SLASH / -REMAINDER % - -AND & -OR | -EXCLUSIVE_OR ^ -SHIFT_LEFT << -SHIFT_RIGHT >> -UNSIGNED_SHIFT_RIGHT >>> -AND_NOT &^ - -ADD_ASSIGN += -SUBTRACT_ASSIGN -= -MULTIPLY_ASSIGN *= -QUOTIENT_ASSIGN /= -REMAINDER_ASSIGN %= - -AND_ASSIGN &= -OR_ASSIGN |= -EXCLUSIVE_OR_ASSIGN ^= -SHIFT_LEFT_ASSIGN <<= -SHIFT_RIGHT_ASSIGN >>= -UNSIGNED_SHIFT_RIGHT_ASSIGN >>>= -AND_NOT_ASSIGN &^= - -LOGICAL_AND && -LOGICAL_OR || -INCREMENT ++ -DECREMENT -- - -EQUAL == -STRICT_EQUAL === -LESS < -GREATER > -ASSIGN = -NOT ! - -BITWISE_NOT ~ - -NOT_EQUAL != -STRICT_NOT_EQUAL !== -LESS_OR_EQUAL <= -GREATER_OR_EQUAL <= - -LEFT_PARENTHESIS ( -LEFT_BRACKET [ -LEFT_BRACE { -COMMA , -PERIOD . - -RIGHT_PARENTHESIS ) -RIGHT_BRACKET ] -RIGHT_BRACE } -SEMICOLON ; -COLON : -QUESTION_MARK ? - -firstKeyword -IF -IN -DO - -VAR -FOR -NEW -TRY - -THIS -ELSE -CASE -VOID -WITH - -WHILE -BREAK -CATCH -THROW - -RETURN -TYPEOF -DELETE -SWITCH - -DEFAULT -FINALLY - -FUNCTION -CONTINUE -DEBUGGER - -INSTANCEOF -lastKeyword -_END_ - chomp; - - next if m/^\s*#/; - - my ($name, $symbol) = m/(\w+)\s*(\S+)?/; - - if (defined $symbol) { - push @order, $name; - push @const, "$name // $symbol"; - $token{$name} = $symbol; - } elsif (defined $name) { - $keywords ||= $name eq 'firstKeyword'; - - push @const, $name; - #$const[-1] .= " Token = iota" if 2 == @const; - if ($name =~ m/^([A-Z]+)/) { - push @keywords, $name if $keywords; - push @order, $name; - if ($token{SEMICOLON}) { - $token{$name} = lc $1; - } else { - $token{$name} = $name; - } - } - } else { - push @const, ""; - } - - } - push @const, ")"; - print join "\n", @const, ""; -} - -{ - print <<_END_; - -var token2string = [...]string{ -_END_ - for my $name (@order) { - print "$name: \"$token{$name}\",\n"; - } - print <<_END_; -} -_END_ - - print <<_END_; - -var keywordTable = map[string]_keyword{ -_END_ - for my $name (@keywords) { - print <<_END_ - "@{[ lc $name ]}": _keyword{ - token: $name, - }, -_END_ - } - - for my $name (qw/ - const - class - enum - export - extends - import - super - /) { - print <<_END_ - "$name": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, -_END_ - } - - for my $name (qw/ - implements - interface - let - package - private - protected - public - static - /) { - print <<_END_ - "$name": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, -_END_ - } - - print <<_END_; -} -_END_ -} diff --git a/vendor/github.com/robertkrimen/otto/type_arguments.go b/vendor/github.com/robertkrimen/otto/type_arguments.go index 841d75855..7f2a83dc7 100644 --- a/vendor/github.com/robertkrimen/otto/type_arguments.go +++ b/vendor/github.com/robertkrimen/otto/type_arguments.go @@ -4,103 +4,97 @@ import ( "strconv" ) -func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, stash _stash, length int) *_object { - self := runtime.newClassObject("Arguments") +func (rt *runtime) newArgumentsObject(indexOfParameterName []string, stash stasher, length int) *object { + obj := rt.newClassObject("Arguments") - for index, _ := range indexOfParameterName { + for index := range indexOfParameterName { name := strconv.FormatInt(int64(index), 10) - objectDefineOwnProperty(self, name, _property{Value{}, 0111}, false) + objectDefineOwnProperty(obj, name, property{Value{}, 0o111}, false) } - self.objectClass = _classArguments - self.value = _argumentsObject{ + obj.objectClass = classArguments + obj.value = argumentsObject{ indexOfParameterName: indexOfParameterName, stash: stash, } - self.prototype = runtime.global.ObjectPrototype + obj.prototype = rt.global.ObjectPrototype - self.defineProperty("length", toValue_int(length), 0101, false) + obj.defineProperty(propertyLength, intValue(length), 0o101, false) - return self + return obj } -type _argumentsObject struct { +type argumentsObject struct { + stash stasher indexOfParameterName []string - // function(abc, def, ghi) - // indexOfParameterName[0] = "abc" - // indexOfParameterName[1] = "def" - // indexOfParameterName[2] = "ghi" - // ... - stash _stash } -func (in _argumentsObject) clone(clone *_clone) _argumentsObject { - indexOfParameterName := make([]string, len(in.indexOfParameterName)) - copy(indexOfParameterName, in.indexOfParameterName) - return _argumentsObject{ - indexOfParameterName, - clone.stash(in.stash), +func (o argumentsObject) clone(c *cloner) argumentsObject { + indexOfParameterName := make([]string, len(o.indexOfParameterName)) + copy(indexOfParameterName, o.indexOfParameterName) + return argumentsObject{ + indexOfParameterName: indexOfParameterName, + stash: c.stash(o.stash), } } -func (self _argumentsObject) get(name string) (Value, bool) { +func (o argumentsObject) get(name string) (Value, bool) { index := stringToArrayIndex(name) - if index >= 0 && index < int64(len(self.indexOfParameterName)) { - name := self.indexOfParameterName[index] - if name == "" { + if index >= 0 && index < int64(len(o.indexOfParameterName)) { + if name = o.indexOfParameterName[index]; name == "" { return Value{}, false } - return self.stash.getBinding(name, false), true + return o.stash.getBinding(name, false), true } return Value{}, false } -func (self _argumentsObject) put(name string, value Value) { +func (o argumentsObject) put(name string, value Value) { index := stringToArrayIndex(name) - name = self.indexOfParameterName[index] - self.stash.setBinding(name, value, false) + name = o.indexOfParameterName[index] + o.stash.setBinding(name, value, false) } -func (self _argumentsObject) delete(name string) { +func (o argumentsObject) delete(name string) { index := stringToArrayIndex(name) - self.indexOfParameterName[index] = "" + o.indexOfParameterName[index] = "" } -func argumentsGet(self *_object, name string) Value { - if value, exists := self.value.(_argumentsObject).get(name); exists { +func argumentsGet(obj *object, name string) Value { + if value, exists := obj.value.(argumentsObject).get(name); exists { return value } - return objectGet(self, name) + return objectGet(obj, name) } -func argumentsGetOwnProperty(self *_object, name string) *_property { - property := objectGetOwnProperty(self, name) - if value, exists := self.value.(_argumentsObject).get(name); exists { - property.value = value +func argumentsGetOwnProperty(obj *object, name string) *property { + prop := objectGetOwnProperty(obj, name) + if value, exists := obj.value.(argumentsObject).get(name); exists { + prop.value = value } - return property + return prop } -func argumentsDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - if _, exists := self.value.(_argumentsObject).get(name); exists { - if !objectDefineOwnProperty(self, name, descriptor, false) { - return self.runtime.typeErrorResult(throw) +func argumentsDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if _, exists := obj.value.(argumentsObject).get(name); exists { + if !objectDefineOwnProperty(obj, name, descriptor, false) { + return obj.runtime.typeErrorResult(throw) } if value, valid := descriptor.value.(Value); valid { - self.value.(_argumentsObject).put(name, value) + obj.value.(argumentsObject).put(name, value) } return true } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func argumentsDelete(self *_object, name string, throw bool) bool { - if !objectDelete(self, name, throw) { +func argumentsDelete(obj *object, name string, throw bool) bool { + if !objectDelete(obj, name, throw) { return false } - if _, exists := self.value.(_argumentsObject).get(name); exists { - self.value.(_argumentsObject).delete(name) + if _, exists := obj.value.(argumentsObject).get(name); exists { + obj.value.(argumentsObject).delete(name) } return true } diff --git a/vendor/github.com/robertkrimen/otto/type_array.go b/vendor/github.com/robertkrimen/otto/type_array.go index c8a974b02..cb673544c 100644 --- a/vendor/github.com/robertkrimen/otto/type_array.go +++ b/vendor/github.com/robertkrimen/otto/type_array.go @@ -4,34 +4,43 @@ import ( "strconv" ) -func (runtime *_runtime) newArrayObject(length uint32) *_object { - self := runtime.newObject() - self.class = "Array" - self.defineProperty("length", toValue_uint32(length), 0100, false) - self.objectClass = _classArray - return self +func (rt *runtime) newArrayObject(length uint32) *object { + obj := rt.newObject() + obj.class = classArrayName + obj.defineProperty(propertyLength, uint32Value(length), 0o100, false) + obj.objectClass = classArray + return obj } -func isArray(object *_object) bool { - return object != nil && (object.class == "Array" || object.class == "GoArray") +func isArray(obj *object) bool { + if obj == nil { + return false + } + + switch obj.class { + case classArrayName, classGoArrayName, classGoSliceName: + return true + default: + return false + } } -func objectLength(object *_object) uint32 { - if object == nil { +func objectLength(obj *object) uint32 { + if obj == nil { return 0 } - switch object.class { - case "Array": - return object.get("length").value.(uint32) - case "String": - return uint32(object.get("length").value.(int)) - case "GoArray": - return uint32(object.get("length").value.(int)) + switch obj.class { + case classArrayName: + return obj.get(propertyLength).value.(uint32) + case classStringName: + return uint32(obj.get(propertyLength).value.(int)) + case classGoArrayName, classGoSliceName: + return uint32(obj.get(propertyLength).value.(int)) } return 0 } -func arrayUint32(rt *_runtime, value Value) uint32 { +func arrayUint32(rt *runtime, value Value) uint32 { nm := value.number() if nm.kind != numberInteger || !isUint32(nm.int64) { // FIXME @@ -40,70 +49,72 @@ func arrayUint32(rt *_runtime, value Value) uint32 { return uint32(nm.int64) } -func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - lengthProperty := self.getOwnProperty("length") +func arrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + lengthProperty := obj.getOwnProperty(propertyLength) lengthValue, valid := lengthProperty.value.(Value) if !valid { panic("Array.length != Value{}") } + + reject := func(reason string) bool { + if throw { + panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %s", reason)) + } + return false + } length := lengthValue.value.(uint32) - if name == "length" { + if name == propertyLength { if descriptor.value == nil { - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } newLengthValue, isValue := descriptor.value.(Value) if !isValue { - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %q is not a value", descriptor.value)) } - newLength := arrayUint32(self.runtime, newLengthValue) - descriptor.value = toValue_uint32(newLength) + newLength := arrayUint32(obj.runtime, newLengthValue) + descriptor.value = uint32Value(newLength) if newLength > length { - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } if !lengthProperty.writable() { - goto Reject + return reject("property length for not writable") } newWritable := true - if descriptor.mode&0700 == 0 { + if descriptor.mode&0o700 == 0 { // If writable is off newWritable = false - descriptor.mode |= 0100 + descriptor.mode |= 0o100 } - if !objectDefineOwnProperty(self, name, descriptor, throw) { + if !objectDefineOwnProperty(obj, name, descriptor, throw) { return false } for newLength < length { length-- - if !self.delete(strconv.FormatInt(int64(length), 10), false) { - descriptor.value = toValue_uint32(length + 1) + if !obj.delete(strconv.FormatInt(int64(length), 10), false) { + descriptor.value = uint32Value(length + 1) if !newWritable { - descriptor.mode &= 0077 + descriptor.mode &= 0o077 } - objectDefineOwnProperty(self, name, descriptor, false) - goto Reject + objectDefineOwnProperty(obj, name, descriptor, false) + return reject("delete failed") } } if !newWritable { - descriptor.mode &= 0077 - objectDefineOwnProperty(self, name, descriptor, false) + descriptor.mode &= 0o077 + objectDefineOwnProperty(obj, name, descriptor, false) } } else if index := stringToArrayIndex(name); index >= 0 { if index >= int64(length) && !lengthProperty.writable() { - goto Reject + return reject("property length not writable") } - if !objectDefineOwnProperty(self, strconv.FormatInt(index, 10), descriptor, false) { - goto Reject + if !objectDefineOwnProperty(obj, strconv.FormatInt(index, 10), descriptor, false) { + return reject("Object.DefineOwnProperty failed") } if index >= int64(length) { - lengthProperty.value = toValue_uint32(uint32(index + 1)) - objectDefineOwnProperty(self, "length", *lengthProperty, false) + lengthProperty.value = uint32Value(uint32(index + 1)) + objectDefineOwnProperty(obj, propertyLength, *lengthProperty, false) return true } } - return objectDefineOwnProperty(self, name, descriptor, throw) -Reject: - if throw { - panic(self.runtime.panicTypeError()) - } - return false + return objectDefineOwnProperty(obj, name, descriptor, throw) } diff --git a/vendor/github.com/robertkrimen/otto/type_boolean.go b/vendor/github.com/robertkrimen/otto/type_boolean.go index afc45c69b..3620553cd 100644 --- a/vendor/github.com/robertkrimen/otto/type_boolean.go +++ b/vendor/github.com/robertkrimen/otto/type_boolean.go @@ -1,13 +1,5 @@ package otto -import ( - "strconv" -) - -func (runtime *_runtime) newBooleanObject(value Value) *_object { - return runtime.newPrimitiveObject("Boolean", toValue_bool(value.bool())) -} - -func booleanToString(value bool) string { - return strconv.FormatBool(value) +func (rt *runtime) newBooleanObject(value Value) *object { + return rt.newPrimitiveObject(classBooleanName, boolValue(value.bool())) } diff --git a/vendor/github.com/robertkrimen/otto/type_date.go b/vendor/github.com/robertkrimen/otto/type_date.go index 7079e649c..d35d1e69d 100644 --- a/vendor/github.com/robertkrimen/otto/type_date.go +++ b/vendor/github.com/robertkrimen/otto/type_date.go @@ -7,23 +7,22 @@ import ( Time "time" ) -type _dateObject struct { - time Time.Time // Time from the "time" package, a cached version of time - epoch int64 +type dateObject struct { + time Time.Time value Value + epoch int64 isNaN bool } -var ( - invalidDateObject = _dateObject{ - time: Time.Time{}, - epoch: -1, - value: NaNValue(), - isNaN: true, - } -) +var invalidDateObject = dateObject{ + time: Time.Time{}, + epoch: -1, + value: NaNValue(), + isNaN: true, +} -type _ecmaTime struct { +type ecmaTime struct { + location *Time.Location year int month int day int @@ -31,80 +30,73 @@ type _ecmaTime struct { minute int second int millisecond int - location *Time.Location // Basically, either local or UTC } -func ecmaTime(goTime Time.Time) _ecmaTime { - return _ecmaTime{ - goTime.Year(), - dateFromGoMonth(goTime.Month()), - goTime.Day(), - goTime.Hour(), - goTime.Minute(), - goTime.Second(), - goTime.Nanosecond() / (100 * 100 * 100), - goTime.Location(), +func newEcmaTime(goTime Time.Time) ecmaTime { + return ecmaTime{ + year: goTime.Year(), + month: dateFromGoMonth(goTime.Month()), + day: goTime.Day(), + hour: goTime.Hour(), + minute: goTime.Minute(), + second: goTime.Second(), + millisecond: goTime.Nanosecond() / (100 * 100 * 100), + location: goTime.Location(), } } -func (self *_ecmaTime) goTime() Time.Time { +func (t *ecmaTime) goTime() Time.Time { return Time.Date( - self.year, - dateToGoMonth(self.month), - self.day, - self.hour, - self.minute, - self.second, - self.millisecond*(100*100*100), - self.location, + t.year, + dateToGoMonth(t.month), + t.day, + t.hour, + t.minute, + t.second, + t.millisecond*(100*100*100), + t.location, ) } -func (self *_dateObject) Time() Time.Time { - return self.time -} - -func (self *_dateObject) Epoch() int64 { - return self.epoch +func (d *dateObject) Time() Time.Time { + return d.time } -func (self *_dateObject) Value() Value { - return self.value +func (d *dateObject) Epoch() int64 { + return d.epoch } -// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1 -func (self *_dateObject) SetNaN() { - self.time = Time.Time{} - self.epoch = -1 - self.value = NaNValue() - self.isNaN = true +func (d *dateObject) Value() Value { + return d.value } -func (self *_dateObject) SetTime(time Time.Time) { - self.Set(timeToEpoch(time)) +// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1. +func (d *dateObject) SetNaN() { + d.time = Time.Time{} + d.epoch = -1 + d.value = NaNValue() + d.isNaN = true } -func epoch2dateObject(epoch float64) _dateObject { - date := _dateObject{} - date.Set(epoch) - return date +func (d *dateObject) SetTime(time Time.Time) { + d.Set(timeToEpoch(time)) } -func (self *_dateObject) Set(epoch float64) { +func (d *dateObject) Set(epoch float64) { // epoch - self.epoch = epochToInteger(epoch) + d.epoch = epochToInteger(epoch) // time time, err := epochToTime(epoch) - self.time = time // Is either a valid time, or the zero-value for time.Time + d.time = time // Is either a valid time, or the zero-value for time.Time // value & isNaN if err != nil { - self.isNaN = true - self.epoch = -1 - self.value = NaNValue() + d.isNaN = true + d.epoch = -1 + d.value = NaNValue() } else { - self.value = toValue_int64(self.epoch) + d.value = int64Value(d.epoch) } } @@ -115,48 +107,49 @@ func epochToInteger(value float64) int64 { return int64(math.Ceil(value)) } -func epochToTime(value float64) (time Time.Time, err error) { +func epochToTime(value float64) (Time.Time, error) { epochWithMilli := value if math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) { - err = fmt.Errorf("Invalid time %v", value) - return + return Time.Time{}, fmt.Errorf("invalid time %v", value) } epoch := int64(epochWithMilli / 1000) milli := int64(epochWithMilli) % 1000 - time = Time.Unix(int64(epoch), milli*1000000).UTC() - return + return Time.Unix(epoch, milli*1000000).In(utcTimeZone), nil } func timeToEpoch(time Time.Time) float64 { - return float64(time.UnixNano() / (1000 * 1000)) + return float64(time.UnixMilli()) } -func (runtime *_runtime) newDateObject(epoch float64) *_object { - self := runtime.newObject() - self.class = "Date" +func (rt *runtime) newDateObject(epoch float64) *object { + obj := rt.newObject() + obj.class = classDateName // FIXME This is ugly... - date := _dateObject{} + date := dateObject{} date.Set(epoch) - self.value = date - return self + obj.value = date + return obj } -func (self *_object) dateValue() _dateObject { - value, _ := self.value.(_dateObject) +func (o *object) dateValue() dateObject { + value, _ := o.value.(dateObject) return value } -func dateObjectOf(rt *_runtime, _dateObject *_object) _dateObject { - if _dateObject == nil || _dateObject.class != "Date" { - panic(rt.panicTypeError()) +func dateObjectOf(rt *runtime, date *object) dateObject { + if date == nil { + panic(rt.panicTypeError("Date.ObjectOf is nil")) } - return _dateObject.dateValue() + if date.class != classDateName { + panic(rt.panicTypeError("Date.ObjectOf %q != %q", date.class, classDateName)) + } + return date.dateValue() } -// JavaScript is 0-based, Go is 1-based (15.9.1.4) +// JavaScript is 0-based, Go is 1-based (15.9.1.4). func dateToGoMonth(month int) Time.Month { return Time.Month(month + 1) } @@ -165,17 +158,12 @@ func dateFromGoMonth(month Time.Month) int { return int(month) - 1 } -// Both JavaScript & Go are 0-based (Sunday == 0) -func dateToGoDay(day int) Time.Weekday { - return Time.Weekday(day) -} - func dateFromGoDay(day Time.Weekday) int { return int(day) } -func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) { - +// newDateTime returns the epoch of date contained in argumentList for location. +func newDateTime(argumentList []Value, location *Time.Location) float64 { pick := func(index int, default_ float64) (float64, bool) { if index >= len(argumentList) { return default_, false @@ -187,29 +175,41 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) return value, false } - if len(argumentList) >= 2 { // 2-argument, 3-argument, ... + switch len(argumentList) { + case 0: // 0-argument + time := Time.Now().In(utcTimeZone) + return timeToEpoch(time) + case 1: // 1-argument + value := valueOfArrayIndex(argumentList, 0) + value = toPrimitiveValue(value) + if value.IsString() { + return dateParse(value.string()) + } + + return value.float64() + default: // 2-argument, 3-argument, ... var year, month, day, hour, minute, second, millisecond float64 var invalid bool if year, invalid = pick(0, 1900.0); invalid { - goto INVALID + return math.NaN() } if month, invalid = pick(1, 0.0); invalid { - goto INVALID + return math.NaN() } if day, invalid = pick(2, 1.0); invalid { - goto INVALID + return math.NaN() } if hour, invalid = pick(3, 0.0); invalid { - goto INVALID + return math.NaN() } if minute, invalid = pick(4, 0.0); invalid { - goto INVALID + return math.NaN() } if second, invalid = pick(5, 0.0); invalid { - goto INVALID + return math.NaN() } if millisecond, invalid = pick(6, 0.0); invalid { - goto INVALID + return math.NaN() } if year >= 0 && year <= 99 { @@ -218,23 +218,7 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) time := Time.Date(int(year), dateToGoMonth(int(month)), int(day), int(hour), int(minute), int(second), int(millisecond)*1000*1000, location) return timeToEpoch(time) - - } else if len(argumentList) == 0 { // 0-argument - time := Time.Now().UTC() - return timeToEpoch(time) - } else { // 1-argument - value := valueOfArrayIndex(argumentList, 0) - value = toPrimitive(value) - if value.IsString() { - return dateParse(value.string()) - } - - return value.float64() } - -INVALID: - epoch = math.NaN() - return } var ( @@ -251,6 +235,10 @@ var ( "2006-01T15:04:05", "2006-01-02T15:04:05", + "2006/01", + "2006/01/02", + "2006/01/02 15:04:05", + "2006T15:04:05.000", "2006-01T15:04:05.000", "2006-01-02T15:04:05.000", @@ -272,28 +260,30 @@ var ( matchDateTimeZone = regexp.MustCompile(`^(.*)(?:(Z)|([\+\-]\d{2}):(\d{2}))$`) ) -func dateParse(date string) (epoch float64) { +// dateParse returns the epoch of the parsed date. +func dateParse(date string) float64 { // YYYY-MM-DDTHH:mm:ss.sssZ var time Time.Time var err error - { - date := date - if match := matchDateTimeZone.FindStringSubmatch(date); match != nil { - if match[2] == "Z" { - date = match[1] + "+0000" - } else { - date = match[1] + match[3] + match[4] - } + + if match := matchDateTimeZone.FindStringSubmatch(date); match != nil { + if match[2] == "Z" { + date = match[1] + "+0000" + } else { + date = match[1] + match[3] + match[4] } - for _, layout := range dateLayoutList { - time, err = Time.Parse(layout, date) - if err == nil { - break - } + } + + for _, layout := range dateLayoutList { + time, err = Time.Parse(layout, date) + if err == nil { + break } } + if err != nil { return math.NaN() } - return float64(time.UnixNano()) / (1000 * 1000) // UnixMilli() + + return float64(time.UnixMilli()) } diff --git a/vendor/github.com/robertkrimen/otto/type_error.go b/vendor/github.com/robertkrimen/otto/type_error.go index 84e5d79b1..3ad9d6bda 100644 --- a/vendor/github.com/robertkrimen/otto/type_error.go +++ b/vendor/github.com/robertkrimen/otto/type_error.go @@ -1,24 +1,58 @@ package otto -func (rt *_runtime) newErrorObject(name string, message Value, stackFramesToPop int) *_object { - self := rt.newClassObject("Error") +func (rt *runtime) newErrorObject(name string, message Value, stackFramesToPop int) *object { + obj := rt.newClassObject(classErrorName) if message.IsDefined() { - msg := message.string() - self.defineProperty("message", toValue_string(msg), 0111, false) - self.value = newError(rt, name, stackFramesToPop, msg) + err := newError(rt, name, stackFramesToPop, "%s", message.string()) + obj.defineProperty("message", err.messageValue(), 0o111, false) + obj.value = err } else { - self.value = newError(rt, name, stackFramesToPop) + obj.value = newError(rt, name, stackFramesToPop) } - self.defineOwnProperty("stack", _property{ - value: _propertyGetSet{ + obj.defineOwnProperty("stack", property{ + value: propertyGetSet{ rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value { - return toValue_string(self.value.(_error).formatWithStack()) + return stringValue(obj.value.(ottoError).formatWithStack()) }), - &_nilGetSetObject, + &nilGetSetObject, }, mode: modeConfigureMask & modeOnMask, }, false) - return self + return obj +} + +func (rt *runtime) newErrorObjectError(err ottoError) *object { + obj := rt.newClassObject(classErrorName) + obj.defineProperty("message", err.messageValue(), 0o111, false) + obj.value = err + switch err.name { + case "EvalError": + obj.prototype = rt.global.EvalErrorPrototype + case "TypeError": + obj.prototype = rt.global.TypeErrorPrototype + case "RangeError": + obj.prototype = rt.global.RangeErrorPrototype + case "ReferenceError": + obj.prototype = rt.global.ReferenceErrorPrototype + case "SyntaxError": + obj.prototype = rt.global.SyntaxErrorPrototype + case "URIError": + obj.prototype = rt.global.URIErrorPrototype + default: + obj.prototype = rt.global.ErrorPrototype + } + + obj.defineOwnProperty("stack", property{ + value: propertyGetSet{ + rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value { + return stringValue(obj.value.(ottoError).formatWithStack()) + }), + &nilGetSetObject, + }, + mode: modeConfigureMask & modeOnMask, + }, false) + + return obj } diff --git a/vendor/github.com/robertkrimen/otto/type_function.go b/vendor/github.com/robertkrimen/otto/type_function.go index ad4b1f16f..41e63933e 100644 --- a/vendor/github.com/robertkrimen/otto/type_function.go +++ b/vendor/github.com/robertkrimen/otto/type_function.go @@ -1,20 +1,20 @@ package otto -// _constructFunction -type _constructFunction func(*_object, []Value) Value +// constructFunction. +type constructFunction func(*object, []Value) Value -// 13.2.2 [[Construct]] -func defaultConstruct(fn *_object, argumentList []Value) Value { - object := fn.runtime.newObject() - object.class = "Object" +// 13.2.2 [[Construct]]. +func defaultConstruct(fn *object, argumentList []Value) Value { + obj := fn.runtime.newObject() + obj.class = classObjectName prototype := fn.get("prototype") if prototype.kind != valueObject { - prototype = toValue_object(fn.runtime.global.ObjectPrototype) + prototype = objectValue(fn.runtime.global.ObjectPrototype) } - object.prototype = prototype._object() + obj.prototype = prototype.object() - this := toValue_object(object) + this := objectValue(obj) value := fn.call(this, argumentList, false, nativeFrame) if value.kind == valueObject { return value @@ -22,176 +22,165 @@ func defaultConstruct(fn *_object, argumentList []Value) Value { return this } -// _nativeFunction -type _nativeFunction func(FunctionCall) Value +// nativeFunction. +type nativeFunction func(FunctionCall) Value -// ===================== // -// _nativeFunctionObject // -// ===================== // - -type _nativeFunctionObject struct { +// nativeFunctionObject. +type nativeFunctionObject struct { + call nativeFunction + construct constructFunction name string file string line int - call _nativeFunction // [[Call]] - construct _constructFunction // [[Construct]] } -func (runtime *_runtime) _newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object { - self := runtime.newClassObject("Function") - self.value = _nativeFunctionObject{ +func (rt *runtime) newNativeFunctionProperty(name, file string, line int, native nativeFunction, length int) *object { + o := rt.newClassObject(classFunctionName) + o.value = nativeFunctionObject{ name: name, file: file, line: line, call: native, construct: defaultConstruct, } - self.defineProperty("name", toValue_string(name), 0000, false) - self.defineProperty("length", toValue_int(length), 0000, false) - return self + o.defineProperty("name", stringValue(name), 0o000, false) + o.defineProperty(propertyLength, intValue(length), 0o000, false) + return o } -func (runtime *_runtime) newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object { - self := runtime._newNativeFunctionObject(name, file, line, native, length) - self.defineOwnProperty("caller", _property{ - value: _propertyGetSet{ - runtime._newNativeFunctionObject("get", "internal", 0, func(fc FunctionCall) Value { - for sc := runtime.scope; sc != nil; sc = sc.outer { - if sc.frame.fn == self { +func (rt *runtime) newNativeFunctionObject(name, file string, line int, native nativeFunction, length int) *object { + o := rt.newNativeFunctionProperty(name, file, line, native, length) + o.defineOwnProperty("caller", property{ + value: propertyGetSet{ + rt.newNativeFunctionProperty("get", "internal", 0, func(fc FunctionCall) Value { + for sc := rt.scope; sc != nil; sc = sc.outer { + if sc.frame.fn == o { if sc.outer == nil || sc.outer.frame.fn == nil { return nullValue } - return runtime.toValue(sc.outer.frame.fn) + return rt.toValue(sc.outer.frame.fn) } } return nullValue }, 0), - &_nilGetSetObject, + &nilGetSetObject, }, - mode: 0000, + mode: 0o000, }, false) - return self + return o } -// =================== // -// _bindFunctionObject // -// =================== // - -type _bindFunctionObject struct { - target *_object +// bindFunctionObject. +type bindFunctionObject struct { + target *object this Value argumentList []Value } -func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newClassObject("Function") - self.value = _bindFunctionObject{ +func (rt *runtime) newBoundFunctionObject(target *object, this Value, argumentList []Value) *object { + o := rt.newClassObject(classFunctionName) + o.value = bindFunctionObject{ target: target, this: this, argumentList: argumentList, } - length := int(toInt32(target.get("length"))) + length := int(toInt32(target.get(propertyLength))) length -= len(argumentList) if length < 0 { length = 0 } - self.defineProperty("name", toValue_string("bound "+target.get("name").String()), 0000, false) - self.defineProperty("length", toValue_int(length), 0000, false) - self.defineProperty("caller", Value{}, 0000, false) // TODO Should throw a TypeError - self.defineProperty("arguments", Value{}, 0000, false) // TODO Should throw a TypeError - return self + o.defineProperty("name", stringValue("bound "+target.get("name").String()), 0o000, false) + o.defineProperty(propertyLength, intValue(length), 0o000, false) + o.defineProperty("caller", Value{}, 0o000, false) // TODO Should throw a TypeError + o.defineProperty("arguments", Value{}, 0o000, false) // TODO Should throw a TypeError + return o } -// [[Construct]] -func (fn _bindFunctionObject) construct(argumentList []Value) Value { - object := fn.target - switch value := object.value.(type) { - case _nativeFunctionObject: - return value.construct(object, fn.argumentList) - case _nodeFunctionObject: +// [[Construct]]. +func (fn bindFunctionObject) construct(argumentList []Value) Value { + obj := fn.target + switch value := obj.value.(type) { + case nativeFunctionObject: + return value.construct(obj, fn.argumentList) + case nodeFunctionObject: argumentList = append(fn.argumentList, argumentList...) - return object.construct(argumentList) + return obj.construct(argumentList) + default: + panic(fn.target.runtime.panicTypeError("construct unknown type %T", obj.value)) } - panic(fn.target.runtime.panicTypeError()) } -// =================== // -// _nodeFunctionObject // -// =================== // - -type _nodeFunctionObject struct { - node *_nodeFunctionLiteral - stash _stash +// nodeFunctionObject. +type nodeFunctionObject struct { + node *nodeFunctionLiteral + stash stasher } -func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, stash _stash) *_object { - self := runtime.newClassObject("Function") - self.value = _nodeFunctionObject{ +func (rt *runtime) newNodeFunctionObject(node *nodeFunctionLiteral, stash stasher) *object { + o := rt.newClassObject(classFunctionName) + o.value = nodeFunctionObject{ node: node, stash: stash, } - self.defineProperty("name", toValue_string(node.name), 0000, false) - self.defineProperty("length", toValue_int(len(node.parameterList)), 0000, false) - self.defineOwnProperty("caller", _property{ - value: _propertyGetSet{ - runtime.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value { - for sc := runtime.scope; sc != nil; sc = sc.outer { - if sc.frame.fn == self { + o.defineProperty("name", stringValue(node.name), 0o000, false) + o.defineProperty(propertyLength, intValue(len(node.parameterList)), 0o000, false) + o.defineOwnProperty("caller", property{ + value: propertyGetSet{ + rt.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value { + for sc := rt.scope; sc != nil; sc = sc.outer { + if sc.frame.fn == o { if sc.outer == nil || sc.outer.frame.fn == nil { return nullValue } - return runtime.toValue(sc.outer.frame.fn) + return rt.toValue(sc.outer.frame.fn) } } return nullValue }), - &_nilGetSetObject, + &nilGetSetObject, }, - mode: 0000, + mode: 0o000, }, false) - return self + return o } -// ======= // -// _object // -// ======= // - -func (self *_object) isCall() bool { - switch fn := self.value.(type) { - case _nativeFunctionObject: +// _object. +func (o *object) isCall() bool { + switch fn := o.value.(type) { + case nativeFunctionObject: return fn.call != nil - case _bindFunctionObject: + case bindFunctionObject: return true - case _nodeFunctionObject: + case nodeFunctionObject: return true + default: + return false } - return false } -func (self *_object) call(this Value, argumentList []Value, eval bool, frame _frame) Value { - switch fn := self.value.(type) { - - case _nativeFunctionObject: +func (o *object) call(this Value, argumentList []Value, eval bool, frm frame) Value { //nolint:unparam // Isn't currently used except in recursive self. + switch fn := o.value.(type) { + case nativeFunctionObject: // Since eval is a native function, we only have to check for it here if eval { - eval = self == self.runtime.eval // If eval is true, then it IS a direct eval + eval = o == o.runtime.eval // If eval is true, then it IS a direct eval } // Enter a scope, name from the native object... - rt := self.runtime + rt := o.runtime if rt.scope != nil && !eval { rt.enterFunctionScope(rt.scope.lexical, this) - rt.scope.frame = _frame{ + rt.scope.frame = frame{ native: true, nativeFile: fn.file, nativeLine: fn.line, callee: fn.name, file: nil, - fn: self, + fn: o, } defer func() { rt.leaveScope() @@ -199,78 +188,77 @@ func (self *_object) call(this Value, argumentList []Value, eval bool, frame _fr } return fn.call(FunctionCall{ - runtime: self.runtime, + runtime: o.runtime, eval: eval, This: this, ArgumentList: argumentList, - Otto: self.runtime.otto, + Otto: o.runtime.otto, }) - case _bindFunctionObject: + case bindFunctionObject: // TODO Passthrough site, do not enter a scope argumentList = append(fn.argumentList, argumentList...) - return fn.target.call(fn.this, argumentList, false, frame) + return fn.target.call(fn.this, argumentList, false, frm) - case _nodeFunctionObject: - rt := self.runtime + case nodeFunctionObject: + rt := o.runtime stash := rt.enterFunctionScope(fn.stash, this) - rt.scope.frame = _frame{ + rt.scope.frame = frame{ callee: fn.node.name, file: fn.node.file, - fn: self, + fn: o, } defer func() { rt.leaveScope() }() - callValue := rt.cmpl_call_nodeFunction(self, stash, fn.node, this, argumentList) - if value, valid := callValue.value.(_result); valid { + callValue := rt.cmplCallNodeFunction(o, stash, fn.node, argumentList) + if value, valid := callValue.value.(result); valid { return value.value } return callValue } - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } -func (self *_object) construct(argumentList []Value) Value { - switch fn := self.value.(type) { - - case _nativeFunctionObject: +func (o *object) construct(argumentList []Value) Value { + switch fn := o.value.(type) { + case nativeFunctionObject: if fn.call == nil { - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } if fn.construct == nil { - panic(self.runtime.panicTypeError("%v is not a constructor", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a constructor", objectValue(o))) } - return fn.construct(self, argumentList) + return fn.construct(o, argumentList) - case _bindFunctionObject: + case bindFunctionObject: return fn.construct(argumentList) - case _nodeFunctionObject: - return defaultConstruct(self, argumentList) + case nodeFunctionObject: + return defaultConstruct(o, argumentList) } - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } -// 15.3.5.3 -func (self *_object) hasInstance(of Value) bool { - if !self.isCall() { +// 15.3.5.3. +func (o *object) hasInstance(of Value) bool { + if !o.isCall() { // We should not have a hasInstance method - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError("Object.hasInstance not callable")) } if !of.IsObject() { return false } - prototype := self.get("prototype") + prototype := o.get("prototype") if !prototype.IsObject() { - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError("Object.hasInstance prototype %q is not an object", prototype)) } - prototypeObject := prototype._object() + prototypeObject := prototype.object() - value := of._object().prototype + value := of.object().prototype for value != nil { if value == prototypeObject { return true @@ -280,61 +268,55 @@ func (self *_object) hasInstance(of Value) bool { return false } -// ============ // -// FunctionCall // -// ============ // - // FunctionCall is an encapsulation of a JavaScript function call. type FunctionCall struct { - runtime *_runtime - _thisObject *_object - eval bool // This call is a direct call to eval - This Value - ArgumentList []Value + runtime *runtime + thisObj *object Otto *Otto + ArgumentList []Value + eval bool } // Argument will return the value of the argument at the given index. // // If no such argument exists, undefined is returned. -func (self FunctionCall) Argument(index int) Value { - return valueOfArrayIndex(self.ArgumentList, index) +func (f FunctionCall) Argument(index int) Value { + return valueOfArrayIndex(f.ArgumentList, index) } -func (self FunctionCall) getArgument(index int) (Value, bool) { - return getValueOfArrayIndex(self.ArgumentList, index) +func (f FunctionCall) getArgument(index int) (Value, bool) { + return getValueOfArrayIndex(f.ArgumentList, index) } -func (self FunctionCall) slice(index int) []Value { - if index < len(self.ArgumentList) { - return self.ArgumentList[index:] +func (f FunctionCall) slice(index int) []Value { + if index < len(f.ArgumentList) { + return f.ArgumentList[index:] } return []Value{} } -func (self *FunctionCall) thisObject() *_object { - if self._thisObject == nil { - this := self.This.resolve() // FIXME Is this right? - self._thisObject = self.runtime.toObject(this) +func (f *FunctionCall) thisObject() *object { + if f.thisObj == nil { + this := f.This.resolve() // FIXME Is this right? + f.thisObj = f.runtime.toObject(this) } - return self._thisObject + return f.thisObj } -func (self *FunctionCall) thisClassObject(class string) *_object { - thisObject := self.thisObject() - if thisObject.class != class { - panic(self.runtime.panicTypeError()) +func (f *FunctionCall) thisClassObject(class string) *object { + if o := f.thisObject(); o.class != class { + panic(f.runtime.panicTypeError("Function.Class %s != %s", o.class, class)) } - return self._thisObject + return f.thisObj } -func (self FunctionCall) toObject(value Value) *_object { - return self.runtime.toObject(value) +func (f FunctionCall) toObject(value Value) *object { + return f.runtime.toObject(value) } // CallerLocation will return file location information (file:line:pos) where this function is being called. -func (self FunctionCall) CallerLocation() string { +func (f FunctionCall) CallerLocation() string { // see error.go for location() - return self.runtime.scope.outer.frame.location() + return f.runtime.scope.outer.frame.location() } diff --git a/vendor/github.com/robertkrimen/otto/type_go_array.go b/vendor/github.com/robertkrimen/otto/type_go_array.go index 13a0b10f2..397c017ff 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_array.go +++ b/vendor/github.com/robertkrimen/otto/type_go_array.go @@ -5,48 +5,64 @@ import ( "strconv" ) -func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "GoArray" - self.objectClass = _classGoArray - self.value = _newGoArrayObject(value) - return self +func (rt *runtime) newGoArrayObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classGoArrayName + o.objectClass = classGoArray + o.value = newGoArrayObject(value) + return o } -type _goArrayObject struct { +type goArrayObject struct { value reflect.Value writable bool - propertyMode _propertyMode + propertyMode propertyMode } -func _newGoArrayObject(value reflect.Value) *_goArrayObject { - writable := value.Kind() == reflect.Ptr // The Array is addressable (like a Slice) - mode := _propertyMode(0010) +func newGoArrayObject(value reflect.Value) *goArrayObject { + writable := value.Kind() == reflect.Ptr || value.CanSet() // The Array is addressable (like a Slice) + mode := propertyMode(0o010) if writable { - mode = 0110 + mode = 0o110 } - self := &_goArrayObject{ + + return &goArrayObject{ value: value, writable: writable, propertyMode: mode, } - return self } -func (self _goArrayObject) getValue(index int64) (reflect.Value, bool) { - value := reflect.Indirect(self.value) +func (o goArrayObject) getValue(name string) (reflect.Value, bool) { //nolint:unused + if index, err := strconv.ParseInt(name, 10, 64); err != nil { + v, ok := o.getValueIndex(index) + if ok { + return v, ok + } + } + + if m := o.value.MethodByName(name); m.IsValid() { + return m, true + } + + return reflect.Value{}, false +} + +func (o goArrayObject) getValueIndex(index int64) (reflect.Value, bool) { + value := reflect.Indirect(o.value) if index < int64(value.Len()) { return value.Index(int(index)), true } + return reflect.Value{}, false } -func (self _goArrayObject) setValue(index int64, value Value) bool { - indexValue, exists := self.getValue(index) +func (o goArrayObject) setValue(index int64, value Value) bool { + indexValue, exists := o.getValueIndex(index) if !exists { return false } - reflectValue, err := value.toReflectValue(reflect.Indirect(self.value).Type().Elem().Kind()) + reflectValue, err := value.toReflectValue(reflect.Indirect(o.value).Type().Elem()) if err != nil { panic(err) } @@ -54,81 +70,87 @@ func (self _goArrayObject) setValue(index int64, value Value) bool { return true } -func goArrayGetOwnProperty(self *_object, name string) *_property { +func goArrayGetOwnProperty(obj *object, name string) *property { // length - if name == "length" { - return &_property{ - value: toValue(reflect.Indirect(self.value.(*_goArrayObject).value).Len()), + if name == propertyLength { + return &property{ + value: toValue(reflect.Indirect(obj.value.(*goArrayObject).value).Len()), mode: 0, } } // .0, .1, .2, ... - index := stringToArrayIndex(name) - if index >= 0 { - object := self.value.(*_goArrayObject) + if index := stringToArrayIndex(name); index >= 0 { + goObj := obj.value.(*goArrayObject) value := Value{} - reflectValue, exists := object.getValue(index) + reflectValue, exists := goObj.getValueIndex(index) if exists { - value = self.runtime.toValue(reflectValue.Interface()) + value = obj.runtime.toValue(reflectValue.Interface()) } - return &_property{ + return &property{ value: value, - mode: object.propertyMode, + mode: goObj.propertyMode, + } + } + + if method := obj.value.(*goArrayObject).value.MethodByName(name); method.IsValid() { + return &property{ + obj.runtime.toValue(method.Interface()), + 0o110, } } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } -func goArrayEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goArrayObject) +func goArrayEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goArrayObject) // .0, .1, .2, ... - for index, length := 0, object.value.Len(); index < length; index++ { + for index, length := 0, goObj.value.Len(); index < length; index++ { name := strconv.FormatInt(int64(index), 10) if !each(name) { return } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - if name == "length" { - return self.runtime.typeErrorResult(throw) +func goArrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if name == propertyLength { + return obj.runtime.typeErrorResult(throw) } else if index := stringToArrayIndex(name); index >= 0 { - object := self.value.(*_goArrayObject) - if object.writable { - if self.value.(*_goArrayObject).setValue(index, descriptor.value.(Value)) { + goObj := obj.value.(*goArrayObject) + if goObj.writable { + if obj.value.(*goArrayObject).setValue(index, descriptor.value.(Value)) { return true } } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func goArrayDelete(self *_object, name string, throw bool) bool { +func goArrayDelete(obj *object, name string, throw bool) bool { // length - if name == "length" { - return self.runtime.typeErrorResult(throw) + if name == propertyLength { + return obj.runtime.typeErrorResult(throw) } // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - object := self.value.(*_goArrayObject) - if object.writable { - indexValue, exists := object.getValue(index) + goObj := obj.value.(*goArrayObject) + if goObj.writable { + indexValue, exists := goObj.getValueIndex(index) if exists { - indexValue.Set(reflect.Zero(reflect.Indirect(object.value).Type().Elem())) + indexValue.Set(reflect.Zero(reflect.Indirect(goObj.value).Type().Elem())) return true } } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return self.delete(name, throw) + return obj.delete(name, throw) } diff --git a/vendor/github.com/robertkrimen/otto/type_go_map.go b/vendor/github.com/robertkrimen/otto/type_go_map.go index 41b9ac0de..d4953bfde 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_map.go +++ b/vendor/github.com/robertkrimen/otto/type_go_map.go @@ -4,69 +4,82 @@ import ( "reflect" ) -func (runtime *_runtime) newGoMapObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "Object" // TODO Should this be something else? - self.objectClass = _classGoMap - self.value = _newGoMapObject(value) - return self +func (rt *runtime) newGoMapObject(value reflect.Value) *object { + obj := rt.newObject() + obj.class = classObjectName // TODO Should this be something else? + obj.objectClass = classGoMap + obj.value = newGoMapObject(value) + return obj } -type _goMapObject struct { +type goMapObject struct { + keyType reflect.Type + valueType reflect.Type value reflect.Value - keyKind reflect.Kind - valueKind reflect.Kind } -func _newGoMapObject(value reflect.Value) *_goMapObject { +func newGoMapObject(value reflect.Value) *goMapObject { if value.Kind() != reflect.Map { dbgf("%/panic//%@: %v != reflect.Map", value.Kind()) } - self := &_goMapObject{ + return &goMapObject{ value: value, - keyKind: value.Type().Key().Kind(), - valueKind: value.Type().Elem().Kind(), + keyType: value.Type().Key(), + valueType: value.Type().Elem(), } - return self } -func (self _goMapObject) toKey(name string) reflect.Value { - reflectValue, err := stringToReflectValue(name, self.keyKind) +func (o goMapObject) toKey(name string) reflect.Value { + reflectValue, err := stringToReflectValue(name, o.keyType.Kind()) if err != nil { panic(err) } return reflectValue } -func (self _goMapObject) toValue(value Value) reflect.Value { - reflectValue, err := value.toReflectValue(self.valueKind) +func (o goMapObject) toValue(value Value) reflect.Value { + reflectValue, err := value.toReflectValue(o.valueType) if err != nil { panic(err) } return reflectValue } -func goMapGetOwnProperty(self *_object, name string) *_property { - object := self.value.(*_goMapObject) - value := object.value.MapIndex(object.toKey(name)) +func goMapGetOwnProperty(obj *object, name string) *property { + goObj := obj.value.(*goMapObject) + + // an error here means that the key referenced by `name` could not possibly + // be a property of this object, so it should be safe to ignore this error + // + // TODO: figure out if any cases from + // https://go.dev/ref/spec#Comparison_operators meet the criteria of 1) + // being possible to represent as a string, 2) being possible to reconstruct + // from a string, and 3) having a meaningful failure case in this context + // other than "key does not exist" + key, err := stringToReflectValue(name, goObj.keyType.Kind()) + if err != nil { + return nil + } + + value := goObj.value.MapIndex(key) if value.IsValid() { - return &_property{self.runtime.toValue(value.Interface()), 0111} + return &property{obj.runtime.toValue(value.Interface()), 0o111} } // Other methods - if method := self.value.(*_goMapObject).value.MethodByName(name); (method != reflect.Value{}) { - return &_property{ - value: self.runtime.toValue(method.Interface()), - mode: 0110, + if method := obj.value.(*goMapObject).value.MethodByName(name); method.IsValid() { + return &property{ + value: obj.runtime.toValue(method.Interface()), + mode: 0o110, } } return nil } -func goMapEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goMapObject) - keys := object.value.MapKeys() +func goMapEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goMapObject) + keys := goObj.value.MapKeys() for _, key := range keys { if !each(toValue(key).String()) { return @@ -74,22 +87,22 @@ func goMapEnumerate(self *_object, all bool, each func(string) bool) { } } -func goMapDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - object := self.value.(*_goMapObject) +func goMapDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + goObj := obj.value.(*goMapObject) // TODO ...or 0222 - if descriptor.mode != 0111 { - return self.runtime.typeErrorResult(throw) + if descriptor.mode != 0o111 { + return obj.runtime.typeErrorResult(throw) } if !descriptor.isDataDescriptor() { - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - object.value.SetMapIndex(object.toKey(name), object.toValue(descriptor.value.(Value))) + goObj.value.SetMapIndex(goObj.toKey(name), goObj.toValue(descriptor.value.(Value))) return true } -func goMapDelete(self *_object, name string, throw bool) bool { - object := self.value.(*_goMapObject) - object.value.SetMapIndex(object.toKey(name), reflect.Value{}) +func goMapDelete(obj *object, name string, throw bool) bool { + goObj := obj.value.(*goMapObject) + goObj.value.SetMapIndex(goObj.toKey(name), reflect.Value{}) // FIXME return true } diff --git a/vendor/github.com/robertkrimen/otto/type_go_slice.go b/vendor/github.com/robertkrimen/otto/type_go_slice.go index 78c69e684..e9acfa335 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_slice.go +++ b/vendor/github.com/robertkrimen/otto/type_go_slice.go @@ -5,122 +5,149 @@ import ( "strconv" ) -func (runtime *_runtime) newGoSliceObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "GoArray" // TODO GoSlice? - self.objectClass = _classGoSlice - self.value = _newGoSliceObject(value) - return self +func (rt *runtime) newGoSliceObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classGoSliceName + o.objectClass = classGoSlice + o.value = newGoSliceObject(value) + return o } -type _goSliceObject struct { +type goSliceObject struct { value reflect.Value } -func _newGoSliceObject(value reflect.Value) *_goSliceObject { - self := &_goSliceObject{ +func newGoSliceObject(value reflect.Value) *goSliceObject { + return &goSliceObject{ value: value, } - return self } -func (self _goSliceObject) getValue(index int64) (reflect.Value, bool) { - if index < int64(self.value.Len()) { - return self.value.Index(int(index)), true +func (o goSliceObject) getValue(index int64) (reflect.Value, bool) { + if index < int64(o.value.Len()) { + return o.value.Index(int(index)), true } return reflect.Value{}, false } -func (self _goSliceObject) setValue(index int64, value Value) bool { - indexValue, exists := self.getValue(index) - if !exists { - return false +func (o *goSliceObject) setLength(value Value) { + want, err := value.ToInteger() + if err != nil { + panic(err) } - reflectValue, err := value.toReflectValue(self.value.Type().Elem().Kind()) + + wantInt := int(want) + switch { + case wantInt == o.value.Len(): + // No change needed. + case wantInt < o.value.Cap(): + // Fits in current capacity. + o.value.SetLen(wantInt) + default: + // Needs expanding. + newSlice := reflect.MakeSlice(o.value.Type(), wantInt, wantInt) + reflect.Copy(newSlice, o.value) + o.value = newSlice + } +} + +func (o *goSliceObject) setValue(index int64, value Value) bool { + reflectValue, err := value.toReflectValue(o.value.Type().Elem()) if err != nil { panic(err) } + + indexValue, exists := o.getValue(index) + if !exists { + if int64(o.value.Len()) == index { + // Trying to append e.g. slice.push(...), allow it. + o.value = reflect.Append(o.value, reflectValue) + return true + } + return false + } + indexValue.Set(reflectValue) return true } -func goSliceGetOwnProperty(self *_object, name string) *_property { +func goSliceGetOwnProperty(obj *object, name string) *property { // length - if name == "length" { - return &_property{ - value: toValue(self.value.(*_goSliceObject).value.Len()), - mode: 0, + if name == propertyLength { + return &property{ + value: toValue(obj.value.(*goSliceObject).value.Len()), + mode: 0o110, } } // .0, .1, .2, ... - index := stringToArrayIndex(name) - if index >= 0 { + if index := stringToArrayIndex(name); index >= 0 { value := Value{} - reflectValue, exists := self.value.(*_goSliceObject).getValue(index) + reflectValue, exists := obj.value.(*goSliceObject).getValue(index) if exists { - value = self.runtime.toValue(reflectValue.Interface()) + value = obj.runtime.toValue(reflectValue.Interface()) } - return &_property{ + return &property{ value: value, - mode: 0110, + mode: 0o110, } } // Other methods - if method := self.value.(*_goSliceObject).value.MethodByName(name); (method != reflect.Value{}) { - return &_property{ - value: self.runtime.toValue(method.Interface()), - mode: 0110, + if method := obj.value.(*goSliceObject).value.MethodByName(name); method.IsValid() { + return &property{ + value: obj.runtime.toValue(method.Interface()), + mode: 0o110, } } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } -func goSliceEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goSliceObject) +func goSliceEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goSliceObject) // .0, .1, .2, ... - for index, length := 0, object.value.Len(); index < length; index++ { + for index, length := 0, goObj.value.Len(); index < length; index++ { name := strconv.FormatInt(int64(index), 10) if !each(name) { return } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goSliceDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - if name == "length" { - return self.runtime.typeErrorResult(throw) +func goSliceDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if name == propertyLength { + obj.value.(*goSliceObject).setLength(descriptor.value.(Value)) + return true } else if index := stringToArrayIndex(name); index >= 0 { - if self.value.(*_goSliceObject).setValue(index, descriptor.value.(Value)) { + if obj.value.(*goSliceObject).setValue(index, descriptor.value.(Value)) { return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func goSliceDelete(self *_object, name string, throw bool) bool { +func goSliceDelete(obj *object, name string, throw bool) bool { // length - if name == "length" { - return self.runtime.typeErrorResult(throw) + if name == propertyLength { + return obj.runtime.typeErrorResult(throw) } // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - object := self.value.(*_goSliceObject) - indexValue, exists := object.getValue(index) + goObj := obj.value.(*goSliceObject) + indexValue, exists := goObj.getValue(index) if exists { - indexValue.Set(reflect.Zero(object.value.Type().Elem())) + indexValue.Set(reflect.Zero(goObj.value.Type().Elem())) return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return self.delete(name, throw) + return obj.delete(name, throw) } diff --git a/vendor/github.com/robertkrimen/otto/type_go_struct.go b/vendor/github.com/robertkrimen/otto/type_go_struct.go index 608ac6660..a61de82d2 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_struct.go +++ b/vendor/github.com/robertkrimen/otto/type_go_struct.go @@ -13,36 +13,39 @@ import ( // 1. Creating a new struct every time // 2. Creating an addressable? struct in the constructor -func (runtime *_runtime) newGoStructObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "Object" // TODO Should this be something else? - self.objectClass = _classGoStruct - self.value = _newGoStructObject(value) - return self +func (rt *runtime) newGoStructObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classObjectName // TODO Should this be something else? + o.objectClass = classGoStruct + o.value = newGoStructObject(value) + return o } -type _goStructObject struct { +type goStructObject struct { value reflect.Value } -func _newGoStructObject(value reflect.Value) *_goStructObject { +func newGoStructObject(value reflect.Value) *goStructObject { if reflect.Indirect(value).Kind() != reflect.Struct { dbgf("%/panic//%@: %v != reflect.Struct", value.Kind()) } - self := &_goStructObject{ + return &goStructObject{ value: value, } - return self } -func (self _goStructObject) getValue(name string) reflect.Value { +func (o goStructObject) getValue(name string) reflect.Value { + if idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) > 0 { + return reflect.Indirect(o.value).FieldByIndex(idx) + } + if validGoStructName(name) { - // Do not reveal hidden or unexported fields - if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) { + // Do not reveal hidden or unexported fields. + if field := reflect.Indirect(o.value).FieldByName(name); field.IsValid() { return field } - if method := self.value.MethodByName(name); (method != reflect.Value{}) { + if method := o.value.MethodByName(name); method.IsValid() { return method } } @@ -50,37 +53,37 @@ func (self _goStructObject) getValue(name string) reflect.Value { return reflect.Value{} } -func (self _goStructObject) field(name string) (reflect.StructField, bool) { - return reflect.Indirect(self.value).Type().FieldByName(name) +func (o goStructObject) fieldIndex(name string) []int { //nolint:unused + return fieldIndexByName(reflect.Indirect(o.value).Type(), name) } -func (self _goStructObject) method(name string) (reflect.Method, bool) { - return reflect.Indirect(self.value).Type().MethodByName(name) +func (o goStructObject) method(name string) (reflect.Method, bool) { //nolint:unused + return reflect.Indirect(o.value).Type().MethodByName(name) } -func (self _goStructObject) setValue(name string, value Value) bool { - field, exists := self.field(name) - if !exists { +func (o goStructObject) setValue(rt *runtime, name string, value Value) bool { + if idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) == 0 { return false } - fieldValue := self.getValue(name) - reflectValue, err := value.toReflectValue(field.Type.Kind()) + + fieldValue := o.getValue(name) + converted, err := rt.convertCallParameter(value, fieldValue.Type()) if err != nil { - panic(err) + panic(rt.panicTypeError("Object.setValue convertCallParameter: %s", err)) } - fieldValue.Set(reflectValue) + fieldValue.Set(converted) return true } -func goStructGetOwnProperty(self *_object, name string) *_property { - object := self.value.(*_goStructObject) - value := object.getValue(name) +func goStructGetOwnProperty(obj *object, name string) *property { + goObj := obj.value.(*goStructObject) + value := goObj.getValue(name) if value.IsValid() { - return &_property{self.runtime.toValue(value.Interface()), 0110} + return &property{obj.runtime.toValue(value), 0o110} } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } func validGoStructName(name string) bool { @@ -90,12 +93,12 @@ func validGoStructName(name string) bool { return 'A' <= name[0] && name[0] <= 'Z' // TODO What about Unicode? } -func goStructEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goStructObject) +func goStructEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goStructObject) // Enumerate fields - for index := 0; index < reflect.Indirect(object.value).NumField(); index++ { - name := reflect.Indirect(object.value).Type().Field(index).Name + for index := range reflect.Indirect(goObj.value).NumField() { + name := reflect.Indirect(goObj.value).Type().Field(index).Name if validGoStructName(name) { if !each(name) { return @@ -104,8 +107,8 @@ func goStructEnumerate(self *_object, all bool, each func(string) bool) { } // Enumerate methods - for index := 0; index < object.value.NumMethod(); index++ { - name := object.value.Type().Method(index).Name + for index := range goObj.value.NumMethod() { + name := goObj.value.Type().Method(index).Name if validGoStructName(name) { if !each(name) { return @@ -113,34 +116,31 @@ func goStructEnumerate(self *_object, all bool, each func(string) bool) { } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goStructCanPut(self *_object, name string) bool { - object := self.value.(*_goStructObject) - value := object.getValue(name) +func goStructCanPut(obj *object, name string) bool { + goObj := obj.value.(*goStructObject) + value := goObj.getValue(name) if value.IsValid() { return true } - return objectCanPut(self, name) + return objectCanPut(obj, name) } -func goStructPut(self *_object, name string, value Value, throw bool) { - object := self.value.(*_goStructObject) - if object.setValue(name, value) { +func goStructPut(obj *object, name string, value Value, throw bool) { + goObj := obj.value.(*goStructObject) + if goObj.setValue(obj.runtime, name, value) { return } - objectPut(self, name, value, throw) + objectPut(obj, name, value, throw) } -func goStructMarshalJSON(self *_object) json.Marshaler { - object := self.value.(*_goStructObject) - goValue := reflect.Indirect(object.value).Interface() - switch marshaler := goValue.(type) { - case json.Marshaler: - return marshaler - } - return nil +func goStructMarshalJSON(obj *object) json.Marshaler { + goObj := obj.value.(*goStructObject) + goValue := reflect.Indirect(goObj.value).Interface() + marshaler, _ := goValue.(json.Marshaler) + return marshaler } diff --git a/vendor/github.com/robertkrimen/otto/type_number.go b/vendor/github.com/robertkrimen/otto/type_number.go index 28de4444c..4201c9268 100644 --- a/vendor/github.com/robertkrimen/otto/type_number.go +++ b/vendor/github.com/robertkrimen/otto/type_number.go @@ -1,5 +1,5 @@ package otto -func (runtime *_runtime) newNumberObject(value Value) *_object { - return runtime.newPrimitiveObject("Number", value.numberValue()) +func (rt *runtime) newNumberObject(value Value) *object { + return rt.newPrimitiveObject(classNumberName, value.numberValue()) } diff --git a/vendor/github.com/robertkrimen/otto/type_reference.go b/vendor/github.com/robertkrimen/otto/type_reference.go index fd770c6f4..1d2d0d3e3 100644 --- a/vendor/github.com/robertkrimen/otto/type_reference.go +++ b/vendor/github.com/robertkrimen/otto/type_reference.go @@ -1,103 +1,93 @@ package otto -type _reference interface { - invalid() bool // IsUnresolvableReference - getValue() Value // getValue - putValue(Value) string // PutValue +type referencer interface { + invalid() bool // IsUnresolvableReference + getValue() Value // getValue + putValue(value Value) string // PutValue delete() bool } // PropertyReference -type _propertyReference struct { +type propertyReference struct { + base *object + runtime *runtime name string + at at strict bool - base *_object - runtime *_runtime - at _at } -func newPropertyReference(rt *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { - return &_propertyReference{ +func newPropertyReference(rt *runtime, base *object, name string, strict bool, atv at) *propertyReference { + return &propertyReference{ runtime: rt, name: name, strict: strict, base: base, - at: at, + at: atv, } } -func (self *_propertyReference) invalid() bool { - return self.base == nil +func (pr *propertyReference) invalid() bool { + return pr.base == nil } -func (self *_propertyReference) getValue() Value { - if self.base == nil { - panic(self.runtime.panicReferenceError("'%s' is not defined", self.name, self.at)) +func (pr *propertyReference) getValue() Value { + if pr.base == nil { + panic(pr.runtime.panicReferenceError("'%s' is not defined", pr.name, pr.at)) } - return self.base.get(self.name) + return pr.base.get(pr.name) } -func (self *_propertyReference) putValue(value Value) string { - if self.base == nil { - return self.name +func (pr *propertyReference) putValue(value Value) string { + if pr.base == nil { + return pr.name } - self.base.put(self.name, value, self.strict) + pr.base.put(pr.name, value, pr.strict) return "" } -func (self *_propertyReference) delete() bool { - if self.base == nil { +func (pr *propertyReference) delete() bool { + if pr.base == nil { // TODO Throw an error if strict return true } - return self.base.delete(self.name, self.strict) + return pr.base.delete(pr.name, pr.strict) } -// ArgumentReference - -func newArgumentReference(runtime *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { - if base == nil { - panic(hereBeDragons()) - } - return newPropertyReference(runtime, base, name, strict, at) -} - -type _stashReference struct { +type stashReference struct { + base stasher name string strict bool - base _stash } -func (self *_stashReference) invalid() bool { +func (sr *stashReference) invalid() bool { return false // The base (an environment) will never be nil } -func (self *_stashReference) getValue() Value { - return self.base.getBinding(self.name, self.strict) +func (sr *stashReference) getValue() Value { + return sr.base.getBinding(sr.name, sr.strict) } -func (self *_stashReference) putValue(value Value) string { - self.base.setValue(self.name, value, self.strict) +func (sr *stashReference) putValue(value Value) string { + sr.base.setValue(sr.name, value, sr.strict) return "" } -func (self *_stashReference) delete() bool { - if self.base == nil { +func (sr *stashReference) delete() bool { + if sr.base == nil { // This should never be reached, but just in case return false } - return self.base.deleteBinding(self.name) + return sr.base.deleteBinding(sr.name) } -// getIdentifierReference - -func getIdentifierReference(runtime *_runtime, stash _stash, name string, strict bool, at _at) _reference { +// getIdentifierReference. +func getIdentifierReference(rt *runtime, stash stasher, name string, strict bool, atv at) referencer { if stash == nil { - return newPropertyReference(runtime, nil, name, strict, at) + return newPropertyReference(rt, nil, name, strict, atv) } if stash.hasBinding(name) { - return stash.newReference(name, strict, at) + return stash.newReference(name, strict, atv) } - return getIdentifierReference(runtime, stash.outer(), name, strict, at) + return getIdentifierReference(rt, stash.outer(), name, strict, atv) } diff --git a/vendor/github.com/robertkrimen/otto/type_regexp.go b/vendor/github.com/robertkrimen/otto/type_regexp.go index 57fe31640..c1370e64e 100644 --- a/vendor/github.com/robertkrimen/otto/type_regexp.go +++ b/vendor/github.com/robertkrimen/otto/type_regexp.go @@ -3,23 +3,22 @@ package otto import ( "fmt" "regexp" - "unicode/utf8" "github.com/robertkrimen/otto/parser" ) -type _regExpObject struct { +type regExpObject struct { regularExpression *regexp.Regexp + source string + flags string global bool ignoreCase bool multiline bool - source string - flags string } -func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object { - self := runtime.newObject() - self.class = "RegExp" +func (rt *runtime) newRegExpObject(pattern string, flags string) *object { + o := rt.newObject() + o.class = classRegExpName global := false ignoreCase := false @@ -32,18 +31,18 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object switch chr { case 'g': if global { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } global = true case 'm': if multiline { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } multiline = true re2flags += "m" case 'i': if ignoreCase { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } ignoreCase = true re2flags += "i" @@ -52,7 +51,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object re2pattern, err := parser.TransformRegExp(pattern) if err != nil { - panic(runtime.panicTypeError("Invalid regular expression: %s", err.Error())) + panic(rt.panicTypeError("Invalid regular expression: %s", err.Error())) } if len(re2flags) > 0 { re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern) @@ -60,10 +59,10 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object regularExpression, err := regexp.Compile(re2pattern) if err != nil { - panic(runtime.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) + panic(rt.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) } - self.value = _regExpObject{ + o.value = regExpObject{ regularExpression: regularExpression, global: global, ignoreCase: ignoreCase, @@ -71,21 +70,21 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object source: pattern, flags: flags, } - self.defineProperty("global", toValue_bool(global), 0, false) - self.defineProperty("ignoreCase", toValue_bool(ignoreCase), 0, false) - self.defineProperty("multiline", toValue_bool(multiline), 0, false) - self.defineProperty("lastIndex", toValue_int(0), 0100, false) - self.defineProperty("source", toValue_string(pattern), 0, false) - return self + o.defineProperty("global", boolValue(global), 0, false) + o.defineProperty("ignoreCase", boolValue(ignoreCase), 0, false) + o.defineProperty("multiline", boolValue(multiline), 0, false) + o.defineProperty("lastIndex", intValue(0), 0o100, false) + o.defineProperty("source", stringValue(pattern), 0, false) + return o } -func (self *_object) regExpValue() _regExpObject { - value, _ := self.value.(_regExpObject) +func (o *object) regExpValue() regExpObject { + value, _ := o.value.(regExpObject) return value } -func execRegExp(this *_object, target string) (match bool, result []int) { - if this.class != "RegExp" { +func execRegExp(this *object, target string) (bool, []int) { + if this.class != classRegExpName { panic(this.runtime.panicTypeError("Calling RegExp.exec on a non-RegExp object")) } lastIndex := this.get("lastIndex").number().int64 @@ -94,53 +93,52 @@ func execRegExp(this *_object, target string) (match bool, result []int) { if !global { index = 0 } + + var result []int if 0 > index || index > int64(len(target)) { } else { result = this.regExpValue().regularExpression.FindStringSubmatchIndex(target[index:]) } + if result == nil { - //this.defineProperty("lastIndex", toValue_(0), 0111, true) - this.put("lastIndex", toValue_int(0), true) - return // !match + this.put("lastIndex", intValue(0), true) + return false, nil } - match = true + startIndex := index endIndex := int(lastIndex) + result[1] // We do this shift here because the .FindStringSubmatchIndex above // was done on a local subordinate slice of the string, not the whole string - for index, _ := range result { - result[index] += int(startIndex) + for index, offset := range result { + if offset != -1 { + result[index] += int(startIndex) + } } if global { - //this.defineProperty("lastIndex", toValue_(endIndex), 0111, true) - this.put("lastIndex", toValue_int(endIndex), true) + this.put("lastIndex", intValue(endIndex), true) } - return // match + + return true, result } -func execResultToArray(runtime *_runtime, target string, result []int) *_object { +func execResultToArray(rt *runtime, target string, result []int) *object { captureCount := len(result) / 2 valueArray := make([]Value, captureCount) - for index := 0; index < captureCount; index++ { + for index := range captureCount { offset := 2 * index if result[offset] != -1 { - valueArray[index] = toValue_string(target[result[offset]:result[offset+1]]) + valueArray[index] = stringValue(target[result[offset]:result[offset+1]]) } else { valueArray[index] = Value{} } } matchIndex := result[0] if matchIndex != 0 { - matchIndex = 0 - // Find the rune index in the string, not the byte index - for index := 0; index < result[0]; { - _, size := utf8.DecodeRuneInString(target[index:]) - matchIndex += 1 - index += size - } + // Find the utf16 index in the string, not the byte index. + matchIndex = utf16Length(target[:matchIndex]) } - match := runtime.newArrayOf(valueArray) - match.defineProperty("input", toValue_string(target), 0111, false) - match.defineProperty("index", toValue_int(matchIndex), 0111, false) + match := rt.newArrayOf(valueArray) + match.defineProperty("input", stringValue(target), 0o111, false) + match.defineProperty("index", intValue(matchIndex), 0o111, false) return match } diff --git a/vendor/github.com/robertkrimen/otto/type_string.go b/vendor/github.com/robertkrimen/otto/type_string.go index ef3afa42b..252c1ae63 100644 --- a/vendor/github.com/robertkrimen/otto/type_string.go +++ b/vendor/github.com/robertkrimen/otto/type_string.go @@ -2,110 +2,112 @@ package otto import ( "strconv" + "unicode/utf16" "unicode/utf8" ) -type _stringObject interface { +type stringObjecter interface { Length() int - At(int) rune + At(at int) rune String() string } -type _stringASCII string +type stringASCII string -func (str _stringASCII) Length() int { +func (str stringASCII) Length() int { return len(str) } -func (str _stringASCII) At(at int) rune { +func (str stringASCII) At(at int) rune { return rune(str[at]) } -func (str _stringASCII) String() string { +func (str stringASCII) String() string { return string(str) } -type _stringWide struct { - string string - length int - runes []rune +type stringWide struct { + string string + value16 []uint16 } -func (str _stringWide) Length() int { - return str.length +func (str stringWide) Length() int { + if str.value16 == nil { + str.value16 = utf16.Encode([]rune(str.string)) + } + return len(str.value16) } -func (str _stringWide) At(at int) rune { - if str.runes == nil { - str.runes = []rune(str.string) +func (str stringWide) At(at int) rune { + if str.value16 == nil { + str.value16 = utf16.Encode([]rune(str.string)) } - return str.runes[at] + return rune(str.value16[at]) } -func (str _stringWide) String() string { +func (str stringWide) String() string { return str.string } -func _newStringObject(str string) _stringObject { - for i := 0; i < len(str); i++ { +func newStringObject(str string) stringObjecter { + for i := range len(str) { if str[i] >= utf8.RuneSelf { goto wide } } - return _stringASCII(str) + return stringASCII(str) wide: - return &_stringWide{ + return &stringWide{ string: str, - length: utf8.RuneCountInString(str), } } -func stringAt(str _stringObject, index int) rune { +func stringAt(str stringObjecter, index int) rune { if 0 <= index && index < str.Length() { return str.At(index) } return utf8.RuneError } -func (runtime *_runtime) newStringObject(value Value) *_object { - str := _newStringObject(value.string()) +func (rt *runtime) newStringObject(value Value) *object { + str := newStringObject(value.string()) - self := runtime.newClassObject("String") - self.defineProperty("length", toValue_int(str.Length()), 0, false) - self.objectClass = _classString - self.value = str - return self + obj := rt.newClassObject(classStringName) + obj.defineProperty(propertyLength, intValue(str.Length()), 0, false) + obj.objectClass = classString + obj.value = str + return obj } -func (self *_object) stringValue() _stringObject { - if str, ok := self.value.(_stringObject); ok { +func (o *object) stringValue() stringObjecter { + if str, ok := o.value.(stringObjecter); ok { return str } return nil } -func stringEnumerate(self *_object, all bool, each func(string) bool) { - if str := self.stringValue(); str != nil { +func stringEnumerate(obj *object, all bool, each func(string) bool) { + if str := obj.stringValue(); str != nil { length := str.Length() - for index := 0; index < length; index++ { + for index := range length { if !each(strconv.FormatInt(int64(index), 10)) { return } } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func stringGetOwnProperty(self *_object, name string) *_property { - if property := objectGetOwnProperty(self, name); property != nil { - return property +func stringGetOwnProperty(obj *object, name string) *property { + if prop := objectGetOwnProperty(obj, name); prop != nil { + return prop } // TODO Test a string of length >= +int32 + 1? if index := stringToArrayIndex(name); index >= 0 { - if chr := stringAt(self.stringValue(), int(index)); chr != utf8.RuneError { - return &_property{toValue_string(string(chr)), 0} + if chr := stringAt(obj.stringValue(), int(index)); chr != utf8.RuneError { + return &property{stringValue(string(chr)), 0} } } return nil diff --git a/vendor/github.com/robertkrimen/otto/value.go b/vendor/github.com/robertkrimen/otto/value.go index 90c140604..183c23171 100644 --- a/vendor/github.com/robertkrimen/otto/value.go +++ b/vendor/github.com/robertkrimen/otto/value.go @@ -1,6 +1,7 @@ package otto import ( + "encoding/json" "fmt" "math" "reflect" @@ -8,17 +9,17 @@ import ( "unicode/utf16" ) -type _valueKind int +type valueKind int const ( - valueUndefined _valueKind = iota + valueUndefined valueKind = iota valueNull valueNumber valueString valueBoolean valueObject - // These are invalid outside of the runtime + // These are invalid outside of the runtime. valueEmpty valueResult valueReference @@ -26,12 +27,12 @@ const ( // Value is the representation of a JavaScript value. type Value struct { - kind _valueKind value interface{} + kind valueKind } -func (value Value) safe() bool { - return value.kind < valueEmpty +func (v Value) safe() bool { + return v.kind < valueEmpty } var ( @@ -53,8 +54,8 @@ func ToValue(value interface{}) (Value, error) { return result, err } -func (value Value) isEmpty() bool { - return value.kind == valueEmpty +func (v Value) isEmpty() bool { + return v.kind == valueEmpty } // Undefined @@ -65,13 +66,13 @@ func UndefinedValue() Value { } // IsDefined will return false if the value is undefined, and true otherwise. -func (value Value) IsDefined() bool { - return value.kind != valueUndefined +func (v Value) IsDefined() bool { + return v.kind != valueUndefined } // IsUndefined will return true if the value is undefined, and false otherwise. -func (value Value) IsUndefined() bool { - return value.kind == valueUndefined +func (v Value) IsUndefined() bool { + return v.kind == valueUndefined } // NullValue will return a Value representing null. @@ -80,91 +81,79 @@ func NullValue() Value { } // IsNull will return true if the value is null, and false otherwise. -func (value Value) IsNull() bool { - return value.kind == valueNull +func (v Value) IsNull() bool { + return v.kind == valueNull } // --- -func (value Value) isCallable() bool { - switch value := value.value.(type) { - case *_object: - return value.isCall() - } - return false +func (v Value) isCallable() bool { + o, ok := v.value.(*object) + return ok && o.isCall() } // Call the value as a function with the given this value and argument list and // return the result of invocation. It is essentially equivalent to: // -// value.apply(thisValue, argumentList) +// value.apply(thisValue, argumentList) // // An undefined value and an error will result if: // -// 1. There is an error during conversion of the argument list -// 2. The value is not actually a function -// 3. An (uncaught) exception is thrown -// -func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) { +// 1. There is an error during conversion of the argument list +// 2. The value is not actually a function +// 3. An (uncaught) exception is thrown +func (v Value) Call(this Value, argumentList ...interface{}) (Value, error) { result := Value{} err := catchPanic(func() { // FIXME - result = value.call(nil, this, argumentList...) + result = v.call(nil, this, argumentList...) }) - if !value.safe() { - value = Value{} + if !v.safe() { + v = Value{} } return result, err } -func (value Value) call(rt *_runtime, this Value, argumentList ...interface{}) Value { - switch function := value.value.(type) { - case *_object: +func (v Value) call(rt *runtime, this Value, argumentList ...interface{}) Value { + if function, ok := v.value.(*object); ok { return function.call(this, function.runtime.toValueArray(argumentList...), false, nativeFrame) } - if rt == nil { - panic("FIXME TypeError") - } - panic(rt.panicTypeError()) + panic(rt.panicTypeError("call %q is not an object", v.value)) } -func (value Value) constructSafe(rt *_runtime, this Value, argumentList ...interface{}) (Value, error) { +func (v Value) constructSafe(rt *runtime, this Value, argumentList ...interface{}) (Value, error) { result := Value{} err := catchPanic(func() { - result = value.construct(rt, this, argumentList...) + result = v.construct(rt, this, argumentList...) }) return result, err } -func (value Value) construct(rt *_runtime, this Value, argumentList ...interface{}) Value { - switch fn := value.value.(type) { - case *_object: +func (v Value) construct(rt *runtime, this Value, argumentList ...interface{}) Value { //nolint:unparam + if fn, ok := v.value.(*object); ok { return fn.construct(fn.runtime.toValueArray(argumentList...)) } - if rt == nil { - panic("FIXME TypeError") - } - panic(rt.panicTypeError()) + panic(rt.panicTypeError("construct %q is not an object", v.value)) } // IsPrimitive will return true if value is a primitive (any kind of primitive). -func (value Value) IsPrimitive() bool { - return !value.IsObject() +func (v Value) IsPrimitive() bool { + return !v.IsObject() } // IsBoolean will return true if value is a boolean (primitive). -func (value Value) IsBoolean() bool { - return value.kind == valueBoolean +func (v Value) IsBoolean() bool { + return v.kind == valueBoolean } // IsNumber will return true if value is a number (primitive). -func (value Value) IsNumber() bool { - return value.kind == valueNumber +func (v Value) IsNumber() bool { + return v.kind == valueNumber } // IsNaN will return true if value is NaN (or would convert to NaN). -func (value Value) IsNaN() bool { - switch value := value.value.(type) { +func (v Value) IsNaN() bool { + switch value := v.value.(type) { case float64: return math.IsNaN(value) case float32: @@ -175,99 +164,98 @@ func (value Value) IsNaN() bool { return false } - return math.IsNaN(value.float64()) + return math.IsNaN(v.float64()) } // IsString will return true if value is a string (primitive). -func (value Value) IsString() bool { - return value.kind == valueString +func (v Value) IsString() bool { + return v.kind == valueString } // IsObject will return true if value is an object. -func (value Value) IsObject() bool { - return value.kind == valueObject +func (v Value) IsObject() bool { + return v.kind == valueObject } // IsFunction will return true if value is a function. -func (value Value) IsFunction() bool { - if value.kind != valueObject { +func (v Value) IsFunction() bool { + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Function" + return v.value.(*object).class == classFunctionName } // Class will return the class string of the value or the empty string if value is not an object. // // The return value will (generally) be one of: // -// Object -// Function -// Array -// String -// Number -// Boolean -// Date -// RegExp -// -func (value Value) Class() string { - if value.kind != valueObject { +// Object +// Function +// Array +// String +// Number +// Boolean +// Date +// RegExp +func (v Value) Class() string { + if v.kind != valueObject { return "" } - return value.value.(*_object).class + return v.value.(*object).class } -func (value Value) isArray() bool { - if value.kind != valueObject { +func (v Value) isArray() bool { //nolint:unused + if v.kind != valueObject { return false } - return isArray(value.value.(*_object)) + return isArray(v.value.(*object)) } -func (value Value) isStringObject() bool { - if value.kind != valueObject { +func (v Value) isStringObject() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "String" + return v.value.(*object).class == classStringName } -func (value Value) isBooleanObject() bool { - if value.kind != valueObject { +func (v Value) isBooleanObject() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Boolean" + return v.value.(*object).class == classBooleanName } -func (value Value) isNumberObject() bool { - if value.kind != valueObject { +func (v Value) isNumberObject() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Number" + return v.value.(*object).class == classNumberName } -func (value Value) isDate() bool { - if value.kind != valueObject { +func (v Value) isDate() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Date" + return v.value.(*object).class == classDateName } -func (value Value) isRegExp() bool { - if value.kind != valueObject { +func (v Value) isRegExp() bool { + if v.kind != valueObject { return false } - return value.value.(*_object).class == "RegExp" + return v.value.(*object).class == classRegExpName } -func (value Value) isError() bool { - if value.kind != valueObject { +func (v Value) isError() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Error" + return v.value.(*object).class == classErrorName } // --- -func toValue_reflectValuePanic(value interface{}, kind reflect.Kind) { +func reflectValuePanic(value interface{}, kind reflect.Kind) { // FIXME? switch kind { case reflect.Struct: @@ -284,46 +272,46 @@ func toValue(value interface{}) Value { case Value: return value case bool: - return Value{valueBoolean, value} + return Value{kind: valueBoolean, value: value} case int: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int8: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int16: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int32: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int64: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint8: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint16: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint32: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint64: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case float32: - return Value{valueNumber, float64(value)} + return Value{kind: valueNumber, value: float64(value)} case float64: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case []uint16: - return Value{valueString, value} + return Value{kind: valueString, value: value} case string: - return Value{valueString, value} + return Value{kind: valueString, value: value} // A rune is actually an int32, which is handled above - case *_object: - return Value{valueObject, value} + case *object: + return Value{kind: valueObject, value: value} case *Object: - return Value{valueObject, value.object} + return Value{kind: valueObject, value: value.object} case Object: - return Value{valueObject, value.object} - case _reference: // reference is an interface (already a pointer) - return Value{valueReference, value} - case _result: - return Value{valueResult, value} + return Value{kind: valueObject, value: value.object} + case referencer: // reference is an interface (already a pointer) + return Value{kind: valueReference, value: value} + case result: + return Value{kind: valueResult, value: value} case nil: // TODO Ugh. return Value{} @@ -341,35 +329,35 @@ func toValue(value interface{}) Value { } switch value.Kind() { case reflect.Bool: - return Value{valueBoolean, bool(value.Bool())} + return Value{kind: valueBoolean, value: value.Bool()} case reflect.Int: - return Value{valueNumber, int(value.Int())} + return Value{kind: valueNumber, value: int(value.Int())} case reflect.Int8: - return Value{valueNumber, int8(value.Int())} + return Value{kind: valueNumber, value: int8(value.Int())} case reflect.Int16: - return Value{valueNumber, int16(value.Int())} + return Value{kind: valueNumber, value: int16(value.Int())} case reflect.Int32: - return Value{valueNumber, int32(value.Int())} + return Value{kind: valueNumber, value: int32(value.Int())} case reflect.Int64: - return Value{valueNumber, int64(value.Int())} + return Value{kind: valueNumber, value: value.Int()} case reflect.Uint: - return Value{valueNumber, uint(value.Uint())} + return Value{kind: valueNumber, value: uint(value.Uint())} case reflect.Uint8: - return Value{valueNumber, uint8(value.Uint())} + return Value{kind: valueNumber, value: uint8(value.Uint())} case reflect.Uint16: - return Value{valueNumber, uint16(value.Uint())} + return Value{kind: valueNumber, value: uint16(value.Uint())} case reflect.Uint32: - return Value{valueNumber, uint32(value.Uint())} + return Value{kind: valueNumber, value: uint32(value.Uint())} case reflect.Uint64: - return Value{valueNumber, uint64(value.Uint())} + return Value{kind: valueNumber, value: value.Uint()} case reflect.Float32: - return Value{valueNumber, float32(value.Float())} + return Value{kind: valueNumber, value: float32(value.Float())} case reflect.Float64: - return Value{valueNumber, float64(value.Float())} + return Value{kind: valueNumber, value: value.Float()} case reflect.String: - return Value{valueString, string(value.String())} + return Value{kind: valueString, value: value.String()} default: - toValue_reflectValuePanic(value.Interface(), value.Kind()) + reflectValuePanic(value.Interface(), value.Kind()) } default: return toValue(reflect.ValueOf(value)) @@ -381,89 +369,88 @@ func toValue(value interface{}) Value { // String will return the value as a string. // // This method will make return the empty string if there is an error. -func (value Value) String() string { - result := "" - catchPanic(func() { - result = value.string() +func (v Value) String() string { + var result string + catchPanic(func() { //nolint:errcheck, gosec + result = v.string() }) return result } // ToBoolean will convert the value to a boolean (bool). // -// ToValue(0).ToBoolean() => false -// ToValue("").ToBoolean() => false -// ToValue(true).ToBoolean() => true -// ToValue(1).ToBoolean() => true -// ToValue("Nothing happens").ToBoolean() => true +// ToValue(0).ToBoolean() => false +// ToValue("").ToBoolean() => false +// ToValue(true).ToBoolean() => true +// ToValue(1).ToBoolean() => true +// ToValue("Nothing happens").ToBoolean() => true // // If there is an error during the conversion process (like an uncaught exception), then the result will be false and an error. -func (value Value) ToBoolean() (bool, error) { +func (v Value) ToBoolean() (bool, error) { result := false err := catchPanic(func() { - result = value.bool() + result = v.bool() }) return result, err } -func (value Value) numberValue() Value { - if value.kind == valueNumber { - return value +func (v Value) numberValue() Value { + if v.kind == valueNumber { + return v } - return Value{valueNumber, value.float64()} + return Value{kind: valueNumber, value: v.float64()} } // ToFloat will convert the value to a number (float64). // -// ToValue(0).ToFloat() => 0. -// ToValue(1.1).ToFloat() => 1.1 -// ToValue("11").ToFloat() => 11. +// ToValue(0).ToFloat() => 0. +// ToValue(1.1).ToFloat() => 1.1 +// ToValue("11").ToFloat() => 11. // // If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -func (value Value) ToFloat() (float64, error) { +func (v Value) ToFloat() (float64, error) { result := float64(0) err := catchPanic(func() { - result = value.float64() + result = v.float64() }) return result, err } // ToInteger will convert the value to a number (int64). // -// ToValue(0).ToInteger() => 0 -// ToValue(1.1).ToInteger() => 1 -// ToValue("11").ToInteger() => 11 +// ToValue(0).ToInteger() => 0 +// ToValue(1.1).ToInteger() => 1 +// ToValue("11").ToInteger() => 11 // // If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -func (value Value) ToInteger() (int64, error) { +func (v Value) ToInteger() (int64, error) { result := int64(0) err := catchPanic(func() { - result = value.number().int64 + result = v.number().int64 }) return result, err } // ToString will convert the value to a string (string). // -// ToValue(0).ToString() => "0" -// ToValue(false).ToString() => "false" -// ToValue(1.1).ToString() => "1.1" -// ToValue("11").ToString() => "11" -// ToValue('Nothing happens.').ToString() => "Nothing happens." +// ToValue(0).ToString() => "0" +// ToValue(false).ToString() => "false" +// ToValue(1.1).ToString() => "1.1" +// ToValue("11").ToString() => "11" +// ToValue('Nothing happens.').ToString() => "Nothing happens." // // If there is an error during the conversion process (like an uncaught exception), then the result will be the empty string ("") and an error. -func (value Value) ToString() (string, error) { +func (v Value) ToString() (string, error) { result := "" err := catchPanic(func() { - result = value.string() + result = v.string() }) return result, err } -func (value Value) _object() *_object { - switch value := value.value.(type) { - case *_object: - return value +func (v Value) object() *object { + if v, ok := v.value.(*object); ok { + return v } return nil } @@ -471,160 +458,137 @@ func (value Value) _object() *_object { // Object will return the object of the value, or nil if value is not an object. // // This method will not do any implicit conversion. For example, calling this method on a string primitive value will not return a String object. -func (value Value) Object() *Object { - switch object := value.value.(type) { - case *_object: - return _newObject(object, value) +func (v Value) Object() *Object { + if obj, ok := v.value.(*object); ok { + return &Object{ + object: obj, + value: v, + } } return nil } -func (value Value) reference() _reference { - switch value := value.value.(type) { - case _reference: - return value - } - return nil +func (v Value) reference() referencer { + value, _ := v.value.(referencer) + return value } -func (value Value) resolve() Value { - switch value := value.value.(type) { - case _reference: +func (v Value) resolve() Value { + if value, ok := v.value.(referencer); ok { return value.getValue() } - return value + return v } var ( - __NaN__ float64 = math.NaN() - __PositiveInfinity__ float64 = math.Inf(+1) - __NegativeInfinity__ float64 = math.Inf(-1) - __PositiveZero__ float64 = 0 - __NegativeZero__ float64 = math.Float64frombits(0 | (1 << 63)) + nan float64 = math.NaN() + positiveInfinity float64 = math.Inf(+1) + negativeInfinity float64 = math.Inf(-1) + positiveZero float64 = 0 + negativeZero float64 = math.Float64frombits(0 | (1 << 63)) ) -func positiveInfinity() float64 { - return __PositiveInfinity__ -} - -func negativeInfinity() float64 { - return __NegativeInfinity__ -} - -func positiveZero() float64 { - return __PositiveZero__ -} - -func negativeZero() float64 { - return __NegativeZero__ -} - // NaNValue will return a value representing NaN. // // It is equivalent to: // -// ToValue(math.NaN()) -// +// ToValue(math.NaN()) func NaNValue() Value { - return Value{valueNumber, __NaN__} + return Value{kind: valueNumber, value: nan} } func positiveInfinityValue() Value { - return Value{valueNumber, __PositiveInfinity__} + return Value{kind: valueNumber, value: positiveInfinity} } func negativeInfinityValue() Value { - return Value{valueNumber, __NegativeInfinity__} + return Value{kind: valueNumber, value: negativeInfinity} } func positiveZeroValue() Value { - return Value{valueNumber, __PositiveZero__} + return Value{kind: valueNumber, value: positiveZero} } func negativeZeroValue() Value { - return Value{valueNumber, __NegativeZero__} + return Value{kind: valueNumber, value: negativeZero} } // TrueValue will return a value representing true. // // It is equivalent to: // -// ToValue(true) -// +// ToValue(true) func TrueValue() Value { - return Value{valueBoolean, true} + return Value{kind: valueBoolean, value: true} } // FalseValue will return a value representing false. // // It is equivalent to: // -// ToValue(false) -// +// ToValue(false) func FalseValue() Value { - return Value{valueBoolean, false} + return Value{kind: valueBoolean, value: false} } func sameValue(x Value, y Value) bool { if x.kind != y.kind { return false } - result := false + switch x.kind { case valueUndefined, valueNull: - result = true + return true case valueNumber: x := x.float64() y := y.float64() if math.IsNaN(x) && math.IsNaN(y) { - result = true - } else { - result = x == y - if result && x == 0 { + return true + } + + if x == y { + if x == 0 { // Since +0 != -0 - result = math.Signbit(x) == math.Signbit(y) + return math.Signbit(x) == math.Signbit(y) } + return true } + return false case valueString: - result = x.string() == y.string() + return x.string() == y.string() case valueBoolean: - result = x.bool() == y.bool() + return x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + return x.object() == y.object() default: panic(hereBeDragons()) } - - return result } func strictEqualityComparison(x Value, y Value) bool { if x.kind != y.kind { return false } - result := false + switch x.kind { case valueUndefined, valueNull: - result = true + return true case valueNumber: x := x.float64() y := y.float64() if math.IsNaN(x) && math.IsNaN(y) { - result = false - } else { - result = x == y + return false } + return x == y case valueString: - result = x.string() == y.string() + return x.string() == y.string() case valueBoolean: - result = x.bool() == y.bool() + return x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + return x.object() == y.object() default: panic(hereBeDragons()) } - - return result } // Export will attempt to convert the value to a Go representation @@ -636,71 +600,80 @@ func strictEqualityComparison(x Value, y Value) bool { // If a reasonable conversion is not possible, then the original // value is returned. // -// undefined -> nil (FIXME?: Should be Value{}) -// null -> nil -// boolean -> bool -// number -> A number type (int, float32, uint64, ...) -// string -> string -// Array -> []interface{} -// Object -> map[string]interface{} -// -func (self Value) Export() (interface{}, error) { - return self.export(), nil -} - -func (self Value) export() interface{} { - - switch self.kind { +// undefined -> nil (FIXME?: Should be Value{}) +// null -> nil +// boolean -> bool +// number -> A number type (int, float32, uint64, ...) +// string -> string +// Array -> []interface{} +// Object -> map[string]interface{} +func (v Value) Export() (interface{}, error) { + return v.export(), nil +} + +func (v Value) export() interface{} { + switch v.kind { case valueUndefined: return nil case valueNull: return nil case valueNumber, valueBoolean: - return self.value + return v.value case valueString: - switch value := self.value.(type) { + switch value := v.value.(type) { case string: return value case []uint16: return string(utf16.Decode(value)) } case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: + obj := v.object() + switch value := obj.value.(type) { + case *goStructObject: return value.value.Interface() - case *_goMapObject: + case *goMapObject: return value.value.Interface() - case *_goArrayObject: + case *goArrayObject: return value.value.Interface() - case *_goSliceObject: + case *goSliceObject: return value.value.Interface() } - if object.class == "Array" { + if obj.class == classArrayName { result := make([]interface{}, 0) - lengthValue := object.get("length") + lengthValue := obj.get(propertyLength) length := lengthValue.value.(uint32) kind := reflect.Invalid + keyKind := reflect.Invalid + elemKind := reflect.Invalid state := 0 var t reflect.Type - for index := uint32(0); index < length; index += 1 { + for index := range length { name := strconv.FormatInt(int64(index), 10) - if !object.hasProperty(name) { + if !obj.hasProperty(name) { continue } - value := object.get(name).export() + value := obj.get(name).export() t = reflect.TypeOf(value) - var k reflect.Kind + var k, kk, ek reflect.Kind if t != nil { k = t.Kind() + switch k { + case reflect.Map: + kk = t.Key().Kind() + fallthrough + case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: + ek = t.Elem().Kind() + } } if state == 0 { kind = k + keyKind = kk + elemKind = ek state = 1 - } else if state == 1 && kind != k { + } else if state == 1 && (kind != k || keyKind != kk || elemKind != ek) { state = 2 } @@ -718,29 +691,29 @@ func (self Value) export() interface{} { val.Index(i).Set(reflect.ValueOf(v)) } return val.Interface() - } else { - result := make(map[string]interface{}) - // TODO Should we export everything? Or just what is enumerable? - object.enumerate(false, func(name string) bool { - value := object.get(name) - if value.IsDefined() { - result[name] = value.export() - } - return true - }) - return result } + + result := make(map[string]interface{}) + // TODO Should we export everything? Or just what is enumerable? + obj.enumerate(false, func(name string) bool { + value := obj.get(name) + if value.IsDefined() { + result[name] = value.export() + } + return true + }) + return result } - if self.safe() { - return self + if v.safe() { + return v } return Value{} } -func (self Value) evaluateBreakContinue(labels []string) _resultKind { - result := self.value.(_result) +func (v Value) evaluateBreakContinue(labels []string) resultKind { + result := v.value.(result) if result.kind == resultBreak || result.kind == resultContinue { for _, label := range labels { if label == result.target { @@ -751,8 +724,8 @@ func (self Value) evaluateBreakContinue(labels []string) _resultKind { return resultReturn } -func (self Value) evaluateBreak(labels []string) _resultKind { - result := self.value.(_result) +func (v Value) evaluateBreak(labels []string) resultKind { + result := v.value.(result) if result.kind == resultBreak { for _, label := range labels { if label == result.target { @@ -763,44 +736,14 @@ func (self Value) evaluateBreak(labels []string) _resultKind { return resultReturn } -func (self Value) exportNative() interface{} { - - switch self.kind { - case valueUndefined: - return self - case valueNull: - return nil - case valueNumber, valueBoolean: - return self.value - case valueString: - switch value := self.value.(type) { - case string: - return value - case []uint16: - return string(utf16.Decode(value)) - } - case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: - return value.value.Interface() - case *_goMapObject: - return value.value.Interface() - case *_goArrayObject: - return value.value.Interface() - case *_goSliceObject: - return value.value.Interface() - } - } - - return self -} - // Make a best effort to return a reflect.Value corresponding to reflect.Kind, but // fallback to just returning the Go value we have handy. -func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { - if kind != reflect.Float32 && kind != reflect.Float64 && kind != reflect.Interface { - switch value := value.value.(type) { +func (v Value) toReflectValue(typ reflect.Type) (reflect.Value, error) { + kind := typ.Kind() + switch kind { + case reflect.Float32, reflect.Float64, reflect.Interface: + default: + switch value := v.value.(type) { case float32: _, frac := math.Modf(float64(value)) if frac > 0 { @@ -816,101 +759,90 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { switch kind { case reflect.Bool: // Bool - return reflect.ValueOf(value.bool()), nil + return reflect.ValueOf(v.bool()).Convert(typ), nil case reflect.Int: // Int // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of int64 - tmp := toIntegerFloat(value) - if tmp < float_minInt || tmp > float_maxInt { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < floatMinInt || tmp > floatMaxInt { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, v) } + return reflect.ValueOf(int(tmp)).Convert(typ), nil case reflect.Int8: // Int8 - tmp := value.number().int64 - if tmp < int64_minInt8 || tmp > int64_maxInt8 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, value) - } else { - return reflect.ValueOf(int8(tmp)), nil + tmp := v.number().int64 + if tmp < int64MinInt8 || tmp > int64MaxInt8 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, v) } + return reflect.ValueOf(int8(tmp)).Convert(typ), nil case reflect.Int16: // Int16 - tmp := value.number().int64 - if tmp < int64_minInt16 || tmp > int64_maxInt16 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, value) - } else { - return reflect.ValueOf(int16(tmp)), nil + tmp := v.number().int64 + if tmp < int64MinInt16 || tmp > int64MaxInt16 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, v) } + return reflect.ValueOf(int16(tmp)).Convert(typ), nil case reflect.Int32: // Int32 - tmp := value.number().int64 - if tmp < int64_minInt32 || tmp > int64_maxInt32 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, value) - } else { - return reflect.ValueOf(int32(tmp)), nil + tmp := v.number().int64 + if tmp < int64MinInt32 || tmp > int64MaxInt32 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, v) } + return reflect.ValueOf(int32(tmp)).Convert(typ), nil case reflect.Int64: // Int64 // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of int64 - tmp := toIntegerFloat(value) - if tmp < float_minInt64 || tmp > float_maxInt64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int64(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < floatMinInt64 || tmp > floatMaxInt64 { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, v) } + return reflect.ValueOf(int64(tmp)).Convert(typ), nil case reflect.Uint: // Uint // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of uint - tmp := toIntegerFloat(value) - if tmp < 0 || tmp > float_maxUint { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, value) - } else { - return reflect.ValueOf(uint(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < 0 || tmp > floatMaxUint { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, v) } + return reflect.ValueOf(uint(tmp)).Convert(typ), nil case reflect.Uint8: // Uint8 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint8 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, value) - } else { - return reflect.ValueOf(uint8(tmp)), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint8 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, v) } + return reflect.ValueOf(uint8(tmp)).Convert(typ), nil case reflect.Uint16: // Uint16 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint16 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, value) - } else { - return reflect.ValueOf(uint16(tmp)), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint16 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, v) } + return reflect.ValueOf(uint16(tmp)).Convert(typ), nil case reflect.Uint32: // Uint32 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint32 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, value) - } else { - return reflect.ValueOf(uint32(tmp)), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint32 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, v) } + return reflect.ValueOf(uint32(tmp)).Convert(typ), nil case reflect.Uint64: // Uint64 // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of uint64 - tmp := toIntegerFloat(value) - if tmp < 0 || tmp > float_maxUint64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, value) - } else { - return reflect.ValueOf(uint64(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < 0 || tmp > floatMaxUint64 { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, v) } + return reflect.ValueOf(uint64(tmp)).Convert(typ), nil case reflect.Float32: // Float32 - tmp := value.float64() + tmp := v.float64() tmp1 := tmp if 0 > tmp1 { tmp1 = -tmp1 } if tmp1 > 0 && (tmp1 < math.SmallestNonzeroFloat32 || tmp1 > math.MaxFloat32) { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, value) - } else { - return reflect.ValueOf(float32(tmp)), nil + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, v) } + return reflect.ValueOf(float32(tmp)).Convert(typ), nil case reflect.Float64: // Float64 - value := value.float64() - return reflect.ValueOf(float64(value)), nil + value := v.float64() + return reflect.ValueOf(value).Convert(typ), nil case reflect.String: // String - return reflect.ValueOf(value.string()), nil + return reflect.ValueOf(v.string()).Convert(typ), nil case reflect.Invalid: // Invalid case reflect.Complex64: // FIXME? Complex64 case reflect.Complex128: // FIXME? Complex128 @@ -919,29 +851,33 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { case reflect.Ptr: // FIXME? Ptr case reflect.UnsafePointer: // FIXME? UnsafePointer default: - switch value.kind { + switch v.kind { case valueObject: - object := value._object() - switch vl := object.value.(type) { - case *_goStructObject: // Struct + obj := v.object() + switch vl := obj.value.(type) { + case *goStructObject: // Struct return reflect.ValueOf(vl.value.Interface()), nil - case *_goMapObject: // Map + case *goMapObject: // Map return reflect.ValueOf(vl.value.Interface()), nil - case *_goArrayObject: // Array + case *goArrayObject: // Array return reflect.ValueOf(vl.value.Interface()), nil - case *_goSliceObject: // Slice + case *goSliceObject: // Slice return reflect.ValueOf(vl.value.Interface()), nil } - return reflect.ValueOf(value.exportNative()), nil + exported := reflect.ValueOf(v.export()) + if exported.Type().ConvertibleTo(typ) { + return exported.Convert(typ), nil + } + return reflect.Value{}, fmt.Errorf("TypeError: could not convert %v to reflect.Type: %v", exported, typ) case valueEmpty, valueResult, valueReference: // These are invalid, and should panic default: - return reflect.ValueOf(value.value), nil + return reflect.ValueOf(v.value), nil } } // FIXME Should this end up as a TypeError? - panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Kind: %v", value.kind, value, kind)) + panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Type: %v", v.kind, v, typ)) } func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error) { @@ -981,7 +917,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(int64(value)), nil + return reflect.ValueOf(value), nil case reflect.Uint: value, err := strconv.ParseUint(value, 0, 0) if err != nil { @@ -1011,7 +947,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(uint64(value)), nil + return reflect.ValueOf(value), nil case reflect.Float32: value, err := strconv.ParseFloat(value, 32) if err != nil { @@ -1023,7 +959,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(float64(value)), nil + return reflect.ValueOf(value), nil case reflect.String: return reflect.ValueOf(value), nil } @@ -1031,3 +967,18 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error // FIXME This should end up as a TypeError? panic(fmt.Errorf("invalid conversion of %q to reflect.Kind: %v", value, kind)) } + +// MarshalJSON implements json.Marshaller. +func (v Value) MarshalJSON() ([]byte, error) { + switch v.kind { + case valueUndefined, valueNull: + return []byte("null"), nil + case valueBoolean, valueNumber: + return json.Marshal(v.value) + case valueString: + return json.Marshal(v.string()) + case valueObject: + return v.Object().MarshalJSON() + } + return nil, fmt.Errorf("invalid type %v", v.kind) +} diff --git a/vendor/github.com/robertkrimen/otto/value_boolean.go b/vendor/github.com/robertkrimen/otto/value_boolean.go index b631507b0..670ecab07 100644 --- a/vendor/github.com/robertkrimen/otto/value_boolean.go +++ b/vendor/github.com/robertkrimen/otto/value_boolean.go @@ -7,37 +7,34 @@ import ( "unicode/utf16" ) -func (value Value) bool() bool { - if value.kind == valueBoolean { - return value.value.(bool) +func (v Value) bool() bool { + if v.kind == valueBoolean { + return v.value.(bool) } - if value.IsUndefined() { + if v.IsUndefined() || v.IsNull() { return false } - if value.IsNull() { - return false - } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: return value case int, int8, int16, int32, int64: - return 0 != reflect.ValueOf(value).Int() + return reflect.ValueOf(value).Int() != 0 case uint, uint8, uint16, uint32, uint64: - return 0 != reflect.ValueOf(value).Uint() + return reflect.ValueOf(value).Uint() != 0 case float32: - return 0 != value + return value != 0 case float64: if math.IsNaN(value) || value == 0 { return false } return true case string: - return 0 != len(value) + return len(value) != 0 case []uint16: - return 0 != len(utf16.Decode(value)) + return len(utf16.Decode(value)) != 0 } - if value.IsObject() { + if v.IsObject() { return true } - panic(fmt.Errorf("toBoolean(%T)", value.value)) + panic(fmt.Sprintf("unexpected boolean type %T", v.value)) } diff --git a/vendor/github.com/robertkrimen/otto/value_number.go b/vendor/github.com/robertkrimen/otto/value_number.go index 8cbf136d2..6f14b4bb5 100644 --- a/vendor/github.com/robertkrimen/otto/value_number.go +++ b/vendor/github.com/robertkrimen/otto/value_number.go @@ -1,6 +1,7 @@ package otto import ( + "errors" "fmt" "math" "regexp" @@ -11,24 +12,25 @@ import ( var stringToNumberParseInteger = regexp.MustCompile(`^(?:0[xX])`) func parseNumber(value string) float64 { - value = strings.Trim(value, builtinString_trim_whitespace) + value = strings.Trim(value, builtinStringTrimWhitespace) if value == "" { return 0 } - parseFloat := false - if strings.IndexRune(value, '.') != -1 { + var parseFloat bool + switch { + case strings.ContainsRune(value, '.'): parseFloat = true - } else if stringToNumberParseInteger.MatchString(value) { + case stringToNumberParseInteger.MatchString(value): parseFloat = false - } else { + default: parseFloat = true } if parseFloat { number, err := strconv.ParseFloat(value, 64) - if err != nil && err.(*strconv.NumError).Err != strconv.ErrRange { + if err != nil && !errors.Is(err, strconv.ErrRange) { return math.NaN() } return number @@ -41,14 +43,14 @@ func parseNumber(value string) float64 { return float64(number) } -func (value Value) float64() float64 { - switch value.kind { +func (v Value) float64() float64 { + switch v.kind { case valueUndefined: return math.NaN() case valueNull: return 0 } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: if value { return 1 @@ -78,89 +80,65 @@ func (value Value) float64() float64 { return value case string: return parseNumber(value) - case *_object: + case *object: return value.DefaultValue(defaultValueHintNumber).float64() } - panic(fmt.Errorf("toFloat(%T)", value.value)) + panic(fmt.Errorf("toFloat(%T)", v.value)) } const ( - float_2_64 float64 = 18446744073709551616.0 - float_2_63 float64 = 9223372036854775808.0 - float_2_32 float64 = 4294967296.0 - float_2_31 float64 = 2147483648.0 - float_2_16 float64 = 65536.0 - integer_2_32 int64 = 4294967296 - integer_2_31 int64 = 2146483648 - sqrt1_2 float64 = math.Sqrt2 / 2 + sqrt1_2 float64 = math.Sqrt2 / 2 ) const ( - maxInt8 = math.MaxInt8 - minInt8 = math.MinInt8 - maxInt16 = math.MaxInt16 - minInt16 = math.MinInt16 - maxInt32 = math.MaxInt32 - minInt32 = math.MinInt32 - maxInt64 = math.MaxInt64 - minInt64 = math.MinInt64 - maxUint8 = math.MaxUint8 - maxUint16 = math.MaxUint16 maxUint32 = math.MaxUint32 - maxUint64 = math.MaxUint64 - maxUint = ^uint(0) - minUint = 0 maxInt = int(^uint(0) >> 1) - minInt = -maxInt - 1 - - // int64 - int64_maxInt int64 = int64(maxInt) - int64_minInt int64 = int64(minInt) - int64_maxInt8 int64 = math.MaxInt8 - int64_minInt8 int64 = math.MinInt8 - int64_maxInt16 int64 = math.MaxInt16 - int64_minInt16 int64 = math.MinInt16 - int64_maxInt32 int64 = math.MaxInt32 - int64_minInt32 int64 = math.MinInt32 - int64_maxUint8 int64 = math.MaxUint8 - int64_maxUint16 int64 = math.MaxUint16 - int64_maxUint32 int64 = math.MaxUint32 - - // float64 - float_maxInt float64 = float64(int(^uint(0) >> 1)) - float_minInt float64 = float64(int(-maxInt - 1)) - float_minUint float64 = float64(0) - float_maxUint float64 = float64(uint(^uint(0))) - float_minUint64 float64 = float64(0) - float_maxUint64 float64 = math.MaxUint64 - float_maxInt64 float64 = math.MaxInt64 - float_minInt64 float64 = math.MinInt64 + + // int64. + int64MaxInt8 int64 = math.MaxInt8 + int64MinInt8 int64 = math.MinInt8 + int64MaxInt16 int64 = math.MaxInt16 + int64MinInt16 int64 = math.MinInt16 + int64MaxInt32 int64 = math.MaxInt32 + int64MinInt32 int64 = math.MinInt32 + int64MaxUint8 int64 = math.MaxUint8 + int64MaxUint16 int64 = math.MaxUint16 + int64MaxUint32 int64 = math.MaxUint32 + + // float64. + floatMaxInt float64 = float64(int(^uint(0) >> 1)) + floatMinInt float64 = float64(-maxInt - 1) + floatMaxUint float64 = float64(^uint(0)) + floatMaxUint64 float64 = math.MaxUint64 + floatMaxInt64 float64 = math.MaxInt64 + floatMinInt64 float64 = math.MinInt64 ) func toIntegerFloat(value Value) float64 { float := value.float64() - if math.IsInf(float, 0) { - } else if math.IsNaN(float) { - float = 0 - } else if float > 0 { - float = math.Floor(float) - } else { - float = math.Ceil(float) + switch { + case math.IsInf(float, 0): + return float + case math.IsNaN(float): + return 0 + case float > 0: + return math.Floor(float) + default: + return math.Ceil(float) } - return float } -type _numberKind int +type numberKind int const ( - numberInteger _numberKind = iota // 3.0 => 3.0 - numberFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1 - numberInfinity // Infinity => 2**63-1 - numberNaN // NaN => 0 + numberInteger numberKind = iota // 3.0 => 3.0 + numberFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1 + numberInfinity // Infinity => 2**63-1 + numberNaN // NaN => 0 ) type _number struct { - kind _numberKind + kind numberKind int64 int64 float64 float64 } @@ -168,59 +146,60 @@ type _number struct { // FIXME // http://www.goinggo.net/2013/08/gustavos-ieee-754-brain-teaser.html // http://bazaar.launchpad.net/~niemeyer/strepr/trunk/view/6/strepr.go#L160 -func (value Value) number() (number _number) { - switch value := value.value.(type) { +func (v Value) number() _number { + var num _number + switch value := v.value.(type) { case int8: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int16: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint8: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint16: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint32: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int64: - number.int64 = value - return + num.int64 = value + return num } - float := value.float64() + float := v.float64() if float == 0 { - return + return num } - number.kind = numberFloat - number.float64 = float + num.kind = numberFloat + num.float64 = float if math.IsNaN(float) { - number.kind = numberNaN - return + num.kind = numberNaN + return num } if math.IsInf(float, 0) { - number.kind = numberInfinity + num.kind = numberInfinity } - if float >= float_maxInt64 { - number.int64 = math.MaxInt64 - return + if float >= floatMaxInt64 { + num.int64 = math.MaxInt64 + return num } - if float <= float_minInt64 { - number.int64 = math.MinInt64 - return + if float <= floatMinInt64 { + num.int64 = math.MinInt64 + return num } - integer := float64(0) + var integer float64 if float > 0 { integer = math.Floor(float) } else { @@ -228,97 +207,130 @@ func (value Value) number() (number _number) { } if float == integer { - number.kind = numberInteger + num.kind = numberInteger } - number.int64 = int64(float) - return + num.int64 = int64(float) + return num } -// ECMA 262: 9.5 +// ECMA 262: 9.5. func toInt32(value Value) int32 { - { - switch value := value.value.(type) { - case int8: - return int32(value) - case int16: - return int32(value) - case int32: - return value - } + switch value := value.value.(type) { + case int8: + return int32(value) + case int16: + return int32(value) + case int32: + return value } + floatValue := value.float64() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { - return 0 - } - if floatValue == 0 { // This will work for +0 & -0 + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 { return 0 } - remainder := math.Mod(floatValue, float_2_32) - if remainder > 0 { - remainder = math.Floor(remainder) - } else { - remainder = math.Ceil(remainder) + float_2_32 - } - if remainder > float_2_31 { - return int32(remainder - float_2_32) - } - return int32(remainder) + + // Convert to int64 before int32 to force correct wrapping. + return int32(int64(floatValue)) } func toUint32(value Value) uint32 { - { - switch value := value.value.(type) { - case int8: - return uint32(value) - case int16: - return uint32(value) - case uint8: - return uint32(value) - case uint16: - return uint32(value) - case uint32: - return value - } + switch value := value.value.(type) { + case int8: + return uint32(value) + case int16: + return uint32(value) + case uint8: + return uint32(value) + case uint16: + return uint32(value) + case uint32: + return value } + floatValue := value.float64() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { - return 0 - } - if floatValue == 0 { + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 { return 0 } - remainder := math.Mod(floatValue, float_2_32) - if remainder > 0 { - remainder = math.Floor(remainder) - } else { - remainder = math.Ceil(remainder) + float_2_32 - } - return uint32(remainder) + + // Convert to int64 before uint32 to force correct wrapping. + return uint32(int64(floatValue)) } +// ECMA 262 - 6.0 - 7.1.8. func toUint16(value Value) uint16 { - { - switch value := value.value.(type) { - case int8: - return uint16(value) - case uint8: - return uint16(value) - case uint16: - return value - } + switch value := value.value.(type) { + case int8: + return uint16(value) + case uint8: + return uint16(value) + case uint16: + return value } + floatValue := value.float64() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 { return 0 } - if floatValue == 0 { + + // Convert to int64 before uint16 to force correct wrapping. + return uint16(int64(floatValue)) +} + +// toIntSign returns sign of a number converted to -1, 0 ,1. +func toIntSign(value Value) int { + switch value := value.value.(type) { + case int8: + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } + + return 0 + case int16: + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } + + return 0 + case int32: + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } + + return 0 + case uint8: + if value > 0 { + return 1 + } + + return 0 + case uint16: + if value > 0 { + return 1 + } + + return 0 + case uint32: + if value > 0 { + return 1 + } + return 0 } - remainder := math.Mod(floatValue, float_2_16) - if remainder > 0 { - remainder = math.Floor(remainder) - } else { - remainder = math.Ceil(remainder) + float_2_16 + floatValue := value.float64() + switch { + case math.IsNaN(floatValue), math.IsInf(floatValue, 0): + return 0 + case floatValue == 0: + return 0 + case floatValue > 0: + return 1 + default: + return -1 } - return uint16(remainder) } diff --git a/vendor/github.com/robertkrimen/otto/value_primitive.go b/vendor/github.com/robertkrimen/otto/value_primitive.go index 11ed329d1..23f8e81d4 100644 --- a/vendor/github.com/robertkrimen/otto/value_primitive.go +++ b/vendor/github.com/robertkrimen/otto/value_primitive.go @@ -1,23 +1,20 @@ package otto -func toStringPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueHintString) -} - func toNumberPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueHintNumber) + return toPrimitive(value, defaultValueHintNumber) } -func toPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueNoHint) +func toPrimitiveValue(value Value) Value { + return toPrimitive(value, defaultValueNoHint) } -func _toPrimitive(value Value, hint _defaultValueHint) Value { +func toPrimitive(value Value, hint defaultValueHint) Value { switch value.kind { case valueNull, valueUndefined, valueNumber, valueString, valueBoolean: return value case valueObject: - return value._object().DefaultValue(hint) + return value.object().DefaultValue(hint) + default: + panic(hereBeDragons(value.kind, value)) } - panic(hereBeDragons(value.kind, value)) } diff --git a/vendor/github.com/robertkrimen/otto/value_string.go b/vendor/github.com/robertkrimen/otto/value_string.go index 0fbfd6b25..2af5bc3a8 100644 --- a/vendor/github.com/robertkrimen/otto/value_string.go +++ b/vendor/github.com/robertkrimen/otto/value_string.go @@ -31,12 +31,15 @@ func floatToString(value float64, bitsize int) string { func numberToStringRadix(value Value, radix int) string { float := value.float64() - if math.IsNaN(float) { + switch { + case math.IsNaN(float): return "NaN" - } else if math.IsInf(float, 1) { + case math.IsInf(float, 1): return "Infinity" - } else if math.IsInf(float, -1) { + case math.IsInf(float, -1): return "-Infinity" + case float == 0: + return "0" } // FIXME This is very broken // Need to do proper radix conversion for floats, ... @@ -44,22 +47,22 @@ func numberToStringRadix(value Value, radix int) string { return strconv.FormatInt(int64(float), radix) } -func (value Value) string() string { - if value.kind == valueString { - switch value := value.value.(type) { +func (v Value) string() string { + if v.kind == valueString { + switch value := v.value.(type) { case string: return value case []uint16: return string(utf16.Decode(value)) } } - if value.IsUndefined() { + if v.IsUndefined() { return "undefined" } - if value.IsNull() { + if v.IsNull() { return "null" } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: return strconv.FormatBool(value) case int: @@ -96,8 +99,8 @@ func (value Value) string() string { return string(utf16.Decode(value)) case string: return value - case *_object: + case *object: return value.DefaultValue(defaultValueHintString).string() } - panic(fmt.Errorf("%v.string( %T)", value.value, value.value)) + panic(fmt.Errorf("%v.string( %T)", v.value, v.value)) } diff --git a/vendor/github.com/spf13/cast/.gitignore b/vendor/github.com/spf13/cast/.gitignore index 836562412..53053a8ac 100644 --- a/vendor/github.com/spf13/cast/.gitignore +++ b/vendor/github.com/spf13/cast/.gitignore @@ -21,3 +21,5 @@ _testmain.go *.exe *.test + +*.bench diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md index af7a1fdc0..0e9e14593 100644 --- a/vendor/github.com/spf13/cast/README.md +++ b/vendor/github.com/spf13/cast/README.md @@ -1,5 +1,9 @@ -cast -==== +# cast + +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/ci.yaml) +[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast) Easy and safe casting from one type to another in Go @@ -14,7 +18,7 @@ interface into a bool, etc. Cast does this intelligently when an obvious conversion is possible. It doesn’t make any attempts to guess what you meant, for example you can only convert a string to an int when it is a string representation of an int such as “8”. Cast was developed for use in -[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON +[Hugo](https://gohugo.io), a website engine which uses YAML, TOML or JSON for meta data. ## Why use Cast? @@ -69,4 +73,3 @@ the code for a complete set. var eight interface{} = 8 cast.ToInt(eight) // 8 cast.ToInt(nil) // 0 - diff --git a/vendor/github.com/spf13/cast/cast.go b/vendor/github.com/spf13/cast/cast.go index de5a68678..0cfe9418d 100644 --- a/vendor/github.com/spf13/cast/cast.go +++ b/vendor/github.com/spf13/cast/cast.go @@ -3,76 +3,174 @@ // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. +// Package cast provides easy and safe casting in Go. package cast import "time" +// ToBool casts an interface to a bool type. func ToBool(i interface{}) bool { v, _ := ToBoolE(i) return v } +// ToTime casts an interface to a time.Time type. func ToTime(i interface{}) time.Time { v, _ := ToTimeE(i) return v } +func ToTimeInDefaultLocation(i interface{}, location *time.Location) time.Time { + v, _ := ToTimeInDefaultLocationE(i, location) + return v +} + +// ToDuration casts an interface to a time.Duration type. func ToDuration(i interface{}) time.Duration { v, _ := ToDurationE(i) return v } +// ToFloat64 casts an interface to a float64 type. func ToFloat64(i interface{}) float64 { v, _ := ToFloat64E(i) return v } +// ToFloat32 casts an interface to a float32 type. +func ToFloat32(i interface{}) float32 { + v, _ := ToFloat32E(i) + return v +} + +// ToInt64 casts an interface to an int64 type. func ToInt64(i interface{}) int64 { v, _ := ToInt64E(i) return v } +// ToInt32 casts an interface to an int32 type. +func ToInt32(i interface{}) int32 { + v, _ := ToInt32E(i) + return v +} + +// ToInt16 casts an interface to an int16 type. +func ToInt16(i interface{}) int16 { + v, _ := ToInt16E(i) + return v +} + +// ToInt8 casts an interface to an int8 type. +func ToInt8(i interface{}) int8 { + v, _ := ToInt8E(i) + return v +} + +// ToInt casts an interface to an int type. func ToInt(i interface{}) int { v, _ := ToIntE(i) return v } +// ToUint casts an interface to a uint type. +func ToUint(i interface{}) uint { + v, _ := ToUintE(i) + return v +} + +// ToUint64 casts an interface to a uint64 type. +func ToUint64(i interface{}) uint64 { + v, _ := ToUint64E(i) + return v +} + +// ToUint32 casts an interface to a uint32 type. +func ToUint32(i interface{}) uint32 { + v, _ := ToUint32E(i) + return v +} + +// ToUint16 casts an interface to a uint16 type. +func ToUint16(i interface{}) uint16 { + v, _ := ToUint16E(i) + return v +} + +// ToUint8 casts an interface to a uint8 type. +func ToUint8(i interface{}) uint8 { + v, _ := ToUint8E(i) + return v +} + +// ToString casts an interface to a string type. func ToString(i interface{}) string { v, _ := ToStringE(i) return v } +// ToStringMapString casts an interface to a map[string]string type. func ToStringMapString(i interface{}) map[string]string { v, _ := ToStringMapStringE(i) return v } +// ToStringMapStringSlice casts an interface to a map[string][]string type. func ToStringMapStringSlice(i interface{}) map[string][]string { v, _ := ToStringMapStringSliceE(i) return v } +// ToStringMapBool casts an interface to a map[string]bool type. func ToStringMapBool(i interface{}) map[string]bool { v, _ := ToStringMapBoolE(i) return v } +// ToStringMapInt casts an interface to a map[string]int type. +func ToStringMapInt(i interface{}) map[string]int { + v, _ := ToStringMapIntE(i) + return v +} + +// ToStringMapInt64 casts an interface to a map[string]int64 type. +func ToStringMapInt64(i interface{}) map[string]int64 { + v, _ := ToStringMapInt64E(i) + return v +} + +// ToStringMap casts an interface to a map[string]interface{} type. func ToStringMap(i interface{}) map[string]interface{} { v, _ := ToStringMapE(i) return v } +// ToSlice casts an interface to a []interface{} type. func ToSlice(i interface{}) []interface{} { v, _ := ToSliceE(i) return v } +// ToBoolSlice casts an interface to a []bool type. +func ToBoolSlice(i interface{}) []bool { + v, _ := ToBoolSliceE(i) + return v +} + +// ToStringSlice casts an interface to a []string type. func ToStringSlice(i interface{}) []string { v, _ := ToStringSliceE(i) return v } +// ToIntSlice casts an interface to a []int type. func ToIntSlice(i interface{}) []int { v, _ := ToIntSliceE(i) return v } + +// ToDurationSlice casts an interface to a []time.Duration type. +func ToDurationSlice(i interface{}) []time.Duration { + v, _ := ToDurationSliceE(i) + return v +} diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go index 237789644..cd9c04885 100644 --- a/vendor/github.com/spf13/cast/caste.go +++ b/vendor/github.com/spf13/cast/caste.go @@ -6,62 +6,102 @@ package cast import ( + "encoding/json" + "errors" "fmt" "html/template" "reflect" "strconv" "strings" "time" - - jww "github.com/spf13/jwalterweatherman" ) -// ToTimeE casts an empty interface to time.Time. +var errNegativeNotAllowed = errors.New("unable to cast negative value") + +type float64EProvider interface { + Float64() (float64, error) +} + +type float64Provider interface { + Float64() float64 +} + +// ToTimeE casts an interface to a time.Time type. func ToTimeE(i interface{}) (tim time.Time, err error) { + return ToTimeInDefaultLocationE(i, time.UTC) +} + +// ToTimeInDefaultLocationE casts an empty interface to time.Time, +// interpreting inputs without a timezone to be in the given location, +// or the local timezone if nil. +func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) { i = indirect(i) - jww.DEBUG.Println("ToTimeE called on type:", reflect.TypeOf(i)) - switch s := i.(type) { + switch v := i.(type) { case time.Time: - return s, nil + return v, nil case string: - d, e := StringToDate(s) - if e == nil { - return d, nil + return StringToDateInDefaultLocation(v, location) + case json.Number: + s, err1 := ToInt64E(v) + if err1 != nil { + return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) } - return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e) + return time.Unix(s, 0), nil + case int: + return time.Unix(int64(v), 0), nil + case int64: + return time.Unix(v, 0), nil + case int32: + return time.Unix(int64(v), 0), nil + case uint: + return time.Unix(int64(v), 0), nil + case uint64: + return time.Unix(int64(v), 0), nil + case uint32: + return time.Unix(int64(v), 0), nil default: - return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i) + return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) } } -// ToDurationE casts an empty interface to time.Duration. +// ToDurationE casts an interface to a time.Duration type. func ToDurationE(i interface{}) (d time.Duration, err error) { i = indirect(i) - jww.DEBUG.Println("ToDurationE called on type:", reflect.TypeOf(i)) switch s := i.(type) { case time.Duration: return s, nil - case int64: - d = time.Duration(s) + case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8: + d = time.Duration(ToInt64(s)) return - case float64: - d = time.Duration(s) + case float32, float64: + d = time.Duration(ToFloat64(s)) return case string: - d, err = time.ParseDuration(s) + if strings.ContainsAny(s, "nsuµmh") { + d, err = time.ParseDuration(s) + } else { + d, err = time.ParseDuration(s + "ns") + } + return + case float64EProvider: + var v float64 + v, err = s.Float64() + d = time.Duration(v) + return + case float64Provider: + d = time.Duration(s.Float64()) return default: - err = fmt.Errorf("Unable to Cast %#v to Duration\n", i) + err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i) return } } -// ToBoolE casts an empty interface to a bool. +// ToBoolE casts an interface to a bool type. func ToBoolE(i interface{}) (bool, error) { i = indirect(i) - jww.DEBUG.Println("ToBoolE called on type:", reflect.TypeOf(i)) switch b := i.(type) { case bool: @@ -69,21 +109,52 @@ func ToBoolE(i interface{}) (bool, error) { case nil: return false, nil case int: - if i.(int) != 0 { - return true, nil - } - return false, nil + return b != 0, nil + case int64: + return b != 0, nil + case int32: + return b != 0, nil + case int16: + return b != 0, nil + case int8: + return b != 0, nil + case uint: + return b != 0, nil + case uint64: + return b != 0, nil + case uint32: + return b != 0, nil + case uint16: + return b != 0, nil + case uint8: + return b != 0, nil + case float64: + return b != 0, nil + case float32: + return b != 0, nil + case time.Duration: + return b != 0, nil case string: return strconv.ParseBool(i.(string)) + case json.Number: + v, err := ToInt64E(b) + if err == nil { + return v != 0, nil + } + return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) default: - return false, fmt.Errorf("Unable to Cast %#v to bool", i) + return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) } } -// ToFloat64E casts an empty interface to a float64. +// ToFloat64E casts an interface to a float64 type. func ToFloat64E(i interface{}) (float64, error) { i = indirect(i) - jww.DEBUG.Println("ToFloat64E called on type:", reflect.TypeOf(i)) + + intv, ok := toInt(i) + if ok { + return float64(intv), nil + } switch s := i.(type) { case float64: @@ -98,63 +169,318 @@ func ToFloat64E(i interface{}) (float64, error) { return float64(s), nil case int8: return float64(s), nil - case int: + case uint: + return float64(s), nil + case uint64: + return float64(s), nil + case uint32: + return float64(s), nil + case uint16: + return float64(s), nil + case uint8: return float64(s), nil case string: v, err := strconv.ParseFloat(s, 64) if err == nil { - return float64(v), nil + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case float64EProvider: + v, err := s.Float64() + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case float64Provider: + return s.Float64(), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + } +} + +// ToFloat32E casts an interface to a float32 type. +func ToFloat32E(i interface{}) (float32, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return float32(intv), nil + } + + switch s := i.(type) { + case float64: + return float32(s), nil + case float32: + return s, nil + case int64: + return float32(s), nil + case int32: + return float32(s), nil + case int16: + return float32(s), nil + case int8: + return float32(s), nil + case uint: + return float32(s), nil + case uint64: + return float32(s), nil + case uint32: + return float32(s), nil + case uint16: + return float32(s), nil + case uint8: + return float32(s), nil + case string: + v, err := strconv.ParseFloat(s, 32) + if err == nil { + return float32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case float64EProvider: + v, err := s.Float64() + if err == nil { + return float32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case float64Provider: + return float32(s.Float64()), nil + case bool: + if s { + return 1, nil } - return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) + return 0, nil + case nil: + return 0, nil default: - return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) } } -// ToInt64E casts an empty interface to an int64. +// ToInt64E casts an interface to an int64 type. func ToInt64E(i interface{}) (int64, error) { i = indirect(i) - jww.DEBUG.Println("ToInt64E called on type:", reflect.TypeOf(i)) + + intv, ok := toInt(i) + if ok { + return int64(intv), nil + } switch s := i.(type) { case int64: return s, nil - case int: - return int64(s), nil case int32: return int64(s), nil case int16: return int64(s), nil case int8: return int64(s), nil + case uint: + return int64(s), nil + case uint64: + return int64(s), nil + case uint32: + return int64(s), nil + case uint16: + return int64(s), nil + case uint8: + return int64(s), nil + case float64: + return int64(s), nil + case float32: + return int64(s), nil case string: - v, err := strconv.ParseInt(s, 0, 0) + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) if err == nil { return v, nil } - return 0, fmt.Errorf("Unable to Cast %#v to int64", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case json.Number: + return ToInt64E(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + } +} + +// ToInt32E casts an interface to an int32 type. +func ToInt32E(i interface{}) (int32, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return int32(intv), nil + } + + switch s := i.(type) { + case int64: + return int32(s), nil + case int32: + return s, nil + case int16: + return int32(s), nil + case int8: + return int32(s), nil + case uint: + return int32(s), nil + case uint64: + return int32(s), nil + case uint32: + return int32(s), nil + case uint16: + return int32(s), nil + case uint8: + return int32(s), nil case float64: - return int64(s), nil + return int32(s), nil + case float32: + return int32(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + return int32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + case json.Number: + return ToInt32E(string(s)) case bool: - if bool(s) { - return int64(1), nil + if s { + return 1, nil } - return int64(0), nil + return 0, nil case nil: - return int64(0), nil + return 0, nil default: - return int64(0), fmt.Errorf("Unable to Cast %#v to int64", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) } } -// ToIntE casts an empty interface to an int. -func ToIntE(i interface{}) (int, error) { +// ToInt16E casts an interface to an int16 type. +func ToInt16E(i interface{}) (int16, error) { i = indirect(i) - jww.DEBUG.Println("ToIntE called on type:", reflect.TypeOf(i)) + + intv, ok := toInt(i) + if ok { + return int16(intv), nil + } switch s := i.(type) { - case int: + case int64: + return int16(s), nil + case int32: + return int16(s), nil + case int16: + return s, nil + case int8: + return int16(s), nil + case uint: + return int16(s), nil + case uint64: + return int16(s), nil + case uint32: + return int16(s), nil + case uint16: + return int16(s), nil + case uint8: + return int16(s), nil + case float64: + return int16(s), nil + case float32: + return int16(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + return int16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + case json.Number: + return ToInt16E(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + } +} + +// ToInt8E casts an interface to an int8 type. +func ToInt8E(i interface{}) (int8, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return int8(intv), nil + } + + switch s := i.(type) { + case int64: + return int8(s), nil + case int32: + return int8(s), nil + case int16: + return int8(s), nil + case int8: return s, nil + case uint: + return int8(s), nil + case uint64: + return int8(s), nil + case uint32: + return int8(s), nil + case uint16: + return int8(s), nil + case uint8: + return int8(s), nil + case float64: + return int8(s), nil + case float32: + return int8(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + return int8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + case json.Number: + return ToInt8E(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + } +} + +// ToIntE casts an interface to an int type. +func ToIntE(i interface{}) (int, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return intv, nil + } + + switch s := i.(type) { case int64: return int(s), nil case int32: @@ -163,23 +489,417 @@ func ToIntE(i interface{}) (int, error) { return int(s), nil case int8: return int(s), nil + case uint: + return int(s), nil + case uint64: + return int(s), nil + case uint32: + return int(s), nil + case uint16: + return int(s), nil + case uint8: + return int(s), nil + case float64: + return int(s), nil + case float32: + return int(s), nil case string: - v, err := strconv.ParseInt(s, 0, 0) + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) if err == nil { return int(v), nil } - return 0, fmt.Errorf("Unable to Cast %#v to int", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case json.Number: + return ToIntE(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + } +} + +// ToUintE casts an interface to a uint type. +func ToUintE(i interface{}) (uint, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + case json.Number: + return ToUintE(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case uint: + return s, nil + case uint64: + return uint(s), nil + case uint32: + return uint(s), nil + case uint16: + return uint(s), nil + case uint8: + return uint(s), nil case float64: - return int(s), nil + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + } +} + +// ToUint64E casts an interface to a uint64 type. +func ToUint64E(i interface{}) (uint64, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint64(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint64(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + case json.Number: + return ToUint64E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case uint: + return uint64(s), nil + case uint64: + return s, nil + case uint32: + return uint64(s), nil + case uint16: + return uint64(s), nil + case uint8: + return uint64(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil case bool: - if bool(s) { + if s { return 1, nil } return 0, nil case nil: return 0, nil default: - return 0, fmt.Errorf("Unable to Cast %#v to int", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + } +} + +// ToUint32E casts an interface to a uint32 type. +func ToUint32E(i interface{}) (uint32, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint32(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + case json.Number: + return ToUint32E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case uint: + return uint32(s), nil + case uint64: + return uint32(s), nil + case uint32: + return s, nil + case uint16: + return uint32(s), nil + case uint8: + return uint32(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + } +} + +// ToUint16E casts an interface to a uint16 type. +func ToUint16E(i interface{}) (uint16, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint16(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + case json.Number: + return ToUint16E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case uint: + return uint16(s), nil + case uint64: + return uint16(s), nil + case uint32: + return uint16(s), nil + case uint16: + return s, nil + case uint8: + return uint16(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + } +} + +// ToUint8E casts an interface to a uint type. +func ToUint8E(i interface{}) (uint8, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint8(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) + case json.Number: + return ToUint8E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case uint: + return uint8(s), nil + case uint64: + return uint8(s), nil + case uint32: + return uint8(s), nil + case uint16: + return uint8(s), nil + case uint8: + return s, nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) } } @@ -212,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} { return nil } - var errorType = reflect.TypeOf((*error)(nil)).Elem() - var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + errorType := reflect.TypeOf((*error)(nil)).Elem() + fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem() v := reflect.ValueOf(a) for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { @@ -222,10 +942,9 @@ func indirectToStringerOrError(a interface{}) interface{} { return v.Interface() } -// ToStringE casts an empty interface to a string. +// ToStringE casts an interface to a string type. func ToStringE(i interface{}) (string, error) { i = indirectToStringerOrError(i) - jww.DEBUG.Println("ToStringE called on type:", reflect.TypeOf(i)) switch s := i.(type) { case string: @@ -233,11 +952,31 @@ func ToStringE(i interface{}) (string, error) { case bool: return strconv.FormatBool(s), nil case float64: - return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil - case int64: - return strconv.FormatInt(i.(int64), 10), nil + return strconv.FormatFloat(s, 'f', -1, 64), nil + case float32: + return strconv.FormatFloat(float64(s), 'f', -1, 32), nil case int: - return strconv.FormatInt(int64(i.(int)), 10), nil + return strconv.Itoa(s), nil + case int64: + return strconv.FormatInt(s, 10), nil + case int32: + return strconv.Itoa(int(s)), nil + case int16: + return strconv.FormatInt(int64(s), 10), nil + case int8: + return strconv.FormatInt(int64(s), 10), nil + case uint: + return strconv.FormatUint(uint64(s), 10), nil + case uint64: + return strconv.FormatUint(uint64(s), 10), nil + case uint32: + return strconv.FormatUint(uint64(s), 10), nil + case uint16: + return strconv.FormatUint(uint64(s), 10), nil + case uint8: + return strconv.FormatUint(uint64(s), 10), nil + case json.Number: + return s.String(), nil case []byte: return string(s), nil case template.HTML: @@ -257,15 +996,13 @@ func ToStringE(i interface{}) (string, error) { case error: return s.Error(), nil default: - return "", fmt.Errorf("Unable to Cast %#v to string", i) + return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i) } } -// ToStringMapStringE casts an empty interface to a map[string]string. +// ToStringMapStringE casts an interface to a map[string]string type. func ToStringMapStringE(i interface{}) (map[string]string, error) { - jww.DEBUG.Println("ToStringMapStringE called on type:", reflect.TypeOf(i)) - - var m = map[string]string{} + m := map[string]string{} switch v := i.(type) { case map[string]string: @@ -285,16 +1022,17 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) { m[ToString(k)] = ToString(val) } return m, nil + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i) } } -// ToStringMapStringSliceE casts an empty interface to a map[string][]string. +// ToStringMapStringSliceE casts an interface to a map[string][]string type. func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { - jww.DEBUG.Println("ToStringMapStringSliceE called on type:", reflect.TypeOf(i)) - - var m = map[string][]string{} + m := map[string][]string{} switch v := i.(type) { case map[string][]string: @@ -310,7 +1048,14 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { } case map[string]interface{}: for k, val := range v { - m[ToString(k)] = []string{ToString(val)} + switch vt := val.(type) { + case []interface{}: + m[ToString(k)] = ToStringSlice(vt) + case []string: + m[ToString(k)] = vt + default: + m[ToString(k)] = []string{ToString(val)} + } } return m, nil case map[interface{}][]string: @@ -332,25 +1077,26 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { for k, val := range v { key, err := ToStringE(k) if err != nil { - return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) } value, err := ToStringSliceE(val) if err != nil { - return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) } m[key] = value } + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) } return m, nil } -// ToStringMapBoolE casts an empty interface to a map[string]bool. +// ToStringMapBoolE casts an interface to a map[string]bool type. func ToStringMapBoolE(i interface{}) (map[string]bool, error) { - jww.DEBUG.Println("ToStringMapBoolE called on type:", reflect.TypeOf(i)) - - var m = map[string]bool{} + m := map[string]bool{} switch v := i.(type) { case map[interface{}]interface{}: @@ -365,16 +1111,17 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) { return m, nil case map[string]bool: return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i) } } -// ToStringMapE casts an empty interface to a map[string]interface{}. +// ToStringMapE casts an interface to a map[string]interface{} type. func ToStringMapE(i interface{}) (map[string]interface{}, error) { - jww.DEBUG.Println("ToStringMapE called on type:", reflect.TypeOf(i)) - - var m = map[string]interface{}{} + m := map[string]interface{}{} switch v := i.(type) { case map[interface{}]interface{}: @@ -384,37 +1131,143 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) { return m, nil case map[string]interface{}: return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i) } } -// ToSliceE casts an empty interface to a []interface{}. -func ToSliceE(i interface{}) ([]interface{}, error) { - jww.DEBUG.Println("ToSliceE called on type:", reflect.TypeOf(i)) +// ToStringMapIntE casts an interface to a map[string]int{} type. +func ToStringMapIntE(i interface{}) (map[string]int, error) { + m := map[string]int{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt(val) + } + return m, nil + case map[string]int: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToIntE(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} +// ToStringMapInt64E casts an interface to a map[string]int64{} type. +func ToStringMapInt64E(i interface{}) (map[string]int64, error) { + m := map[string]int64{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt64(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt64(val) + } + return m, nil + case map[string]int64: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToInt64E(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} + +// ToSliceE casts an interface to a []interface{} type. +func ToSliceE(i interface{}) ([]interface{}, error) { var s []interface{} switch v := i.(type) { case []interface{}: - for _, u := range v { - s = append(s, u) - } - return s, nil + return append(s, v...), nil case []map[string]interface{}: for _, u := range v { s = append(s, u) } return s, nil default: - return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i)) + return s, fmt.Errorf("unable to cast %#v of type %T to []interface{}", i, i) } } -// ToStringSliceE casts an empty interface to a []string. -func ToStringSliceE(i interface{}) ([]string, error) { - jww.DEBUG.Println("ToStringSliceE called on type:", reflect.TypeOf(i)) +// ToBoolSliceE casts an interface to a []bool type. +func ToBoolSliceE(i interface{}) ([]bool, error) { + if i == nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + + switch v := i.(type) { + case []bool: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]bool, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToBoolE(s.Index(j).Interface()) + if err != nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + a[j] = val + } + return a, nil + default: + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } +} +// ToStringSliceE casts an interface to a []string type. +func ToStringSliceE(i interface{}) ([]string, error) { var a []string switch v := i.(type) { @@ -425,25 +1278,58 @@ func ToStringSliceE(i interface{}) ([]string, error) { return a, nil case []string: return v, nil + case []int8: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int32: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int64: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []float32: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []float64: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil case string: return strings.Fields(v), nil + case []error: + for _, err := range i.([]error) { + a = append(a, err.Error()) + } + return a, nil case interface{}: str, err := ToStringE(v) if err != nil { - return a, fmt.Errorf("Unable to Cast %#v to []string", i) + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) } return []string{str}, nil default: - return a, fmt.Errorf("Unable to Cast %#v to []string", i) + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) } } -// ToIntSliceE casts an empty interface to a []int. +// ToIntSliceE casts an interface to a []int type. func ToIntSliceE(i interface{}) ([]int, error) { - jww.DEBUG.Println("ToIntSliceE called on type:", reflect.TypeOf(i)) - if i == nil { - return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) } switch v := i.(type) { @@ -459,42 +1345,166 @@ func ToIntSliceE(i interface{}) ([]int, error) { for j := 0; j < s.Len(); j++ { val, err := ToIntE(s.Index(j).Interface()) if err != nil { - return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) } a[j] = val } return a, nil default: - return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) } } -// StringToDate casts an empty interface to a time.Time. +// ToDurationSliceE casts an interface to a []time.Duration type. +func ToDurationSliceE(i interface{}) ([]time.Duration, error) { + if i == nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + + switch v := i.(type) { + case []time.Duration: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]time.Duration, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToDurationE(s.Index(j).Interface()) + if err != nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + a[j] = val + } + return a, nil + default: + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } +} + +// StringToDate attempts to parse a string into a time.Time type using a +// predefined list of formats. If no suitable format is found, an error is +// returned. func StringToDate(s string) (time.Time, error) { - return parseDateWith(s, []string{ - time.RFC3339, - "2006-01-02T15:04:05", // iso8601 without timezone - time.RFC1123Z, - time.RFC1123, - time.RFC822Z, - time.RFC822, - time.ANSIC, - time.UnixDate, - time.RubyDate, - "2006-01-02 15:04:05Z07:00", - "02 Jan 06 15:04 MST", - "2006-01-02", - "02 Jan 2006", - "2006-01-02 15:04:05 -07:00", - "2006-01-02 15:04:05 -0700", - }) -} - -func parseDateWith(s string, dates []string) (d time.Time, e error) { - for _, dateType := range dates { - if d, e = time.Parse(dateType, s); e == nil { + return parseDateWith(s, time.UTC, timeFormats) +} + +// StringToDateInDefaultLocation casts an empty interface to a time.Time, +// interpreting inputs without a timezone to be in the given location, +// or the local timezone if nil. +func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) { + return parseDateWith(s, location, timeFormats) +} + +type timeFormatType int + +const ( + timeFormatNoTimezone timeFormatType = iota + timeFormatNamedTimezone + timeFormatNumericTimezone + timeFormatNumericAndNamedTimezone + timeFormatTimeOnly +) + +type timeFormat struct { + format string + typ timeFormatType +} + +func (f timeFormat) hasTimezone() bool { + // We don't include the formats with only named timezones, see + // https://github.com/golang/go/issues/19694#issuecomment-289103522 + return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone +} + +var timeFormats = []timeFormat{ + // Keep common formats at the top. + {"2006-01-02", timeFormatNoTimezone}, + {time.RFC3339, timeFormatNumericTimezone}, + {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone + {time.RFC1123Z, timeFormatNumericTimezone}, + {time.RFC1123, timeFormatNamedTimezone}, + {time.RFC822Z, timeFormatNumericTimezone}, + {time.RFC822, timeFormatNamedTimezone}, + {time.RFC850, timeFormatNamedTimezone}, + {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() + {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon + {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon + {"2006-01-02 15:04:05", timeFormatNoTimezone}, + {time.ANSIC, timeFormatNoTimezone}, + {time.UnixDate, timeFormatNamedTimezone}, + {time.RubyDate, timeFormatNumericTimezone}, + {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, + {"02 Jan 2006", timeFormatNoTimezone}, + {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, + {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, + {time.Kitchen, timeFormatTimeOnly}, + {time.Stamp, timeFormatTimeOnly}, + {time.StampMilli, timeFormatTimeOnly}, + {time.StampMicro, timeFormatTimeOnly}, + {time.StampNano, timeFormatTimeOnly}, +} + +func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) { + for _, format := range formats { + if d, e = time.Parse(format.format, s); e == nil { + + // Some time formats have a zone name, but no offset, so it gets + // put in that zone name (not the default one passed in to us), but + // without that zone's offset. So set the location manually. + if format.typ <= timeFormatNamedTimezone { + if location == nil { + location = time.Local + } + year, month, day := d.Date() + hour, min, sec := d.Clock() + d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location) + } + return } } - return d, fmt.Errorf("Unable to parse date: %s", s) + return d, fmt.Errorf("unable to parse date: %s", s) +} + +// jsonStringToObject attempts to unmarshall a string as JSON into +// the object passed as pointer. +func jsonStringToObject(s string, v interface{}) error { + data := []byte(s) + return json.Unmarshal(data, v) +} + +// toInt returns the int value of v if v or v's underlying type +// is an int. +// Note that this will return false for int64 etc. types. +func toInt(v interface{}) (int, bool) { + switch v := v.(type) { + case int: + return v, true + case time.Weekday: + return int(v), true + case time.Month: + return int(v), true + default: + return 0, false + } +} + +func trimZeroDecimal(s string) string { + var foundZero bool + for i := len(s); i > 0; i-- { + switch s[i-1] { + case '.': + if foundZero { + return s[:i-1] + } + case '0': + foundZero = true + default: + return s + } + } + return s } diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore index 36d1a84d3..c7b459e4d 100644 --- a/vendor/github.com/spf13/cobra/.gitignore +++ b/vendor/github.com/spf13/cobra/.gitignore @@ -19,6 +19,21 @@ _cgo_export.* _testmain.go -*.exe +# Vim files https://github.com/github/gitignore/blob/master/Global/Vim.gitignore +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags +*.exe cobra.test +bin + +.idea/ +*.iml diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml deleted file mode 100644 index 2bbf62312..000000000 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go -go: - - 1.4.3 - - 1.5.4 - - 1.6.2 - - tip - -matrix: - allow_failures: - - go: tip - -before_install: - - mkdir -p bin - - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.4.3/shellcheck - - chmod +x bin/shellcheck -script: - - PATH=$PATH:$PWD/bin go test -v ./... - - go build diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 34c79eb8e..6444f4b7f 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -1,64 +1,35 @@ -![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) +![cobra logo](assets/CobraMain.png) -Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files. +Cobra is a library for creating powerful modern CLI applications. -Many of the most widely used Go projects are built using Cobra including: +Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), +[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to +name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra. -* [Kubernetes](http://kubernetes.io/) -* [Hugo](http://gohugo.io) -* [rkt](https://github.com/coreos/rkt) -* [etcd](https://github.com/coreos/etcd) -* [Docker (distribution)](https://github.com/docker/distribution) -* [OpenShift](https://www.openshift.com/) -* [Delve](https://github.com/derekparker/delve) -* [GopherJS](http://www.gopherjs.org/) -* [CockroachDB](http://www.cockroachlabs.com/) -* [Bleve](http://www.blevesearch.com/) -* [ProjectAtomic (enterprise)](http://www.projectatomic.io/) -* [Parse (CLI)](https://parse.com/) -* [GiantSwarm's swarm](https://github.com/giantswarm/cli) -* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) - - -[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) -[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) -[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) - -![cobra](https://cloud.githubusercontent.com/assets/173412/10911369/84832a8e-8212-11e5-9f82-cc96660a4794.gif) +[![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) +[![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra) +[![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199) # Overview Cobra is a library providing a simple interface to create powerful modern CLI interfaces similar to git & go tools. -Cobra is also an application that will generate your application scaffolding to rapidly -develop a Cobra-based application. - Cobra provides: * Easy subcommand-based CLIs: `app server`, `app fetch`, etc. * Fully POSIX-compliant flags (including short & long versions) * Nested subcommands * Global, local and cascading flags -* Easy generation of applications & commands with `cobra create appname` & `cobra add cmdname` * Intelligent suggestions (`app srver`... did you mean `app server`?) * Automatic help generation for commands and flags -* Automatic detailed help for `app help [command]` +* Grouping help for subcommands * Automatic help flag recognition of `-h`, `--help`, etc. -* Automatically generated bash autocomplete for your application +* Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell) * Automatically generated man pages for your application * Command aliases so you can change things without breaking them -* The flexibilty to define your own help, usage, etc. -* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps - -Cobra has an exceptionally clean interface and simple design without needless -constructors or initialization methods. - -Applications built with Cobra commands are designed to be as user-friendly as -possible. Flags can be placed before or after the command (as long as a -confusing space isn’t provided). Both short and long flags can be used. A -command need not even be fully typed. Help is automatically generated and -available for the application or for a specific command using either the help -command or the `--help` flag. +* The flexibility to define your own help, usage, etc. +* Optional seamless integration with [viper](https://github.com/spf13/viper) for 12-factor apps # Concepts @@ -66,23 +37,23 @@ Cobra is built on a structure of commands, arguments & flags. **Commands** represent actions, **Args** are things and **Flags** are modifiers for those actions. -The best applications will read like sentences when used. Users will know how -to use the application because they will natively understand how to use it. +The best applications read like sentences when used, and as a result, users +intuitively know how to interact with them. The pattern to follow is -`APPNAME VERB NOUN --ADJECTIVE.` +`APPNAME VERB NOUN --ADJECTIVE` or -`APPNAME COMMAND ARG --FLAG` +`APPNAME COMMAND ARG --FLAG`. A few good real world examples may better illustrate this point. In the following example, 'server' is a command, and 'port' is a flag: - > hugo server --port=1313 + hugo server --port=1313 In this command we are telling Git to clone the url bare. - > git clone URL --bare + git clone URL --bare ## Commands @@ -92,20 +63,11 @@ have children commands and optionally run an action. In the example above, 'server' is the command. -A Command has the following structure: - -```go -type Command struct { - Use string // The one-line usage message. - Short string // The short description shown in the 'help' output. - Long string // The long message shown in the 'help ' output. - Run func(cmd *Command, args []string) // Run runs the command. -} -``` +[More about cobra.Command](https://pkg.go.dev/github.com/spf13/cobra#Command) ## Flags -A Flag is a way to modify the behavior of a command. Cobra supports +A flag is a way to modify the behavior of a command. Cobra supports fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). A Cobra command can define flags that persist through to children commands and flags that are only available to that command. @@ -113,780 +75,38 @@ and flags that are only available to that command. In the example above, 'port' is the flag. Flag functionality is provided by the [pflag -library](https://github.com/ogier/pflag), a fork of the flag standard library +library](https://github.com/spf13/pflag), a fork of the flag standard library which maintains the same interface while adding POSIX compliance. -## Usage - -Cobra works by creating a set of commands and then organizing them into a tree. -The tree defines the structure of the application. - -Once each command is defined with its corresponding flags, then the -tree is assigned to the commander which is finally executed. - # Installing Using Cobra is easy. First, use `go get` to install the latest version -of the library. This command will install the `cobra` generator executible -along with the library: - - > go get -v github.com/spf13/cobra/cobra - -Next, include Cobra in your application: - -```go -import "github.com/spf13/cobra" -``` - -# Getting Started - -While you are welcome to provide your own organization, typically a Cobra based -application will follow the following organizational structure. - -``` - ▾ appName/ - ▾ cmd/ - add.go - your.go - commands.go - here.go - main.go -``` - -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. - -```go -package main - -import "{pathToYourApp}/cmd" - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} -``` - -## Using the Cobra Generator - -Cobra provides its own program that will create your application and add any -commands you want. It's the easiest way to incorporate Cobra into your application. - -### cobra init - -The `cobra init [yourApp]` command will create your initial application code -for you. It is a very powerful application that will populate your program with -the right structure so you can immediately enjoy all the benefits of Cobra. It -will also automatically apply the license you specify to your application. - -Cobra init is pretty smart. You can provide it a full path, or simply a path -similar to what is expected in the import. - -``` -cobra init github.com/spf13/newAppName -``` - -### cobra add - -Once an application is initialized Cobra can create additional commands for you. -Let's say you created an app and you wanted the following commands for it: - -* app serve -* app config -* app config create - -In your project directory (where your main.go file is) you would run the following: - -``` -cobra add serve -cobra add config -cobra add create -p 'configCmd' -``` - -Once you have run these three commands you would have an app structure that would look like: - -``` - ▾ app/ - ▾ cmd/ - serve.go - config.go - create.go - main.go -``` - -at this point you can run `go run main.go` and it would run your app. `go run -main.go serve`, `go run main.go config`, `go run main.go config create` along -with `go run main.go help serve`, etc would all work. - -Obviously you haven't added your own code to these yet, the commands are ready -for you to give them their tasks. Have fun. - -### Configuring the cobra generator - -The cobra generator will be easier to use if you provide a simple configuration -file which will help you eliminate providing a bunch of repeated information in -flags over and over. - -An example ~/.cobra.yaml file: - -```yaml -author: Steve Francia -license: MIT -``` - -You can specify no license by setting `license` to `none` or you can specify -a custom license: - -```yaml -license: - header: This file is part of {{ .appName }}. - text: | - {{ .copyright }} - - This is my license. There are many like it, but this one is mine. - My license is my best friend. It is my life. I must master it as I must - master my life. -``` - -## Manually implementing Cobra - -To manually implement cobra you need to create a bare main.go file and a RootCmd file. -You will optionally provide additional commands as you see fit. - -### Create the root command - -The root command represents your binary itself. - - -#### Manually create rootCmd - -Cobra doesn't require any special constructors. Simply create your commands. - -Ideally you place this in app/cmd/root.go: - -```go -var RootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, -} -``` - -You will additionally define flags and handle configuration in your init() function. - -for example cmd/root.go: - -```go -func init() { - cobra.OnInitialize(initConfig) - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") - RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") - RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") - RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") - viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) - viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") -} -``` - -### Create your main.go - -With the root command you need to have your main function execute it. -Execute should be run on the root for clarity, though it can be called on any command. - -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. - -```go -package main - -import "{pathToYourApp}/cmd" - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} -``` - - -### Create additional commands - -Additional commands can be defined and typically are each given their own file -inside of the cmd/ directory. - -If you wanted to create a version command you would create cmd/version.go and -populate it with the following: - -```go -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - RootCmd.AddCommand(versionCmd) -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, -} -``` - -### Attach command to its parent - - -If you notice in the above example we attach the command to its parent. In -this case the parent is the rootCmd. In this example we are attaching it to the -root, but commands can be attached at any level. - -```go -RootCmd.AddCommand(versionCmd) -``` - -### Remove a command from its parent - -Removing a command is not a common action in simple programs, but it allows 3rd -parties to customize an existing command tree. +of the library. -In this example, we remove the existing `VersionCmd` command of an existing -root command, and we replace it with our own version: - -```go -mainlib.RootCmd.RemoveCommand(mainlib.VersionCmd) -mainlib.RootCmd.AddCommand(versionCmd) -``` - -## Working with Flags - -Flags provide modifiers to control how the action command operates. - -### Assign flags to a command - -Since the flags are defined and used in different locations, we need to -define a variable outside with the correct scope to assign the flag to -work with. - -```go -var Verbose bool -var Source string -``` - -There are two different approaches to assign a flag. - -### Persistent Flags - -A flag can be 'persistent' meaning that this flag will be available to the -command it's assigned to as well as every command under that command. For -global flags, assign a flag as a persistent flag on the root. - -```go -RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") -``` - -### Local Flags - -A flag can also be assigned locally which will only apply to that specific command. - -```go -RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") -``` - - -## Example - -In the example below, we have defined three commands. Two are at the top level -and one (cmdTimes) is a child of one of the top commands. In this case the root -is not executable meaning that a subcommand is required. This is accomplished -by not providing a 'Run' for the 'rootCmd'. - -We have only defined one flag for a single command. - -More documentation about flags is available at https://github.com/spf13/pflag - -```go -package main - -import ( - "fmt" - "strings" - - "github.com/spf13/cobra" -) - -func main() { - - var echoTimes int - - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. - For many years people have printed back to the screen. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. - Echo works a lot like print, except it has a child command. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdTimes = &cobra.Command{ - Use: "times [# times] [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing - a count and a string.`, - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } - - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() -} ``` - -For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). - -## The Help Command - -Cobra automatically adds a help command to your application when you have subcommands. -This will be called when a user runs 'app help'. Additionally, help will also -support all other commands as input. Say, for instance, you have a command called -'create' without any additional configuration; Cobra will work when 'app help -create' is called. Every command will automatically have the '--help' flag added. - -### Example - -The following output is automatically generated by Cobra. Nothing beyond the -command and flag definitions are needed. - - > hugo help - - hugo is the main command, used to build your Hugo site. - - Hugo is a Fast and Flexible Static Site Generator - built with love by spf13 and friends in Go. - - Complete documentation is available at http://gohugo.io/. - - Usage: - hugo [flags] - hugo [command] - - Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. - - Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - - Use "hugo [command] --help" for more information about a command. - - -Help is just a command like any other. There is no special logic or behavior -around it. In fact, you can provide your own if you want. - -### Defining your own help - -You can provide your own Help command or your own template for the default command to use. - -The default help command is - -```go -func (c *Command) initHelp() { - if c.helpCommand == nil { - c.helpCommand = &Command{ - Use: "help [command]", - Short: "Help about any command", - Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - Run: c.HelpFunc(), - } - } - c.AddCommand(c.helpCommand) -} +go get -u github.com/spf13/cobra@latest ``` -You can provide your own command, function or template through the following methods: - -```go -command.SetHelpCommand(cmd *Command) - -command.SetHelpFunc(f func(*Command, []string)) - -command.SetHelpTemplate(s string) -``` - -The latter two will also apply to any children commands. - -## Usage - -When the user provides an invalid flag or invalid command, Cobra responds by -showing the user the 'usage'. - -### Example -You may recognize this from the help above. That's because the default help -embeds the usage as part of its output. - - Usage: - hugo [flags] - hugo [command] - - Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. - - Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - -### Defining your own usage -You can provide your own usage function or template for Cobra to use. - -The default usage function is: - -```go -return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) - return err -} -``` - -Like help, the function and template are overridable through public methods: - -```go -command.SetUsageFunc(f func(*Command) error) - -command.SetUsageTemplate(s string) -``` - -## PreRun or PostRun Hooks - -It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherrited by children if they do not declare their own. These function are run in the following order: - -- `PersistentPreRun` -- `PreRun` -- `Run` -- `PostRun` -- `PersistentPostRun` - -An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: - -```go -package main - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func main() { - - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } - - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } - - rootCmd.AddCommand(subCmd) - - rootCmd.SetArgs([]string{""}) - _ = rootCmd.Execute() - fmt.Print("\n") - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - _ = rootCmd.Execute() -} -``` - - -## Alternative Error Handling - -Cobra also has functions where the return signature is an error. This allows for errors to bubble up to the top, -providing a way to handle the errors in one location. The current list of functions that return an error is: - -* PersistentPreRunE -* PreRunE -* RunE -* PostRunE -* PersistentPostRunE - -If you would like to silence the default `error` and `usage` output in favor of your own, you can set `SilenceUsage` -and `SilenceErrors` to `false` on the command. A child command respects these flags if they are set on the parent -command. - -**Example Usage using RunE:** - -```go -package main - -import ( - "errors" - "log" - - "github.com/spf13/cobra" -) - -func main() { - var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - RunE: func(cmd *cobra.Command, args []string) error { - // Do Stuff Here - return errors.New("some random error") - }, - } - - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } -} -``` - -## Suggestions when "unknown command" happens - -Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: - -``` -$ hugo srever -Error: unknown command "srever" for "hugo" - -Did you mean this? - server - -Run 'hugo --help' for usage. -``` - -Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. - -If you need to disable suggestions or tweak the string distance in your command, use: - -```go -command.DisableSuggestions = true -``` - -or +Next, include Cobra in your application: ```go -command.SuggestionsMinimumDistance = 1 +import "github.com/spf13/cobra" ``` -You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example: - -``` -$ kubectl remove -Error: unknown command "remove" for "kubectl" +# Usage +`cobra-cli` is a command line program to generate cobra applications and command files. +It will bootstrap your application scaffolding to rapidly +develop a Cobra-based application. It is the easiest way to incorporate Cobra into your application. -Did you mean this? - delete +It can be installed by running: -Run 'kubectl help' for usage. ``` - -## Generating Markdown-formatted documentation for your command - -Cobra can generate a Markdown-formatted document based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Markdown Docs](doc/md_docs.md). - -## Generating man pages for your command - -Cobra can generate a man page based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Man Docs](doc/man_docs.md). - -## Generating bash completions for your command - -Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). - -## Debugging - -Cobra provides a ‘DebugFlags’ method on a command which, when called, will print -out everything Cobra knows about the flags for each command. - -### Example - -```go -command.DebugFlags() +go install github.com/spf13/cobra-cli@latest ``` -## Release Notes -* **0.9.0** June 17, 2014 - * flags can appears anywhere in the args (provided they are unambiguous) - * --help prints usage screen for app or command - * Prefix matching for commands - * Cleaner looking help and usage output - * Extensive test suite -* **0.8.0** Nov 5, 2013 - * Reworked interface to remove commander completely - * Command now primary structure - * No initialization needed - * Usage & Help templates & functions definable at any level - * Updated Readme -* **0.7.0** Sept 24, 2013 - * Needs more eyes - * Test suite - * Support for automatic error messages - * Support for help command - * Support for printing to any io.Writer instead of os.Stderr - * Support for persistent flags which cascade down tree - * Ready for integration into Hugo -* **0.1.0** Sept 3, 2013 - * Implement first draft - -## Extensions - -Libraries for extending Cobra: - -* [cmdns](https://github.com/gosuri/cmdns): Enables name spacing a command's immediate children. It provides an alternative way to structure subcommands, similar to `heroku apps:create` and `ovrclk clusters:launch`. - -## ToDo -* Launch proper documentation site - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request - -## Contributors - -Names in no particular order: - -* [spf13](https://github.com/spf13), -[eparis](https://github.com/eparis), -[bep](https://github.com/bep), and many more! - -## License +For complete details on using the Cobra-CLI generator, please read [The Cobra Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) -Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) +For complete details on using the Cobra library, please read the [The Cobra User Guide](site/content/user_guide.md). +# License -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/spf13/cobra/trend.png)](https://bitdeli.com/free "Bitdeli Badge") +Cobra is released under the Apache 2.0 license. See [LICENSE.txt](LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 3f33bb0ec..f4d198cbc 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,6 +1,21 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( + "bytes" "fmt" "io" "os" @@ -10,35 +25,33 @@ import ( "github.com/spf13/pflag" ) +// Annotations for Bash completion. const ( - BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extentions" + BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" BashCompCustom = "cobra_annotation_bash_completion_custom" BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag" BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" ) -func preamble(out io.Writer, name string) error { - _, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name) - if err != nil { - return err - } - _, err = fmt.Fprint(out, ` -__debug() +func writePreamble(buf io.StringWriter, name string) { + WriteStringAndCheck(buf, fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) + WriteStringAndCheck(buf, fmt.Sprintf(` +__%[1]s_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } # Homebrew on Macs have version 1.3 of bash-completion which doesn't include # _init_completion. This is a very minimal version of that function. -__my_init_completion() +__%[1]s_init_completion() { COMPREPLY=() _get_comp_words_by_ref "$@" cur prev words cword } -__index_of_word() +__%[1]s_index_of_word() { local w word=$1 shift @@ -50,7 +63,7 @@ __index_of_word() index=-1 } -__contains_word() +__%[1]s_contains_word() { local w word=$1; shift for w in "$@"; do @@ -59,9 +72,104 @@ __contains_word() return 1 } -__handle_reply() +__%[1]s_handle_go_custom_completion() +{ + __%[1]s_debug "${FUNCNAME[0]}: cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}" + + local shellCompDirectiveError=%[3]d + local shellCompDirectiveNoSpace=%[4]d + local shellCompDirectiveNoFileComp=%[5]d + local shellCompDirectiveFilterFileExt=%[6]d + local shellCompDirectiveFilterDirs=%[7]d + + local out requestComp lastParam lastChar comp directive args + + # Prepare the command to request completions for the program. + # Calling ${words[0]} instead of directly %[1]s allows handling aliases + args=("${words[@]:1}") + # Disable ActiveHelp which is not supported for bash completion v1 + requestComp="%[8]s=0 ${words[0]} %[2]s ${args[*]}" + + lastParam=${words[$((${#words[@]}-1))]} + lastChar=${lastParam:$((${#lastParam}-1)):1} + __%[1]s_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}" + + if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then + # If the last parameter is complete (there is a space following it) + # We add an extra empty parameter so we can indicate this to the go method. + __%[1]s_debug "${FUNCNAME[0]}: Adding extra empty parameter" + requestComp="${requestComp} \"\"" + fi + + __%[1]s_debug "${FUNCNAME[0]}: calling ${requestComp}" + # Use eval to handle any environment variables and such + out=$(eval "${requestComp}" 2>/dev/null) + + # Extract the directive integer at the very end of the output following a colon (:) + directive=${out##*:} + # Remove the directive + out=${out%%:*} + if [ "${directive}" = "${out}" ]; then + # There is not directive specified + directive=0 + fi + __%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}" + __%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out}" + + if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then + # Error code. No completion. + __%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code" + return + else + if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then + if [[ $(type -t compopt) = "builtin" ]]; then + __%[1]s_debug "${FUNCNAME[0]}: activating no space" + compopt -o nospace + fi + fi + if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then + if [[ $(type -t compopt) = "builtin" ]]; then + __%[1]s_debug "${FUNCNAME[0]}: activating no file completion" + compopt +o default + fi + fi + fi + + if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then + # File extension filtering + local fullFilter filter filteringCmd + # Do not use quotes around the $out variable or else newline + # characters will be kept. + for filter in ${out}; do + fullFilter+="$filter|" + done + + filteringCmd="_filedir $fullFilter" + __%[1]s_debug "File filtering command: $filteringCmd" + $filteringCmd + elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then + # File completion for directories only + local subdir + # Use printf to strip any trailing newline + subdir=$(printf "%%s" "${out}") + if [ -n "$subdir" ]; then + __%[1]s_debug "Listing directories in $subdir" + __%[1]s_handle_subdirs_in_dir_flag "$subdir" + else + __%[1]s_debug "Listing directories in ." + _filedir -d + fi + else + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${out}" -- "$cur") + fi +} + +__%[1]s_handle_reply() { - __debug "${FUNCNAME[0]}" + __%[1]s_debug "${FUNCNAME[0]}" + local comp case $cur in -*) if [[ $(type -t compopt) = "builtin" ]]; then @@ -73,7 +181,9 @@ __handle_reply() else allflags=("${flags[*]} ${two_word_flags[*]}") fi - COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") ) + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${allflags[*]}" -- "$cur") if [[ $(type -t compopt) = "builtin" ]]; then [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace fi @@ -86,25 +196,31 @@ __handle_reply() local index flag flag="${cur%%=*}" - __index_of_word "${flag}" "${flags_with_completion[@]}" + __%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}" + COMPREPLY=() if [[ ${index} -ge 0 ]]; then - COMPREPLY=() PREFIX="" cur="${cur#*=}" ${flags_completion[${index}]} - if [ -n "${ZSH_VERSION}" ]; then - # zfs completion needs --flag= prefix + if [ -n "${ZSH_VERSION:-}" ]; then + # zsh completion needs --flag= prefix eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" fi fi fi - return 0; + + if [[ -z "${flag_parsing_disabled}" ]]; then + # If flag parsing is enabled, we have completed the flags and can return. + # If flag parsing is disabled, we may not know all (or any) of the flags, so we fallthrough + # to possibly call handle_go_custom_completion. + return 0; + fi ;; esac # check if we are handling a flag with special work handling local index - __index_of_word "${prev}" "${flags_with_completion[@]}" + __%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}" if [[ ${index} -ge 0 ]]; then ${flags_completion[${index}]} return @@ -116,68 +232,99 @@ __handle_reply() fi local completions + completions=("${commands[@]}") + if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then + completions+=("${must_have_one_noun[@]}") + elif [[ -n "${has_completion_function}" ]]; then + # if a go completion function is provided, defer to that function + __%[1]s_handle_go_custom_completion + fi if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then - completions=("${must_have_one_flag[@]}") - elif [[ ${#must_have_one_noun[@]} -ne 0 ]]; then - completions=("${must_have_one_noun[@]}") - else - completions=("${commands[@]}") + completions+=("${must_have_one_flag[@]}") fi - COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${completions[*]}" -- "$cur") if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then - COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") ) + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${noun_aliases[*]}" -- "$cur") fi if [[ ${#COMPREPLY[@]} -eq 0 ]]; then - declare -F __custom_func >/dev/null && __custom_func + if declare -F __%[1]s_custom_func >/dev/null; then + # try command name qualified custom func + __%[1]s_custom_func + else + # otherwise fall back to unqualified for compatibility + declare -F __custom_func >/dev/null && __custom_func + fi fi - __ltrim_colon_completions "$cur" + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi + + # If there is only 1 completion and it is a flag with an = it will be completed + # but we don't want a space after the = + if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then + compopt -o nospace + fi } # The arguments should be in the form "ext1|ext2|extn" -__handle_filename_extension_flag() +__%[1]s_handle_filename_extension_flag() { local ext="$1" _filedir "@(${ext})" } -__handle_subdirs_in_dir_flag() +__%[1]s_handle_subdirs_in_dir_flag() { local dir="$1" - pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 + pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return } -__handle_flag() +__%[1]s_handle_flag() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" # if a command required a flag, and we found it, unset must_have_one_flag() local flagname=${words[c]} - local flagvalue + local flagvalue="" # if the word contained an = if [[ ${words[c]} == *"="* ]]; then flagvalue=${flagname#*=} # take in as flagvalue after the = flagname=${flagname%%=*} # strip everything after the = flagname="${flagname}=" # but put the = back fi - __debug "${FUNCNAME[0]}: looking for ${flagname}" - if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then + __%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}" + if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then must_have_one_flag=() fi + # if you set a flag which only applies to this command, don't show subcommands + if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + commands=() + fi + # keep flag value with flagname as flaghash - if [ -n "${flagvalue}" ] ; then - flaghash[${flagname}]=${flagvalue} - elif [ -n "${words[ $((c+1)) ]}" ] ; then - flaghash[${flagname}]=${words[ $((c+1)) ]} - else - flaghash[${flagname}]="true" # pad "true" for bool flag + # flaghash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then + if [ -n "${flagvalue}" ] ; then + flaghash[${flagname}]=${flagvalue} + elif [ -n "${words[ $((c+1)) ]}" ] ; then + flaghash[${flagname}]=${words[ $((c+1)) ]} + else + flaghash[${flagname}]="true" # pad "true" for bool flag + fi fi # skip the argument to a two word flag - if __contains_word "${words[c]}" "${two_word_flags[@]}"; then + if [[ ${words[c]} != *"="* ]] && __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then + __%[1]s_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument" c=$((c+1)) # if we are looking for a flags value, don't show commands if [[ $c -eq $cword ]]; then @@ -189,13 +336,13 @@ __handle_flag() } -__handle_noun() +__%[1]s_handle_noun() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" - if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then + if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then must_have_one_noun=() - elif __contains_word "${words[c]}" "${noun_aliases[@]}"; then + elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then must_have_one_noun=() fi @@ -203,400 +350,360 @@ __handle_noun() c=$((c+1)) } -__handle_command() +__%[1]s_handle_command() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" local next_command if [[ -n ${last_command} ]]; then next_command="_${last_command}_${words[c]//:/__}" else if [[ $c -eq 0 ]]; then - next_command="_$(basename "${words[c]//:/__}")" + next_command="_%[1]s_root_command" else next_command="_${words[c]//:/__}" fi fi c=$((c+1)) - __debug "${FUNCNAME[0]}: looking for ${next_command}" - declare -F $next_command >/dev/null && $next_command + __%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}" + declare -F "$next_command" >/dev/null && $next_command } -__handle_word() +__%[1]s_handle_word() { if [[ $c -ge $cword ]]; then - __handle_reply + __%[1]s_handle_reply return fi - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" if [[ "${words[c]}" == -* ]]; then - __handle_flag - elif __contains_word "${words[c]}" "${commands[@]}"; then - __handle_command - elif [[ $c -eq 0 ]] && __contains_word "$(basename "${words[c]}")" "${commands[@]}"; then - __handle_command + __%[1]s_handle_flag + elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then + __%[1]s_handle_command + elif [[ $c -eq 0 ]]; then + __%[1]s_handle_command + elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then + # aliashash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then + words[c]=${aliashash[${words[c]}]} + __%[1]s_handle_command + else + __%[1]s_handle_noun + fi else - __handle_noun + __%[1]s_handle_noun fi - __handle_word + __%[1]s_handle_word } -`) - return err +`, name, ShellCompNoDescRequestCmd, + ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) } -func postscript(w io.Writer, name string) error { - name = strings.Replace(name, ":", "__", -1) - _, err := fmt.Fprintf(w, "__start_%s()\n", name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `{ - local cur prev words cword +func writePostscript(buf io.StringWriter, name string) { + name = strings.ReplaceAll(name, ":", "__") + WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name)) + WriteStringAndCheck(buf, fmt.Sprintf(`{ + local cur prev words cword split declare -A flaghash 2>/dev/null || : + declare -A aliashash 2>/dev/null || : if declare -F _init_completion >/dev/null 2>&1; then _init_completion -s || return else - __my_init_completion -n "=" || return + __%[1]s_init_completion -n "=" || return fi local c=0 + local flag_parsing_disabled= local flags=() local two_word_flags=() + local local_nonpersistent_flags=() local flags_with_completion=() local flags_completion=() - local commands=("%s") + local commands=("%[1]s") + local command_aliases=() local must_have_one_flag=() local must_have_one_noun=() - local last_command + local has_completion_function="" + local last_command="" local nouns=() + local noun_aliases=() - __handle_word + __%[1]s_handle_word } -`, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then +`, name)) + WriteStringAndCheck(buf, fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then complete -o default -F __start_%s %s else complete -o default -o nospace -F __start_%s %s fi -`, name, name, name, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n") - return err +`, name, name, name, name)) + WriteStringAndCheck(buf, "# ex: ts=4 sw=4 et filetype=sh\n") } -func writeCommands(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil { - return err - } +func writeCommands(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " commands=()\n") for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c == cmd.helpCommand { + if !c.IsAvailableCommand() && c != cmd.helpCommand { continue } - if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" commands+=(%q)\n", c.Name())) + writeCmdAliases(buf, c) } - _, err := fmt.Fprintf(w, "\n") - return err + WriteStringAndCheck(buf, "\n") } -func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error { +func writeFlagHandler(buf io.StringWriter, name string, annotations map[string][]string, cmd *Command) { for key, value := range annotations { switch key { case BashCompFilenameExt: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) > 0 { - ext := "__handle_filename_extension_flag " + strings.Join(value, "|") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|") } else { - ext := "_filedir" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir" } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", ext)) case BashCompCustom: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + if len(value) > 0 { handlers := strings.Join(value, "; ") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers) + WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", handlers)) } else { - _, err = fmt.Fprintf(w, " flags_completion+=(:)\n") - } - if err != nil { - return err + WriteStringAndCheck(buf, " flags_completion+=(:)\n") } case BashCompSubdirsInDir: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) + WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) == 1 { - ext := "__handle_subdirs_in_dir_flag " + value[0] - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0] } else { - ext := "_filedir -d" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir -d" } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", ext)) } } - return nil } -func writeShortFlag(flag *pflag.Flag, w io.Writer) error { - b := (flag.Value.Type() == "bool") +const cbn = "\")\n" + +func writeShortFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) { name := flag.Shorthand format := " " - if !b { + if len(flag.NoOptDefVal) == 0 { format += "two_word_" } - format += "flags+=(\"-%s\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return writeFlagHandler("-"+name, flag.Annotations, w) + format += "flags+=(\"-%s" + cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) + writeFlagHandler(buf, "-"+name, flag.Annotations, cmd) } -func writeFlag(flag *pflag.Flag, w io.Writer) error { - b := (flag.Value.Type() == "bool") +func writeFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) { name := flag.Name format := " flags+=(\"--%s" - if !b { + if len(flag.NoOptDefVal) == 0 { format += "=" } - format += "\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err + format += cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) + if len(flag.NoOptDefVal) == 0 { + format = " two_word_flags+=(\"--%s" + cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) } - return writeFlagHandler("--"+name, flag.Annotations, w) + writeFlagHandler(buf, "--"+name, flag.Annotations, cmd) } -func writeFlags(cmd *Command, w io.Writer) error { - _, err := fmt.Fprintf(w, ` flags=() +func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { + name := flag.Name + format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn + if len(flag.NoOptDefVal) == 0 { + format += " local_nonpersistent_flags+=(\"--%[1]s=" + cbn + } + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) + if len(flag.Shorthand) > 0 { + WriteStringAndCheck(buf, fmt.Sprintf(" local_nonpersistent_flags+=(\"-%s\")\n", flag.Shorthand)) + } +} + +// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags +func prepareCustomAnnotationsForFlags(cmd *Command) { + flagCompletionMutex.RLock() + defer flagCompletionMutex.RUnlock() + for flag := range flagCompletionFunctions { + // Make sure the completion script calls the __*_go_custom_completion function for + // every registered flag. We need to do this here (and not when the flag was registered + // for completion) so that we can know the root command name for the prefix + // of ___go_custom_completion + if flag.Annotations == nil { + flag.Annotations = map[string][]string{} + } + flag.Annotations[BashCompCustom] = []string{fmt.Sprintf("__%[1]s_handle_go_custom_completion", cmd.Root().Name())} + } +} + +func writeFlags(buf io.StringWriter, cmd *Command) { + prepareCustomAnnotationsForFlags(cmd) + WriteStringAndCheck(buf, ` flags=() two_word_flags=() + local_nonpersistent_flags=() flags_with_completion=() flags_completion=() `) - if err != nil { - return err + + if cmd.DisableFlagParsing { + WriteStringAndCheck(buf, " flag_parsing_disabled=1\n") } - var visitErr error + + localNonPersistentFlags := cmd.LocalNonPersistentFlags() cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { - if err := writeFlag(flag, w); err != nil { - visitErr = err + if nonCompletableFlag(flag) { return } + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag, cmd) + } + // localNonPersistentFlags are used to stop the completion of subcommands when one is set + // if TraverseChildren is true we should allow to complete subcommands + if localNonPersistentFlags.Lookup(flag.Name) != nil && !cmd.Root().TraverseChildren { + writeLocalNonPersistentFlag(buf, flag) } }) - if visitErr != nil { - return visitErr - } cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { - if err := writeFlag(flag, w); err != nil { - visitErr = err + if nonCompletableFlag(flag) { return } + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag, cmd) } }) - if visitErr != nil { - return visitErr - } - _, err = fmt.Fprintf(w, "\n") - return err + WriteStringAndCheck(buf, "\n") } -func writeRequiredFlag(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil { - return err - } +func writeRequiredFlag(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " must_have_one_flag=()\n") flags := cmd.NonInheritedFlags() - var visitErr error flags.VisitAll(func(flag *pflag.Flag) { - for key := range flag.Annotations { - switch key { - case BashCompOneRequiredFlag: - format := " must_have_one_flag+=(\"--%s" - b := (flag.Value.Type() == "bool") - if !b { - format += "=" - } - format += "\")\n" - if _, err := fmt.Fprintf(w, format, flag.Name); err != nil { - visitErr = err - return - } - - if len(flag.Shorthand) > 0 { - if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil { - visitErr = err - return - } - } + if nonCompletableFlag(flag) { + return + } + if _, ok := flag.Annotations[BashCompOneRequiredFlag]; ok { + format := " must_have_one_flag+=(\"--%s" + if flag.Value.Type() != "bool" { + format += "=" + } + format += cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name)) + + if len(flag.Shorthand) > 0 { + WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) } } }) - return visitErr } -func writeRequiredNouns(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil { - return err - } - sort.Sort(sort.StringSlice(cmd.ValidArgs)) +func writeRequiredNouns(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " must_have_one_noun=()\n") + sort.Strings(cmd.ValidArgs) for _, value := range cmd.ValidArgs { - if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil { - return err - } + // Remove any description that may be included following a tab character. + // Descriptions are not supported by bash completion. + value = strings.SplitN(value, "\t", 2)[0] + WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) + } + if cmd.ValidArgsFunction != nil { + WriteStringAndCheck(buf, " has_completion_function=1\n") } - return nil } -func writeArgAliases(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil { - return err +func writeCmdAliases(buf io.StringWriter, cmd *Command) { + if len(cmd.Aliases) == 0 { + return } - sort.Sort(sort.StringSlice(cmd.ArgAliases)) + + sort.Strings(cmd.Aliases) + + WriteStringAndCheck(buf, fmt.Sprint(` if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then`, "\n")) + for _, value := range cmd.Aliases { + WriteStringAndCheck(buf, fmt.Sprintf(" command_aliases+=(%q)\n", value)) + WriteStringAndCheck(buf, fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name())) + } + WriteStringAndCheck(buf, ` fi`) + WriteStringAndCheck(buf, "\n") +} +func writeArgAliases(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " noun_aliases=()\n") + sort.Strings(cmd.ArgAliases) for _, value := range cmd.ArgAliases { - if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" noun_aliases+=(%q)\n", value)) } - return nil } -func gen(cmd *Command, w io.Writer) error { +func gen(buf io.StringWriter, cmd *Command) { for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c == cmd.helpCommand { + if !c.IsAvailableCommand() && c != cmd.helpCommand { continue } - if err := gen(c, w); err != nil { - return err - } + gen(buf, c) } commandName := cmd.CommandPath() - commandName = strings.Replace(commandName, " ", "_", -1) - commandName = strings.Replace(commandName, ":", "__", -1) - if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil { - return err - } - if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil { - return err - } - if err := writeCommands(cmd, w); err != nil { - return err - } - if err := writeFlags(cmd, w); err != nil { - return err - } - if err := writeRequiredFlag(cmd, w); err != nil { - return err - } - if err := writeRequiredNouns(cmd, w); err != nil { - return err - } - if err := writeArgAliases(cmd, w); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "}\n\n"); err != nil { - return err - } - return nil -} + commandName = strings.ReplaceAll(commandName, " ", "_") + commandName = strings.ReplaceAll(commandName, ":", "__") -func (cmd *Command) GenBashCompletion(w io.Writer) error { - if err := preamble(w, cmd.Name()); err != nil { - return err - } - if len(cmd.BashCompletionFunction) > 0 { - if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil { - return err - } - } - if err := gen(cmd, w); err != nil { - return err + if cmd.Root() == cmd { + WriteStringAndCheck(buf, fmt.Sprintf("_%s_root_command()\n{\n", commandName)) + } else { + WriteStringAndCheck(buf, fmt.Sprintf("_%s()\n{\n", commandName)) } - return postscript(w, cmd.Name()) -} -func (cmd *Command) GenBashCompletionFile(filename string) error { - outFile, err := os.Create(filename) - if err != nil { - return err - } - defer outFile.Close() + WriteStringAndCheck(buf, fmt.Sprintf(" last_command=%q\n", commandName)) + WriteStringAndCheck(buf, "\n") + WriteStringAndCheck(buf, " command_aliases=()\n") + WriteStringAndCheck(buf, "\n") - return cmd.GenBashCompletion(outFile) + writeCommands(buf, cmd) + writeFlags(buf, cmd) + writeRequiredFlag(buf, cmd) + writeRequiredNouns(buf, cmd) + writeArgAliases(buf, cmd) + WriteStringAndCheck(buf, "}\n\n") } -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists. -func (cmd *Command) MarkFlagRequired(name string) error { - return MarkFlagRequired(cmd.Flags(), name) -} - -// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists. -func (cmd *Command) MarkPersistentFlagRequired(name string) error { - return MarkFlagRequired(cmd.PersistentFlags(), name) -} - -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists. -func MarkFlagRequired(flags *pflag.FlagSet, name string) error { - return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) -} - -// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.Flags(), name, extensions...) -} +// GenBashCompletion generates bash completion file and writes to the passed writer. +func (c *Command) GenBashCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + writePreamble(buf, c.Name()) + if len(c.BashCompletionFunction) > 0 { + buf.WriteString(c.BashCompletionFunction + "\n") + } + gen(buf, c) + writePostscript(buf, c.Name()) -// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. -// Generated bash autocompletion will call the bash function f for the flag. -func (cmd *Command) MarkFlagCustom(name string, f string) error { - return MarkFlagCustom(cmd.Flags(), name, f) + _, err := buf.WriteTo(w) + return err } -// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.PersistentFlags(), name, extensions...) +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 } -// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { - return flags.SetAnnotation(name, BashCompFilenameExt, extensions) -} +// GenBashCompletionFile generates bash completion file. +func (c *Command) GenBashCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() -// MarkFlagCustom adds the BashCompCustom annotation to the named flag in the flag set, if it exists. -// Generated bash autocompletion will call the bash function f for the flag. -func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { - return flags.SetAnnotation(name, BashCompCustom, []string{f}) + return c.GenBashCompletion(outFile) } diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md deleted file mode 100644 index 84d5b012f..000000000 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ /dev/null @@ -1,206 +0,0 @@ -# Generating Bash Completions For Your Own cobra.Command - -Generating bash completions from a cobra command is incredibly easy. An actual program which does so for the kubernetes kubectl binary is as follows: - -```go -package main - -import ( - "io/ioutil" - "os" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd" -) - -func main() { - kubectl := cmd.NewFactory(nil).NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) - kubectl.GenBashCompletionFile("out.sh") -} -``` - -That will get you completions of subcommands and flags. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. - -## Creating your own custom functions - -Some more actual code that works in kubernetes: - -```bash -const ( - bash_completion_func = `__kubectl_parse_get() -{ - local kubectl_output out - if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then - out=($(echo "${kubectl_output}" | awk '{print $1}')) - COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_get_resource() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 - fi - __kubectl_parse_get ${nouns[${#nouns[@]} -1]} - if [[ $? -eq 0 ]]; then - return 0 - fi -} - -__custom_func() { - case ${last_command} in - kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) - __kubectl_get_resource - return - ;; - *) - ;; - esac -} -`) -``` - -And then I set that in my command definition: - -```go -cmds := &cobra.Command{ - Use: "kubectl", - Short: "kubectl controls the Kubernetes cluster manager", - Long: `kubectl controls the Kubernetes cluster manager. - -Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, - Run: runHelp, - BashCompletionFunction: bash_completion_func, -} -``` - -The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__custom_func()` to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! - -## Have the completions code complete your 'nouns' - -In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like: - -```go -validArgs []string = { "pod", "node", "service", "replicationcontroller" } - -cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", - Short: "Display one or many resources", - Long: get_long, - Example: get_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunGet(f, out, cmd, args) - util.CheckErr(err) - }, - ValidArgs: validArgs, -} -``` - -Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like - -```bash -# kubectl get [tab][tab] -node pod replicationcontroller service -``` - -## Plural form and shortcuts for nouns - -If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`: - -```go` -argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } - -cmd := &cobra.Command{ - ... - ValidArgs: validArgs, - ArgAliases: argAliases -} -``` - -The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion aglorithm if entered manually, e.g. in: - -```bash -# kubectl get rc [tab][tab] -backend frontend database -``` - -Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns -in this example again instead of the replication controllers. - -## Mark flags as required - -Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy. - -```go -cmd.MarkFlagRequired("pod") -cmd.MarkFlagRequired("container") -``` - -and you'll get something like - -```bash -# kubectl exec [tab][tab][tab] --c --container= -p --pod= -``` - -# Specify valid filename extensions for flags that take a filename - -In this example we use --filename= and expect to get a json or yaml file as the argument. To make this easier we annotate the --filename flag with valid filename extensions. - -```go - annotations := []string{"json", "yaml", "yml"} - annotation := make(map[string][]string) - annotation[cobra.BashCompFilenameExt] = annotations - - flag := &pflag.Flag{ - Name: "filename", - Shorthand: "f", - Usage: usage, - Value: value, - DefValue: value.String(), - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -Now when you run a command with this filename flag you'll get something like - -```bash -# kubectl create -f -test/ example/ rpmbuild/ -hello.yml test.json -``` - -So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. - -# Specifiy custom flag completion - -Similar to the filename completion and filtering usingn cobra.BashCompFilenameExt, you can specifiy -a custom flag completion function with cobra.BashCompCustom: - -```go - annotation := make(map[string][]string) - annotation[cobra.BashCompFilenameExt] = []string{"__kubectl_get_namespaces"} - - flag := &pflag.Flag{ - Name: "namespace", - Usage: usage, - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction` -value, e.g.: - -```bash -__kubectl_get_namespaces() -{ - local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - local kubectl_out - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) - fi -} -``` diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index 0c4e2e5de..e0b0947b0 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -1,9 +1,10 @@ -// Copyright © 2013 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -19,52 +20,97 @@ package cobra import ( "fmt" "io" + "os" "reflect" "strconv" "strings" "text/template" + "time" "unicode" ) var templateFuncs = template.FuncMap{ - "trim": strings.TrimSpace, - "trimRightSpace": trimRightSpace, - "appendIfNotPresent": appendIfNotPresent, - "rpad": rpad, - "gt": Gt, - "eq": Eq, + "trim": strings.TrimSpace, + "trimRightSpace": trimRightSpace, + "trimTrailingWhitespaces": trimRightSpace, + "appendIfNotPresent": appendIfNotPresent, + "rpad": rpad, + "gt": Gt, + "eq": Eq, } var initializers []func() +var finalizers []func() + +const ( + defaultPrefixMatching = false + defaultCommandSorting = true + defaultCaseInsensitive = false + defaultTraverseRunHooks = false +) + +// EnablePrefixMatching allows setting automatic prefix matching. Automatic prefix matching can be a dangerous thing +// to automatically enable in CLI tools. +// Set this to true to enable it. +var EnablePrefixMatching = defaultPrefixMatching + +// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. +// To disable sorting, set it to false. +var EnableCommandSorting = defaultCommandSorting + +// EnableCaseInsensitive allows case-insensitive commands names. (case sensitive by default) +var EnableCaseInsensitive = defaultCaseInsensitive + +// EnableTraverseRunHooks executes persistent pre-run and post-run hooks from all parents. +// By default this is disabled, which means only the first run hook to be found is executed. +var EnableTraverseRunHooks = defaultTraverseRunHooks -// automatic prefix matching can be a dangerous thing to automatically enable in CLI tools. -// Set this to true to enable it -var EnablePrefixMatching = false +// MousetrapHelpText enables an information splash screen on Windows +// if the CLI is started from explorer.exe. +// To disable the mousetrap, just set this variable to blank string (""). +// Works only on Microsoft Windows. +var MousetrapHelpText = `This is a command line tool. -//AddTemplateFunc adds a template function that's available to Usage and Help -//template generation. +You need to open cmd.exe and run it from there. +` + +// MousetrapDisplayDuration controls how long the MousetrapHelpText message is displayed on Windows +// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed. +// To disable the mousetrap, just set MousetrapHelpText to blank string (""). +// Works only on Microsoft Windows. +var MousetrapDisplayDuration = 5 * time.Second + +// AddTemplateFunc adds a template function that's available to Usage and Help +// template generation. func AddTemplateFunc(name string, tmplFunc interface{}) { templateFuncs[name] = tmplFunc } -//AddTemplateFuncs adds multiple template functions availalble to Usage and -//Help template generation. +// AddTemplateFuncs adds multiple template functions that are available to Usage and +// Help template generation. func AddTemplateFuncs(tmplFuncs template.FuncMap) { for k, v := range tmplFuncs { templateFuncs[k] = v } } -//OnInitialize takes a series of func() arguments and appends them to a slice of func(). +// OnInitialize sets the passed functions to be run when each command's +// Execute method is called. func OnInitialize(y ...func()) { - for _, x := range y { - initializers = append(initializers, x) - } + initializers = append(initializers, y...) } -//Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, -//Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as -//ints and then compared. +// OnFinalize sets the passed functions to be run when each command's +// Execute method is terminated. +func OnFinalize(y ...func()) { + finalizers = append(finalizers, y...) +} + +// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, +// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as +// ints and then compared. func Gt(a interface{}, b interface{}) bool { var left, right int64 av := reflect.ValueOf(a) @@ -92,7 +138,9 @@ func Gt(a interface{}, b interface{}) bool { return left > right } -//Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. +// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. func Eq(a interface{}, b interface{}) bool { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) @@ -112,7 +160,9 @@ func trimRightSpace(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) } -// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s +// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s. func appendIfNotPresent(s, stringToAppend string) string { if strings.Contains(s, stringToAppend) { return s @@ -120,10 +170,10 @@ func appendIfNotPresent(s, stringToAppend string) string { return s + " " + stringToAppend } -//rpad adds padding to the right of a string +// rpad adds padding to the right of a string. func rpad(s string, padding int) string { - template := fmt.Sprintf("%%-%ds", padding) - return fmt.Sprintf(template, s) + formattedString := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(formattedString, s) } // tmpl executes the given template text on data, writing the result to w. @@ -134,7 +184,7 @@ func tmpl(w io.Writer, text string, data interface{}) error { return t.Execute(w, data) } -// ld compares two strings and returns the levenshtein distance between them +// ld compares two strings and returns the levenshtein distance between them. func ld(s, t string, ignoreCase bool) int { if ignoreCase { s = strings.ToLower(s) @@ -143,8 +193,6 @@ func ld(s, t string, ignoreCase bool) int { d := make([][]int, len(s)+1) for i := range d { d[i] = make([]int, len(t)+1) - } - for i := range d { d[i][0] = i } for j := range d[0] { @@ -169,3 +217,26 @@ func ld(s, t string, ignoreCase bool) int { } return d[len(s)][len(t)] } + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +// CheckErr prints the msg with the prefix 'Error:' and exits with error code 1. If the msg is nil, it does nothing. +func CheckErr(msg interface{}) { + if msg != nil { + fmt.Fprintln(os.Stderr, "Error:", msg) + os.Exit(1) + } +} + +// WriteStringAndCheck writes a string into a buffer, and checks if the error is not nil. +func WriteStringAndCheck(b io.StringWriter, s string) { + _, err := b.WriteString(s) + CheckErr(err) +} diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index b92c95cbb..54748fc67 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -1,9 +1,10 @@ -// Copyright © 2013 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -11,172 +12,355 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. -//In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. +// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. +// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. package cobra import ( "bytes" + "context" + "errors" "fmt" "io" "os" "path/filepath" + "sort" "strings" flag "github.com/spf13/pflag" ) +const ( + FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" + CommandDisplayNameAnnotation = "cobra_annotation_command_display_name" +) + +// FParseErrWhitelist configures Flag parse errors to be ignored +type FParseErrWhitelist flag.ParseErrorsWhitelist + +// Group Structure to manage groups for commands +type Group struct { + ID string + Title string +} + // Command is just that, a command for your application. -// eg. 'go run' ... 'run' is the command. Cobra requires +// E.g. 'go run ...' - 'run' is the command. Cobra requires // you to define the usage and description as part of your command // definition to ensure usability. type Command struct { - // Name is the command name, usually the executable's name. - name string - // The one-line usage message. + // Use is the one-line usage message. + // Recommended syntax is as follows: + // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. + // ... indicates that you can specify multiple values for the previous argument. + // | indicates mutually exclusive information. You can use the argument to the left of the separator or the + // argument to the right of the separator. You cannot use both arguments in a single use of the command. + // { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are + // optional, they are enclosed in brackets ([ ]). + // Example: add [-F file | -D dir]... [-f format] profile Use string - // An array of aliases that can be used instead of the first word in Use. + + // Aliases is an array of aliases that can be used instead of the first word in Use. Aliases []string - // An array of command names for which this command will be suggested - similar to aliases but only suggests. + + // SuggestFor is an array of command names for which this command will be suggested - + // similar to aliases but only suggests. SuggestFor []string - // The short description shown in the 'help' output. + + // Short is the short description shown in the 'help' output. Short string - // The long message shown in the 'help ' output. + + // The group id under which this subcommand is grouped in the 'help' output of its parent. + GroupID string + + // Long is the long message shown in the 'help ' output. Long string - // Examples of how to use the command + + // Example is examples of how to use the command. Example string - // List of all valid non-flag arguments that are accepted in bash completions + + // ValidArgs is list of all valid non-flag arguments that are accepted in shell completions ValidArgs []string - // List of aliases for ValidArgs. These are not suggested to the user in the bash - // completion, but accepted if entered manually. + // ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. + // It is a dynamic version of using ValidArgs. + // Only one of ValidArgs and ValidArgsFunction can be used for a command. + ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + + // Expected arguments + Args PositionalArgs + + // ArgAliases is List of aliases for ValidArgs. + // These are not suggested to the user in the shell completion, + // but accepted if entered manually. ArgAliases []string - // Custom functions used by the bash autocompletion generator + + // BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. + // For portability with other shells, it is recommended to instead use ValidArgsFunction BashCompletionFunction string - // Is this command deprecated and should print this string when used? + + // Deprecated defines, if this command is deprecated and should print this string when used. Deprecated string - // Is this command hidden and should NOT show up in the list of available commands? - Hidden bool - // Full set of flags - flags *flag.FlagSet - // Set of flags childrens of this command will inherit - pflags *flag.FlagSet - // Flags that are declared specifically by this command (not inherited). - lflags *flag.FlagSet - // SilenceErrors is an option to quiet errors down stream - SilenceErrors bool - // Silence Usage is an option to silence usage when an error occurs. - SilenceUsage bool + + // Annotations are key/value pairs that can be used by applications to identify or + // group commands or set special options. + Annotations map[string]string + + // Version defines the version for this command. If this value is non-empty and the command does not + // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + // will print content of the "Version" variable. A shorthand "v" flag will also be added if the + // command does not define one. + Version string + // The *Run functions are executed in the following order: // * PersistentPreRun() // * PreRun() // * Run() // * PostRun() // * PersistentPostRun() - // All functions get the same args, the arguments after the command name - // PersistentPreRun: children of this command will inherit and execute + // All functions get the same args, the arguments after the command name. + // The *PreRun and *PostRun functions will only be executed if the Run function of the current + // command has been declared. + // + // PersistentPreRun: children of this command will inherit and execute. PersistentPreRun func(cmd *Command, args []string) - // PersistentPreRunE: PersistentPreRun but returns an error + // PersistentPreRunE: PersistentPreRun but returns an error. PersistentPreRunE func(cmd *Command, args []string) error // PreRun: children of this command will not inherit. PreRun func(cmd *Command, args []string) - // PreRunE: PreRun but returns an error + // PreRunE: PreRun but returns an error. PreRunE func(cmd *Command, args []string) error - // Run: Typically the actual work function. Most commands will only implement this + // Run: Typically the actual work function. Most commands will only implement this. Run func(cmd *Command, args []string) - // RunE: Run but returns an error + // RunE: Run but returns an error. RunE func(cmd *Command, args []string) error // PostRun: run after the Run command. PostRun func(cmd *Command, args []string) - // PostRunE: PostRun but returns an error + // PostRunE: PostRun but returns an error. PostRunE func(cmd *Command, args []string) error - // PersistentPostRun: children of this command will inherit and execute after PostRun + // PersistentPostRun: children of this command will inherit and execute after PostRun. PersistentPostRun func(cmd *Command, args []string) - // PersistentPostRunE: PersistentPostRun but returns an error + // PersistentPostRunE: PersistentPostRun but returns an error. PersistentPostRunE func(cmd *Command, args []string) error - // DisableAutoGenTag remove - DisableAutoGenTag bool - // Commands is the list of commands supported by this program. + + // groups for subcommands + commandgroups []*Group + + // args is actual args parsed from flags. + args []string + // flagErrorBuf contains all error messages from pflag. + flagErrorBuf *bytes.Buffer + // flags is full set of flags. + flags *flag.FlagSet + // pflags contains persistent flags. + pflags *flag.FlagSet + // lflags contains local flags. + // This field does not represent internal state, it's used as a cache to optimise LocalFlags function call + lflags *flag.FlagSet + // iflags contains inherited flags. + // This field does not represent internal state, it's used as a cache to optimise InheritedFlags function call + iflags *flag.FlagSet + // parentsPflags is all persistent flags of cmd's parents. + parentsPflags *flag.FlagSet + // globNormFunc is the global normalization function + // that we can use on every pflag set and children commands + globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + + // usageFunc is usage func defined by user. + usageFunc func(*Command) error + // usageTemplate is usage template defined by user. + usageTemplate string + // flagErrorFunc is func defined by user and it's called when the parsing of + // flags returns an error. + flagErrorFunc func(*Command, error) error + // helpTemplate is help template defined by user. + helpTemplate string + // helpFunc is help func defined by user. + helpFunc func(*Command, []string) + // helpCommand is command with usage 'help'. If it's not defined by user, + // cobra uses default help command. + helpCommand *Command + // helpCommandGroupID is the group id for the helpCommand + helpCommandGroupID string + + // completionCommandGroupID is the group id for the completion command + completionCommandGroupID string + + // versionTemplate is the version template defined by user. + versionTemplate string + + // errPrefix is the error message prefix defined by user. + errPrefix string + + // inReader is a reader defined by the user that replaces stdin + inReader io.Reader + // outWriter is a writer defined by the user that replaces stdout + outWriter io.Writer + // errWriter is a writer defined by the user that replaces stderr + errWriter io.Writer + + // FParseErrWhitelist flag parse errors to be ignored + FParseErrWhitelist FParseErrWhitelist + + // CompletionOptions is a set of options to control the handling of shell completion + CompletionOptions CompletionOptions + + // commandsAreSorted defines, if command slice are sorted or not. + commandsAreSorted bool + // commandCalledAs is the name or alias value used to call this command. + commandCalledAs struct { + name string + called bool + } + + ctx context.Context + + // commands is the list of commands supported by this program. commands []*Command - // Parent Command for this command + // parent is a parent command for this command. parent *Command - // max lengths of commands' string lengths for use in padding + // Max lengths of commands' string lengths for use in padding. commandsMaxUseLen int commandsMaxCommandPathLen int commandsMaxNameLen int - flagErrorBuf *bytes.Buffer + // TraverseChildren parses flags on all parents before executing child command. + TraverseChildren bool - args []string // actual args parsed from flags - output *io.Writer // nil means stderr; use Out() method instead - usageFunc func(*Command) error // Usage can be defined by application - usageTemplate string // Can be defined by Application - helpTemplate string // Can be defined by Application - helpFunc func(*Command, []string) // Help can be defined by application - helpCommand *Command // The help command - // The global normalization function that we can use on every pFlag set and children commands - globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + Hidden bool + + // SilenceErrors is an option to quiet errors down stream. + SilenceErrors bool - // Disable the suggestions based on Levenshtein distance that go along with 'unknown command' messages + // SilenceUsage is an option to silence usage when an error occurs. + SilenceUsage bool + + // DisableFlagParsing disables the flag parsing. + // If this is true all flags will be passed to the command as arguments. + DisableFlagParsing bool + + // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") + // will be printed by generating docs for this command. + DisableAutoGenTag bool + + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + + // DisableSuggestions disables the suggestions based on Levenshtein distance + // that go along with 'unknown command' messages. DisableSuggestions bool - // If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0 + + // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + // Must be > 0. SuggestionsMinimumDistance int } -// os.Args[1:] by default, if desired, can be overridden +// Context returns underlying command context. If command was executed +// with ExecuteContext or the context was set with SetContext, the +// previously set context will be returned. Otherwise, nil is returned. +// +// Notice that a call to Execute and ExecuteC will replace a nil context of +// a command with a context.Background, so a background context will be +// returned by Context after one of these functions has been called. +func (c *Command) Context() context.Context { + return c.ctx +} + +// SetContext sets context for the command. This context will be overwritten by +// Command.ExecuteContext or Command.ExecuteContextC. +func (c *Command) SetContext(ctx context.Context) { + c.ctx = ctx +} + +// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden // particularly useful when testing. func (c *Command) SetArgs(a []string) { c.args = a } -func (c *Command) getOut(def io.Writer) io.Writer { - if c.output != nil { - return *c.output - } - - if c.HasParent() { - return c.parent.Out() - } - return def +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +// Deprecated: Use SetOut and/or SetErr instead +func (c *Command) SetOutput(output io.Writer) { + c.outWriter = output + c.errWriter = output } -func (c *Command) Out() io.Writer { - return c.getOut(os.Stderr) +// SetOut sets the destination for usage messages. +// If newOut is nil, os.Stdout is used. +func (c *Command) SetOut(newOut io.Writer) { + c.outWriter = newOut } -func (c *Command) getOutOrStdout() io.Writer { - return c.getOut(os.Stdout) +// SetErr sets the destination for error messages. +// If newErr is nil, os.Stderr is used. +func (c *Command) SetErr(newErr io.Writer) { + c.errWriter = newErr } -// SetOutput sets the destination for usage and error messages. -// If output is nil, os.Stderr is used. -func (c *Command) SetOutput(output io.Writer) { - c.output = &output +// SetIn sets the source for input data +// If newIn is nil, os.Stdin is used. +func (c *Command) SetIn(newIn io.Reader) { + c.inReader = newIn } -// Usage can be defined by application +// SetUsageFunc sets usage function. Usage can be defined by application. func (c *Command) SetUsageFunc(f func(*Command) error) { c.usageFunc = f } -// Can be defined by Application +// SetUsageTemplate sets usage template. Can be defined by Application. func (c *Command) SetUsageTemplate(s string) { c.usageTemplate = s } -// Can be defined by Application +// SetFlagErrorFunc sets a function to generate an error when flag parsing +// fails. +func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { + c.flagErrorFunc = f +} + +// SetHelpFunc sets help function. Can be defined by Application. func (c *Command) SetHelpFunc(f func(*Command, []string)) { c.helpFunc = f } +// SetHelpCommand sets help command. func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } -// Can be defined by Application +// SetHelpCommandGroupID sets the group id of the help command. +func (c *Command) SetHelpCommandGroupID(groupID string) { + if c.helpCommand != nil { + c.helpCommand.GroupID = groupID + } + // helpCommandGroupID is used if no helpCommand is defined by the user + c.helpCommandGroupID = groupID +} + +// SetCompletionCommandGroupID sets the group id of the completion command. +func (c *Command) SetCompletionCommandGroupID(groupID string) { + // completionCommandGroupID is used if no completion command is defined by the user + c.Root().completionCommandGroupID = groupID +} + +// SetHelpTemplate sets help template to be used. Application can use it to set custom template. func (c *Command) SetHelpTemplate(s string) { c.helpTemplate = s } +// SetVersionTemplate sets version template to be used. Application can use it to set custom template. +func (c *Command) SetVersionTemplate(s string) { + c.versionTemplate = s +} + +// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. +func (c *Command) SetErrPrefix(s string) { + c.errPrefix = s +} + // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // The user should not have a cyclic dependency on commands. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { @@ -189,43 +373,148 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string } } +// OutOrStdout returns output to stdout. +func (c *Command) OutOrStdout() io.Writer { + return c.getOut(os.Stdout) +} + +// OutOrStderr returns output to stderr +func (c *Command) OutOrStderr() io.Writer { + return c.getOut(os.Stderr) +} + +// ErrOrStderr returns output to stderr +func (c *Command) ErrOrStderr() io.Writer { + return c.getErr(os.Stderr) +} + +// InOrStdin returns input to stdin +func (c *Command) InOrStdin() io.Reader { + return c.getIn(os.Stdin) +} + +func (c *Command) getOut(def io.Writer) io.Writer { + if c.outWriter != nil { + return c.outWriter + } + if c.HasParent() { + return c.parent.getOut(def) + } + return def +} + +func (c *Command) getErr(def io.Writer) io.Writer { + if c.errWriter != nil { + return c.errWriter + } + if c.HasParent() { + return c.parent.getErr(def) + } + return def +} + +func (c *Command) getIn(def io.Reader) io.Reader { + if c.inReader != nil { + return c.inReader + } + if c.HasParent() { + return c.parent.getIn(def) + } + return def +} + +// UsageFunc returns either the function set by SetUsageFunc for this command +// or a parent, or it returns a default usage function. func (c *Command) UsageFunc() (f func(*Command) error) { if c.usageFunc != nil { return c.usageFunc } - if c.HasParent() { - return c.parent.UsageFunc() + return c.Parent().UsageFunc() } return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) + c.mergePersistentFlags() + err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c) if err != nil { - fmt.Print(err) + c.PrintErrln(err) } return err } } +// Usage puts out the usage for the command. +// Used when a user provides invalid input. +// Can be defined by user by overriding UsageFunc. +func (c *Command) Usage() error { + return c.UsageFunc()(c) +} + // HelpFunc returns either the function set by SetHelpFunc for this command -// or a parent, or it returns a function which calls c.Help() +// or a parent, or it returns a function with default help behavior. func (c *Command) HelpFunc() func(*Command, []string) { - cmd := c - for cmd != nil { - if cmd.helpFunc != nil { - return cmd.helpFunc - } - cmd = cmd.parent + if c.helpFunc != nil { + return c.helpFunc + } + if c.HasParent() { + return c.Parent().HelpFunc() } - return func(*Command, []string) { - err := c.Help() + return func(c *Command, a []string) { + c.mergePersistentFlags() + // The help should be sent to stdout + // See https://github.com/spf13/cobra/issues/1002 + err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) if err != nil { - c.Println(err) + c.PrintErrln(err) } } } +// Help puts out the help for the command. +// Used when a user calls help [command]. +// Can be defined by user by overriding HelpFunc. +func (c *Command) Help() error { + c.HelpFunc()(c, []string{}) + return nil +} + +// UsageString returns usage string. +func (c *Command) UsageString() string { + // Storing normal writers + tmpOutput := c.outWriter + tmpErr := c.errWriter + + bb := new(bytes.Buffer) + c.outWriter = bb + c.errWriter = bb + + CheckErr(c.Usage()) + + // Setting things back to normal + c.outWriter = tmpOutput + c.errWriter = tmpErr + + return bb.String() +} + +// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this +// command or a parent, or it returns a function which returns the original +// error. +func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { + if c.flagErrorFunc != nil { + return c.flagErrorFunc + } + + if c.HasParent() { + return c.parent.FlagErrorFunc() + } + return func(c *Command, err error) error { + return err + } +} + var minUsagePadding = 25 +// UsagePadding return padding for the usage. func (c *Command) UsagePadding() int { if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen { return minUsagePadding @@ -235,7 +524,7 @@ func (c *Command) UsagePadding() int { var minCommandPathPadding = 11 -// +// CommandPathPadding return padding for the command path. func (c *Command) CommandPathPadding() int { if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen { return minCommandPathPadding @@ -245,6 +534,7 @@ func (c *Command) CommandPathPadding() int { var minNamePadding = 11 +// NamePadding returns padding for the name. func (c *Command) NamePadding() int { if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen { return minNamePadding @@ -252,6 +542,7 @@ func (c *Command) NamePadding() int { return c.parent.commandsMaxNameLen } +// UsageTemplate returns usage template for the command. func (c *Command) UsageTemplate() string { if c.usageTemplate != "" { return c.usageTemplate @@ -261,32 +552,38 @@ func (c *Command) UsageTemplate() string { return c.parent.UsageTemplate() } return `Usage:{{if .Runnable}} - {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}} - {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} Aliases: - {{.NameAndAliases}} -{{end}}{{if .HasExample}} + {{.NameAndAliases}}{{end}}{{if .HasExample}} Examples: -{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}} +{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}} + +Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}} -Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}} +{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}} + +Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} Flags: -{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}} +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} Global Flags: -{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}} +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} -Additional help topics:{{range .Commands}}{{if .IsHelpCommand}} - {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }} +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} ` } +// HelpTemplate return help template for the command. func (c *Command) HelpTemplate() string { if c.helpTemplate != "" { return c.helpTemplate @@ -295,72 +592,88 @@ func (c *Command) HelpTemplate() string { if c.HasParent() { return c.parent.HelpTemplate() } - return `{{with or .Long .Short }}{{. | trim}} + return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` } -// Really only used when casting a command to a commander -func (c *Command) resetChildrensParents() { - for _, x := range c.commands { - x.parent = c +// VersionTemplate return version template for the command. +func (c *Command) VersionTemplate() string { + if c.versionTemplate != "" { + return c.versionTemplate + } + + if c.HasParent() { + return c.parent.VersionTemplate() + } + return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} +` +} + +// ErrPrefix return error message prefix for the command +func (c *Command) ErrPrefix() string { + if c.errPrefix != "" { + return c.errPrefix + } + + if c.HasParent() { + return c.parent.ErrPrefix() } + return "Error:" } -// Test if the named flag is a boolean flag. -func isBooleanFlag(name string, f *flag.FlagSet) bool { - flag := f.Lookup(name) +func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { + flag := fs.Lookup(name) if flag == nil { return false } - return flag.Value.Type() == "bool" + return flag.NoOptDefVal != "" } -// Test if the named flag is a boolean flag. -func isBooleanShortFlag(name string, f *flag.FlagSet) bool { - result := false - f.VisitAll(func(f *flag.Flag) { - if f.Shorthand == name && f.Value.Type() == "bool" { - result = true - } - }) - return result +func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool { + if len(name) == 0 { + return false + } + + flag := fs.ShorthandLookup(name[:1]) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" } func stripFlags(args []string, c *Command) []string { - if len(args) < 1 { + if len(args) == 0 { return args } c.mergePersistentFlags() commands := []string{} - - inQuote := false - inFlag := false - for _, y := range args { - if !inQuote { - switch { - case strings.HasPrefix(y, "\""): - inQuote = true - case strings.Contains(y, "=\""): - inQuote = true - case strings.HasPrefix(y, "--") && !strings.Contains(y, "="): - // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' - inFlag = !isBooleanFlag(y[2:], c.Flags()) - case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()): - inFlag = true - case inFlag: - inFlag = false - case y == "": - // strip empty commands, as the go tests expect this to be ok.... - case !strings.HasPrefix(y, "-"): - commands = append(commands, y) - inFlag = false + flags := c.Flags() + +Loop: + for len(args) > 0 { + s := args[0] + args = args[1:] + switch { + case s == "--": + // "--" terminates the flags + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + // If '--flag arg' then + // delete arg from args. + fallthrough // (do the same as below) + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // If '-f arg' then + // delete 'arg' from args or break the loop if len(args) <= 1. + if len(args) <= 1 { + break Loop + } else { + args = args[1:] + continue } - } - - if strings.HasSuffix(y, "\"") && !strings.HasSuffix(y, "\\\"") { - inQuote = false + case s != "" && !strings.HasPrefix(s, "-"): + commands = append(commands, s) } } @@ -369,25 +682,50 @@ func stripFlags(args []string, c *Command) []string { // argsMinusFirstX removes only the first x from args. Otherwise, commands that look like // openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). -func argsMinusFirstX(args []string, x string) []string { - for i, y := range args { - if x == y { - ret := []string{} - ret = append(ret, args[:i]...) - ret = append(ret, args[i+1:]...) - return ret +// Special care needs to be taken not to remove a flag value. +func (c *Command) argsMinusFirstX(args []string, x string) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + flags := c.Flags() + +Loop: + for pos := 0; pos < len(args); pos++ { + s := args[pos] + switch { + case s == "--": + // -- means we have reached the end of the parseable args. Break out of the loop now. + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + fallthrough + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip + // over the next arg, because that is the value of this flag. + pos++ + continue + case !strings.HasPrefix(s, "-"): + // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, + // return the args, excluding the one at this position. + if s == x { + ret := make([]string, 0, len(args)-1) + ret = append(ret, args[:pos]...) + ret = append(ret, args[pos+1:]...) + return ret + } } } return args } -// find the target command given the args and command tree +func isFlagArg(arg string) bool { + return ((len(arg) >= 3 && arg[0:2] == "--") || + (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) +} + +// Find the target command given the args and command tree // Meant to be run on the highest node. Only searches down. func (c *Command) Find(args []string) (*Command, []string, error) { - if c == nil { - return nil, nil, fmt.Errorf("Called find() on a nil Command") - } - var innerfind func(*Command, []string) (*Command, []string) innerfind = func(c *Command, innerArgs []string) (*Command, []string) { @@ -396,59 +734,103 @@ func (c *Command) Find(args []string) (*Command, []string, error) { return c, innerArgs } nextSubCmd := argsWOflags[0] - matches := make([]*Command, 0) - for _, cmd := range c.commands { - if cmd.Name() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) - } - if EnablePrefixMatching { - if strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match - matches = append(matches, cmd) - } - for _, x := range cmd.Aliases { - if strings.HasPrefix(x, nextSubCmd) { - matches = append(matches, cmd) - } - } - } - } - // only accept a single prefix match - multiple matches would be ambiguous - if len(matches) == 1 { - return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0])) + cmd := c.findNext(nextSubCmd) + if cmd != nil { + return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd)) } - return c, innerArgs } commandFound, a := innerfind(c, args) - argsWOflags := stripFlags(a, commandFound) + if commandFound.Args == nil { + return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound)) + } + return commandFound, a, nil +} - // no subcommand, always take args - if !commandFound.HasSubCommands() { - return commandFound, a, nil +func (c *Command) findSuggestions(arg string) string { + if c.DisableSuggestions { + return "" + } + if c.SuggestionsMinimumDistance <= 0 { + c.SuggestionsMinimumDistance = 2 + } + var sb strings.Builder + if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { + sb.WriteString("\n\nDid you mean this?\n") + for _, s := range suggestions { + _, _ = fmt.Fprintf(&sb, "\t%v\n", s) + } } + return sb.String() +} - // root command with subcommands, do subcommand checking - if commandFound == c && len(argsWOflags) > 0 { - suggestionsString := "" - if !c.DisableSuggestions { - if c.SuggestionsMinimumDistance <= 0 { - c.SuggestionsMinimumDistance = 2 - } - if suggestions := c.SuggestionsFor(argsWOflags[0]); len(suggestions) > 0 { - suggestionsString += "\n\nDid you mean this?\n" - for _, s := range suggestions { - suggestionsString += fmt.Sprintf("\t%v\n", s) - } - } +func (c *Command) findNext(next string) *Command { + matches := make([]*Command, 0) + for _, cmd := range c.commands { + if commandNameMatches(cmd.Name(), next) || cmd.HasAlias(next) { + cmd.commandCalledAs.name = next + return cmd + } + if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { + matches = append(matches, cmd) } - return commandFound, a, fmt.Errorf("unknown command %q for %q%s", argsWOflags[0], commandFound.CommandPath(), suggestionsString) } - return commandFound, a, nil + if len(matches) == 1 { + // Temporarily disable gosec G602, which produces a false positive. + // See https://github.com/securego/gosec/issues/1005. + return matches[0] // #nosec G602 + } + + return nil +} + +// Traverse the command tree to find the command, and parse args for +// each parent. +func (c *Command) Traverse(args []string) (*Command, []string, error) { + flags := []string{} + inFlag := false + + for i, arg := range args { + switch { + // A long flag with a space separated value + case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="): + // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' + inFlag = !hasNoOptDefVal(arg[2:], c.Flags()) + flags = append(flags, arg) + continue + // A short flag with a space separated value + case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()): + inFlag = true + flags = append(flags, arg) + continue + // The value for a flag + case inFlag: + inFlag = false + flags = append(flags, arg) + continue + // A flag without a value, or with an `=` separated value + case isFlagArg(arg): + flags = append(flags, arg) + continue + } + + cmd := c.findNext(arg) + if cmd == nil { + return c, args, nil + } + + if err := c.ParseFlags(flags); err != nil { + return nil, args, err + } + return cmd.Traverse(args[i+1:]) + } + return c, args, nil } +// SuggestionsFor provides suggestions for the typedName. func (c *Command) SuggestionsFor(typedName string) []string { suggestions := []string{} for _, cmd := range c.commands { @@ -469,84 +851,119 @@ func (c *Command) SuggestionsFor(typedName string) []string { return suggestions } +// VisitParents visits all parents of the command and invokes fn on each parent. func (c *Command) VisitParents(fn func(*Command)) { - var traverse func(*Command) *Command - - traverse = func(x *Command) *Command { - if x != c { - fn(x) - } - if x.HasParent() { - return traverse(x.parent) - } - return x + if c.HasParent() { + fn(c.Parent()) + c.Parent().VisitParents(fn) } - traverse(c) } +// Root finds root command. func (c *Command) Root() *Command { - var findRoot func(*Command) *Command - - findRoot = func(x *Command) *Command { - if x.HasParent() { - return findRoot(x.parent) - } - return x + if c.HasParent() { + return c.Parent().Root() } - - return findRoot(c) + return c } -// ArgsLenAtDash will return the length of f.Args at the moment when a -- was -// found during arg parsing. This allows your program to know which args were -// before the -- and which came after. (Description from -// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash). +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. func (c *Command) ArgsLenAtDash() int { return c.Flags().ArgsLenAtDash() } func (c *Command) execute(a []string) (err error) { if c == nil { - return fmt.Errorf("Called Execute() on a nil Command") + return fmt.Errorf("called Execute() on a nil Command") } if len(c.Deprecated) > 0 { c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) } - // initialize help flag as the last point possible to allow for user + // initialize help and version flag at the last point possible to allow for user // overriding - c.initHelpFlag() + c.InitDefaultHelpFlag() + c.InitDefaultVersionFlag() err = c.ParseFlags(a) if err != nil { - return err + return c.FlagErrorFunc()(c, err) } - // If help is called, regardless of other flags, return we want help + + // If help is called, regardless of other flags, return we want help. // Also say we need help if the command isn't runnable. helpVal, err := c.Flags().GetBool("help") if err != nil { // should be impossible to get here as we always declare a help - // flag in initHelpFlag() + // flag in InitDefaultHelpFlag() c.Println("\"help\" flag declared as non-bool. Please correct your code") return err } - if helpVal || !c.Runnable() { + + if helpVal { + return flag.ErrHelp + } + + // for back-compat, only add version flag behavior if version is defined + if c.Version != "" { + versionVal, err := c.Flags().GetBool("version") + if err != nil { + c.Println("\"version\" flag declared as non-bool. Please correct your code") + return err + } + if versionVal { + err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } + } + + if !c.Runnable() { return flag.ErrHelp } c.preRun() + + defer c.postRun() + argWoFlags := c.Flags().Args() + if c.DisableFlagParsing { + argWoFlags = a + } + if err := c.ValidateArgs(argWoFlags); err != nil { + return err + } + + parents := make([]*Command, 0, 5) for p := c; p != nil; p = p.Parent() { + if EnableTraverseRunHooks { + // When EnableTraverseRunHooks is set: + // - Execute all persistent pre-runs from the root parent till this command. + // - Execute all persistent post-runs from this command till the root parent. + parents = append([]*Command{p}, parents...) + } else { + // Otherwise, execute only the first found persistent hook. + parents = append(parents, p) + } + } + for _, p := range parents { if p.PersistentPreRunE != nil { if err := p.PersistentPreRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPreRun != nil { p.PersistentPreRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } if c.PreRunE != nil { @@ -557,6 +974,13 @@ func (c *Command) execute(a []string) (err error) { c.PreRun(c, argWoFlags) } + if err := c.ValidateRequiredFlags(); err != nil { + return err + } + if err := c.ValidateFlagGroups(); err != nil { + return err + } + if c.RunE != nil { if err := c.RunE(c, argWoFlags); err != nil { return err @@ -576,10 +1000,14 @@ func (c *Command) execute(a []string) (err error) { if err := p.PersistentPostRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPostRun != nil { p.PersistentPostRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } @@ -592,18 +1020,21 @@ func (c *Command) preRun() { } } -func (c *Command) errorMsgFromParse() string { - s := c.flagErrorBuf.String() - - x := strings.Split(s, "\n") - - if len(x) > 0 { - return x[0] +func (c *Command) postRun() { + for _, x := range finalizers { + x() } - return "" } -// Call execute to use the args (os.Args[1:] by default) +// ExecuteContext is the same as Execute(), but sets the ctx on the command. +// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs +// functions. +func (c *Command) ExecuteContext(ctx context.Context) error { + c.ctx = ctx + return c.Execute() +} + +// Execute uses the args (os.Args[1:] by default) // and run through the command tree finding appropriate matches // for commands and then corresponding flags. func (c *Command) Execute() error { @@ -611,7 +1042,19 @@ func (c *Command) Execute() error { return err } +// ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command. +// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs +// functions. +func (c *Command) ExecuteContextC(ctx context.Context) (*Command, error) { + c.ctx = ctx + return c.ExecuteC() +} + +// ExecuteC executes the command. func (c *Command) ExecuteC() (cmd *Command, err error) { + if c.ctx == nil { + c.ctx = context.Background() + } // Regardless of what command execute is called on, run on Root only if c.HasParent() { @@ -623,99 +1066,239 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { preExecHookFn(c) } - // initialize help as the last point possible to allow for user - // overriding - c.initHelpCmd() + // initialize help at the last point to allow for user overriding + c.InitDefaultHelpCmd() + // initialize completion at the last point to allow for user overriding + c.InitDefaultCompletionCmd() + + // Now that all commands have been created, let's make sure all groups + // are properly created also + c.checkCommandGroups() - var args []string + args := c.args // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155 if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" { args = os.Args[1:] - } else { - args = c.args } - cmd, flags, err := c.Find(args) + // initialize the hidden command to be used for shell completion + c.initCompleteCmd(args) + + var flags []string + if c.TraverseChildren { + cmd, flags, err = c.Traverse(args) + } else { + cmd, flags, err = c.Find(args) + } if err != nil { // If found parse to a subcommand and then failed, talk about the subcommand if cmd != nil { c = cmd } if !c.SilenceErrors { - c.Println("Error:", err.Error()) - c.Printf("Run '%v --help' for usage.\n", c.CommandPath()) + c.PrintErrln(c.ErrPrefix(), err.Error()) + c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err } + + cmd.commandCalledAs.called = true + if cmd.commandCalledAs.name == "" { + cmd.commandCalledAs.name = cmd.Name() + } + + // We have to pass global context to children command + // if context is present on the parent command. + if cmd.ctx == nil { + cmd.ctx = c.ctx + } + err = cmd.execute(flags) if err != nil { // Always show help if requested, even if SilenceErrors is in // effect - if err == flag.ErrHelp { + if errors.Is(err, flag.ErrHelp) { cmd.HelpFunc()(cmd, args) return cmd, nil } - // If root command has SilentErrors flagged, + // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.Println("Error:", err.Error()) + c.PrintErrln(cmd.ErrPrefix(), err.Error()) } - // If root command has SilentUsage flagged, + // If root command has SilenceUsage flagged, // all subcommands should respect it if !cmd.SilenceUsage && !c.SilenceUsage { c.Println(cmd.UsageString()) } - return cmd, err } - return cmd, nil + return cmd, err } -func (c *Command) initHelpFlag() { - if c.Flags().Lookup("help") == nil { - c.Flags().BoolP("help", "h", false, "help for "+c.Name()) +func (c *Command) ValidateArgs(args []string) error { + if c.Args == nil { + return ArbitraryArgs(c, args) } + return c.Args(c, args) } -func (c *Command) initHelpCmd() { - if c.helpCommand == nil { - if !c.HasSubCommands() { +// ValidateRequiredFlags validates all required flags are present and returns an error otherwise +func (c *Command) ValidateRequiredFlags() error { + if c.DisableFlagParsing { + return nil + } + + flags := c.Flags() + missingFlagNames := []string{} + flags.VisitAll(func(pflag *flag.Flag) { + requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag] + if !found { return } + if (requiredAnnotation[0] == "true") && !pflag.Changed { + missingFlagNames = append(missingFlagNames, pflag.Name) + } + }) + + if len(missingFlagNames) > 0 { + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) + } + return nil +} + +// checkCommandGroups checks if a command has been added to a group that does not exists. +// If so, we panic because it indicates a coding error that should be corrected. +func (c *Command) checkCommandGroups() { + for _, sub := range c.commands { + // if Group is not defined let the developer know right away + if sub.GroupID != "" && !c.ContainsGroup(sub.GroupID) { + panic(fmt.Sprintf("group id '%s' is not defined for subcommand '%s'", sub.GroupID, sub.CommandPath())) + } + + sub.checkCommandGroups() + } +} + +// InitDefaultHelpFlag adds default help flag to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help flag, it will do nothing. +func (c *Command) InitDefaultHelpFlag() { + c.mergePersistentFlags() + if c.Flags().Lookup("help") == nil { + usage := "help for " + name := c.displayName() + if name == "" { + usage += "this command" + } else { + usage += name + } + c.Flags().BoolP("help", "h", false, usage) + _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"}) + } +} + +// InitDefaultVersionFlag adds default version flag to c. +// It is called automatically by executing the c. +// If c already has a version flag, it will do nothing. +// If c.Version is empty, it will do nothing. +func (c *Command) InitDefaultVersionFlag() { + if c.Version == "" { + return + } + + c.mergePersistentFlags() + if c.Flags().Lookup("version") == nil { + usage := "version for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + if c.Flags().ShorthandLookup("v") == nil { + c.Flags().BoolP("version", "v", false, usage) + } else { + c.Flags().Bool("version", false, usage) + } + _ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"}) + } +} + +// InitDefaultHelpCmd adds default help command to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help command or c has no subcommands, it will do nothing. +func (c *Command) InitDefaultHelpCmd() { + if !c.HasSubCommands() { + return + } + if c.helpCommand == nil { c.helpCommand = &Command{ Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - PersistentPreRun: func(cmd *Command, args []string) {}, - PersistentPostRun: func(cmd *Command, args []string) {}, - +Simply type ` + c.displayName() + ` help [path to command] for full details.`, + ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + var completions []string + cmd, _, e := c.Root().Find(args) + if e != nil { + return nil, ShellCompDirectiveNoFileComp + } + if cmd == nil { + // Root help command. + cmd = c.Root() + } + for _, subCmd := range cmd.Commands() { + if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand { + if strings.HasPrefix(subCmd.Name(), toComplete) { + completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short)) + } + } + } + return completions, ShellCompDirectiveNoFileComp + }, Run: func(c *Command, args []string) { cmd, _, e := c.Root().Find(args) if cmd == nil || e != nil { - c.Printf("Unknown help topic %#q.", args) - c.Root().Usage() + c.Printf("Unknown help topic %#q\n", args) + CheckErr(c.Root().Usage()) } else { - helpFunc := cmd.HelpFunc() - helpFunc(cmd, args) + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown + CheckErr(cmd.Help()) } }, + GroupID: c.helpCommandGroupID, } } + c.RemoveCommand(c.helpCommand) c.AddCommand(c.helpCommand) } -// Used for testing +// ResetCommands delete parent, subcommand and help command from c. func (c *Command) ResetCommands() { + c.parent = nil c.commands = nil c.helpCommand = nil + c.parentsPflags = nil } -//Commands returns a slice of child commands. +// Sorts commands by their names. +type commandSorterByName []*Command + +func (c commandSorterByName) Len() int { return len(c) } +func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() } + +// Commands returns a sorted slice of child commands. func (c *Command) Commands() []*Command { + // do not sort commands if it already sorted or sorting was disabled + if EnableCommandSorting && !c.commandsAreSorted { + sort.Sort(commandSorterByName(c.commands)) + c.commandsAreSorted = true + } return c.commands } @@ -744,7 +1327,38 @@ func (c *Command) AddCommand(cmds ...*Command) { x.SetGlobalNormalizationFunc(c.globNormFunc) } c.commands = append(c.commands, x) + c.commandsAreSorted = false + } +} + +// Groups returns a slice of child command groups. +func (c *Command) Groups() []*Group { + return c.commandgroups +} + +// AllChildCommandsHaveGroup returns if all subcommands are assigned to a group +func (c *Command) AllChildCommandsHaveGroup() bool { + for _, sub := range c.commands { + if (sub.IsAvailableCommand() || sub == c.helpCommand) && sub.GroupID == "" { + return false + } + } + return true +} + +// ContainsGroup return if groupID exists in the list of command groups. +func (c *Command) ContainsGroup(groupID string) bool { + for _, x := range c.commandgroups { + if x.ID == groupID { + return true + } } + return false +} + +// AddGroup adds one or more command groups to this parent command. +func (c *Command) AddGroup(groups ...*Group) { + c.commandgroups = append(c.commandgroups, groups...) } // RemoveCommand removes one or more commands from a parent command. @@ -781,72 +1395,71 @@ main: } } -// Print is a convenience method to Print to the defined output +// Print is a convenience method to Print to the defined output, fallback to Stderr if not set. func (c *Command) Print(i ...interface{}) { - fmt.Fprint(c.Out(), i...) + fmt.Fprint(c.OutOrStderr(), i...) } -// Println is a convenience method to Println to the defined output +// Println is a convenience method to Println to the defined output, fallback to Stderr if not set. func (c *Command) Println(i ...interface{}) { - str := fmt.Sprintln(i...) - c.Print(str) + c.Print(fmt.Sprintln(i...)) } -// Printf is a convenience method to Printf to the defined output +// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. func (c *Command) Printf(format string, i ...interface{}) { - str := fmt.Sprintf(format, i...) - c.Print(str) + c.Print(fmt.Sprintf(format, i...)) } -// Output the usage for the command -// Used when a user provides invalid input -// Can be defined by user by overriding UsageFunc -func (c *Command) Usage() error { - c.mergePersistentFlags() - err := c.UsageFunc()(c) - return err +// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErr(i ...interface{}) { + fmt.Fprint(c.ErrOrStderr(), i...) } -// Output the help for the command -// Used when a user calls help [command] -// by the default HelpFunc in the commander -func (c *Command) Help() error { - c.mergePersistentFlags() - err := tmpl(c.getOutOrStdout(), c.HelpTemplate(), c) - return err +// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErrln(i ...interface{}) { + c.PrintErr(fmt.Sprintln(i...)) } -func (c *Command) UsageString() string { - tmpOutput := c.output - bb := new(bytes.Buffer) - c.SetOutput(bb) - c.Usage() - c.output = tmpOutput - return bb.String() +// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErrf(format string, i ...interface{}) { + c.PrintErr(fmt.Sprintf(format, i...)) } // CommandPath returns the full path to this command. func (c *Command) CommandPath() string { - str := c.Name() - x := c - for x.HasParent() { - str = x.parent.Name() + " " + str - x = x.parent + if c.HasParent() { + return c.Parent().CommandPath() + " " + c.Name() } - return str + return c.displayName() } -//The full usage for a given command (including parents) +func (c *Command) displayName() string { + if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok { + return displayName + } + return c.Name() +} + +// UseLine puts out the full usage for a given command (including parents). func (c *Command) UseLine() string { - str := "" + var useline string + use := strings.Replace(c.Use, c.Name(), c.displayName(), 1) if c.HasParent() { - str = c.parent.CommandPath() + " " + useline = c.parent.CommandPath() + " " + use + } else { + useline = use + } + if c.DisableFlagsInUseLine { + return useline } - return str + c.Use + if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { + useline += " [flags]" + } + return useline } -// For use in determining which flags have been assigned to which commands -// and which persist +// DebugFlags used to determine which flags have been assigned to which commands +// and which persist. func (c *Command) DebugFlags() { c.Println("DebugFlags called on", c.Name()) var debugflags func(*Command) @@ -857,12 +1470,8 @@ func (c *Command) DebugFlags() { } if x.HasFlags() { x.flags.VisitAll(func(f *flag.Flag) { - if x.HasPersistentFlags() { - if x.persistentFlag(f.Name) == nil { - c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") - } else { - c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") - } + if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") } else { c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") } @@ -892,9 +1501,6 @@ func (c *Command) DebugFlags() { // Name returns the command's name: the first word in the use line. func (c *Command) Name() string { - if c.name != "" { - return c.name - } name := c.Use i := strings.Index(name, " ") if i >= 0 { @@ -906,33 +1512,60 @@ func (c *Command) Name() string { // HasAlias determines if a given string is an alias of the command. func (c *Command) HasAlias(s string) bool { for _, a := range c.Aliases { - if a == s { + if commandNameMatches(a, s) { return true } } return false } +// CalledAs returns the command name or alias that was used to invoke +// this command or an empty string if the command has not been called. +func (c *Command) CalledAs() string { + if c.commandCalledAs.called { + return c.commandCalledAs.name + } + return "" +} + +// hasNameOrAliasPrefix returns true if the Name or any of aliases start +// with prefix +func (c *Command) hasNameOrAliasPrefix(prefix string) bool { + if strings.HasPrefix(c.Name(), prefix) { + c.commandCalledAs.name = c.Name() + return true + } + for _, alias := range c.Aliases { + if strings.HasPrefix(alias, prefix) { + c.commandCalledAs.name = alias + return true + } + } + return false +} + +// NameAndAliases returns a list of the command name and all aliases func (c *Command) NameAndAliases() string { return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") } +// HasExample determines if the command has example. func (c *Command) HasExample() bool { return len(c.Example) > 0 } -// Runnable determines if the command is itself runnable +// Runnable determines if the command is itself runnable. func (c *Command) Runnable() bool { return c.Run != nil || c.RunE != nil } -// HasSubCommands determines if the command has children commands +// HasSubCommands determines if the command has children commands. func (c *Command) HasSubCommands() bool { return len(c.commands) > 0 } // IsAvailableCommand determines if a command is available as a non-help command -// (this includes all non deprecated/hidden commands) +// (this includes all non deprecated/hidden commands). func (c *Command) IsAvailableCommand() bool { if len(c.Deprecated) != 0 || c.Hidden { return false @@ -949,11 +1582,12 @@ func (c *Command) IsAvailableCommand() bool { return false } -// IsHelpCommand determines if a command is a 'help' command; a help command is -// determined by the fact that it is NOT runnable/hidden/deprecated, and has no -// sub commands that are runnable/hidden/deprecated -func (c *Command) IsHelpCommand() bool { - +// IsAdditionalHelpTopicCommand determines if a command is an additional +// help topic command; additional help topic command is determined by the +// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that +// are runnable/hidden/deprecated. +// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. +func (c *Command) IsAdditionalHelpTopicCommand() bool { // if a command is runnable, deprecated, or hidden it is not a 'help' command if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden { return false @@ -961,7 +1595,7 @@ func (c *Command) IsHelpCommand() bool { // if any non-help sub commands are found, the command is not a 'help' command for _, sub := range c.commands { - if !sub.IsHelpCommand() { + if !sub.IsAdditionalHelpTopicCommand() { return false } } @@ -970,14 +1604,13 @@ func (c *Command) IsHelpCommand() bool { return true } -// HasHelpSubCommands determines if a command has any avilable 'help' sub commands +// HasHelpSubCommands determines if a command has any available 'help' sub commands // that need to be shown in the usage/help default template under 'additional help -// topics' +// topics'. func (c *Command) HasHelpSubCommands() bool { - // return true on the first found available 'help' sub command for _, sub := range c.commands { - if sub.IsHelpCommand() { + if sub.IsAdditionalHelpTopicCommand() { return true } } @@ -987,9 +1620,8 @@ func (c *Command) HasHelpSubCommands() bool { } // HasAvailableSubCommands determines if a command has available sub commands that -// need to be shown in the usage/help default template under 'available commands' +// need to be shown in the usage/help default template under 'available commands'. func (c *Command) HasAvailableSubCommands() bool { - // return true on the first found available (non deprecated/help/hidden) // sub command for _, sub := range c.commands { @@ -998,89 +1630,113 @@ func (c *Command) HasAvailableSubCommands() bool { } } - // the command either has no sub comamnds, or no available (non deprecated/help/hidden) + // the command either has no sub commands, or no available (non deprecated/help/hidden) // sub commands return false } -// Determine if the command is a child command +// HasParent determines if the command is a child command. func (c *Command) HasParent() bool { return c.parent != nil } -// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists +// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { return c.globNormFunc } -// Get the complete FlagSet that applies to this command (local and persistent declared here and by all parents) +// Flags returns the complete FlagSet that applies +// to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } c.flags.SetOutput(c.flagErrorBuf) } + return c.flags } -// Get the local FlagSet specifically set in the current command +// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. +func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { + persistentFlags := c.PersistentFlags() + + out := flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.LocalFlags().VisitAll(func(f *flag.Flag) { + if persistentFlags.Lookup(f.Name) == nil { + out.AddFlag(f) + } + }) + return out +} + +// LocalFlags returns the local FlagSet specifically set in the current command. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() - local := flag.NewFlagSet(c.Name(), flag.ContinueOnError) - c.lflags.VisitAll(func(f *flag.Flag) { - local.AddFlag(f) - }) - if !c.HasParent() { - flag.CommandLine.VisitAll(func(f *flag.Flag) { - if local.Lookup(f.Name) == nil { - local.AddFlag(f) - } - }) + if c.lflags == nil { + c.lflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.lflags.SetOutput(c.flagErrorBuf) + } + c.lflags.SortFlags = c.Flags().SortFlags + if c.globNormFunc != nil { + c.lflags.SetNormalizeFunc(c.globNormFunc) } - return local + + addToLocal := func(f *flag.Flag) { + // Add the flag if it is not a parent PFlag, or it shadows a parent PFlag + if c.lflags.Lookup(f.Name) == nil && f != c.parentsPflags.Lookup(f.Name) { + c.lflags.AddFlag(f) + } + } + c.Flags().VisitAll(addToLocal) + c.PersistentFlags().VisitAll(addToLocal) + return c.lflags } -// All Flags which were inherited from parents commands +// InheritedFlags returns all flags which were inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) InheritedFlags() *flag.FlagSet { c.mergePersistentFlags() - inherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError) - local := c.LocalFlags() - - var rmerge func(x *Command) - - rmerge = func(x *Command) { - if x.HasPersistentFlags() { - x.PersistentFlags().VisitAll(func(f *flag.Flag) { - if inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { - inherited.AddFlag(f) - } - }) - } - if x.HasParent() { - rmerge(x.parent) + if c.iflags == nil { + c.iflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) } + c.iflags.SetOutput(c.flagErrorBuf) } - if c.HasParent() { - rmerge(c.parent) + local := c.LocalFlags() + if c.globNormFunc != nil { + c.iflags.SetNormalizeFunc(c.globNormFunc) } - return inherited + c.parentsPflags.VisitAll(func(f *flag.Flag) { + if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { + c.iflags.AddFlag(f) + } + }) + return c.iflags } -// All Flags which were not inherited from parent commands +// NonInheritedFlags returns all flags which were not inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) NonInheritedFlags() *flag.FlagSet { return c.LocalFlags() } -// Get the Persistent FlagSet specifically set in the current command +// PersistentFlags returns the persistent FlagSet specifically set in the current command. func (c *Command) PersistentFlags() *flag.FlagSet { if c.pflags == nil { - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1089,60 +1745,64 @@ func (c *Command) PersistentFlags() *flag.FlagSet { return c.pflags } -// For use in testing +// ResetFlags deletes all flags from command. func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.flags.SetOutput(c.flagErrorBuf) - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) + + c.lflags = nil + c.iflags = nil + c.parentsPflags = nil } -// Does the command contain any flags (local plus persistent from the entire structure) +// HasFlags checks if the command contains any flags (local plus persistent from the entire structure). func (c *Command) HasFlags() bool { return c.Flags().HasFlags() } -// Does the command contain persistent flags +// HasPersistentFlags checks if the command contains persistent flags. func (c *Command) HasPersistentFlags() bool { return c.PersistentFlags().HasFlags() } -// Does the command has flags specifically declared locally +// HasLocalFlags checks if the command has flags specifically declared locally. func (c *Command) HasLocalFlags() bool { return c.LocalFlags().HasFlags() } -// Does the command have flags inherited from its parent command +// HasInheritedFlags checks if the command has flags inherited from its parent command. func (c *Command) HasInheritedFlags() bool { return c.InheritedFlags().HasFlags() } -// Does the command contain any flags (local plus persistent from the entire -// structure) which are not hidden or deprecated +// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire +// structure) which are not hidden or deprecated. func (c *Command) HasAvailableFlags() bool { return c.Flags().HasAvailableFlags() } -// Does the command contain persistent flags which are not hidden or deprecated +// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. func (c *Command) HasAvailablePersistentFlags() bool { return c.PersistentFlags().HasAvailableFlags() } -// Does the command has flags specifically declared locally which are not hidden -// or deprecated +// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden +// or deprecated. func (c *Command) HasAvailableLocalFlags() bool { return c.LocalFlags().HasAvailableFlags() } -// Does the command have flags inherited from its parent command which are -// not hidden or deprecated +// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are +// not hidden or deprecated. func (c *Command) HasAvailableInheritedFlags() bool { return c.InheritedFlags().HasAvailableFlags() } -// Flag climbs up the command tree looking for matching flag +// Flag climbs up the command tree looking for matching flag. func (c *Command) Flag(name string) (flag *flag.Flag) { flag = c.Flags().Lookup(name) @@ -1153,65 +1813,84 @@ func (c *Command) Flag(name string) (flag *flag.Flag) { return } -// recursively find matching persistent flag +// Recursively find matching persistent flag. func (c *Command) persistentFlag(name string) (flag *flag.Flag) { if c.HasPersistentFlags() { flag = c.PersistentFlags().Lookup(name) } - if flag == nil && c.HasParent() { - flag = c.parent.persistentFlag(name) + if flag == nil { + c.updateParentsPflags() + flag = c.parentsPflags.Lookup(name) } return } -// ParseFlags parses persistent flag tree & local flags -func (c *Command) ParseFlags(args []string) (err error) { +// ParseFlags parses persistent flag tree and local flags. +func (c *Command) ParseFlags(args []string) error { + if c.DisableFlagParsing { + return nil + } + + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + beforeErrorBufLen := c.flagErrorBuf.Len() c.mergePersistentFlags() - err = c.Flags().Parse(args) - return + + // do it here after merging all flags and just before parse + c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist) + + err := c.Flags().Parse(args) + // Print warnings if they occurred (e.g. deprecated flag messages). + if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil { + c.Print(c.flagErrorBuf.String()) + } + + return err } -// Parent returns a commands parent command +// Parent returns a commands parent command. func (c *Command) Parent() *Command { return c.parent } +// mergePersistentFlags merges c.PersistentFlags() to c.Flags() +// and adds missing persistent flags of all parents. func (c *Command) mergePersistentFlags() { - var rmerge func(x *Command) + c.updateParentsPflags() + c.Flags().AddFlagSet(c.PersistentFlags()) + c.Flags().AddFlagSet(c.parentsPflags) +} - // Save the set of local flags - if c.lflags == nil { - c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) - if c.flagErrorBuf == nil { - c.flagErrorBuf = new(bytes.Buffer) - } - c.lflags.SetOutput(c.flagErrorBuf) - addtolocal := func(f *flag.Flag) { - c.lflags.AddFlag(f) - } - c.Flags().VisitAll(addtolocal) - c.PersistentFlags().VisitAll(addtolocal) - } - rmerge = func(x *Command) { - if !x.HasParent() { - flag.CommandLine.VisitAll(func(f *flag.Flag) { - if x.PersistentFlags().Lookup(f.Name) == nil { - x.PersistentFlags().AddFlag(f) - } - }) - } - if x.HasPersistentFlags() { - x.PersistentFlags().VisitAll(func(f *flag.Flag) { - if c.Flags().Lookup(f.Name) == nil { - c.Flags().AddFlag(f) - } - }) - } - if x.HasParent() { - rmerge(x.parent) - } +// updateParentsPflags updates c.parentsPflags by adding +// new persistent flags of all parents. +// If c.parentsPflags == nil, it makes new. +func (c *Command) updateParentsPflags() { + if c.parentsPflags == nil { + c.parentsPflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.parentsPflags.SetOutput(c.flagErrorBuf) + c.parentsPflags.SortFlags = false + } + + if c.globNormFunc != nil { + c.parentsPflags.SetNormalizeFunc(c.globNormFunc) + } + + c.Root().PersistentFlags().AddFlagSet(flag.CommandLine) + + c.VisitParents(func(parent *Command) { + c.parentsPflags.AddFlagSet(parent.PersistentFlags()) + }) +} + +// commandNameMatches checks if two command names are equal +// taking into account case sensitivity according to +// EnableCaseInsensitive global configuration. +func commandNameMatches(s string, t string) bool { + if EnableCaseInsensitive { + return strings.EqualFold(s, t) } - rmerge(c) + return s == t } diff --git a/vendor/github.com/spf13/cobra/command_notwin.go b/vendor/github.com/spf13/cobra/command_notwin.go index 6159c1cc1..307f0c127 100644 --- a/vendor/github.com/spf13/cobra/command_notwin.go +++ b/vendor/github.com/spf13/cobra/command_notwin.go @@ -1,3 +1,18 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !windows // +build !windows package cobra diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go index 4b0eaa1b6..adbef395c 100644 --- a/vendor/github.com/spf13/cobra/command_win.go +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -1,8 +1,24 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows // +build windows package cobra import ( + "fmt" "os" "time" @@ -11,16 +27,15 @@ import ( var preExecHookFn = preExecHook -// enables an information splash screen on Windows if the CLI is started from explorer.exe. -var MousetrapHelpText string = `This is a command line tool - -You need to open cmd.exe and run it from there. -` - func preExecHook(c *Command) { - if mousetrap.StartedByExplorer() { + if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { c.Print(MousetrapHelpText) - time.Sleep(5 * time.Second) + if MousetrapDisplayDuration > 0 { + time.Sleep(MousetrapDisplayDuration) + } else { + c.Println("Press return to continue...") + fmt.Scanln() + } os.Exit(1) } } diff --git a/vendor/github.com/spf13/jwalterweatherman/.gitignore b/vendor/github.com/spf13/jwalterweatherman/.gitignore index 00268614f..a71f88af8 100644 --- a/vendor/github.com/spf13/jwalterweatherman/.gitignore +++ b/vendor/github.com/spf13/jwalterweatherman/.gitignore @@ -20,3 +20,5 @@ _cgo_export.* _testmain.go *.exe +*.bench +go.sum \ No newline at end of file diff --git a/vendor/github.com/spf13/jwalterweatherman/README.md b/vendor/github.com/spf13/jwalterweatherman/README.md index c6f327c1d..932a23fc6 100644 --- a/vendor/github.com/spf13/jwalterweatherman/README.md +++ b/vendor/github.com/spf13/jwalterweatherman/README.md @@ -18,7 +18,7 @@ provides a few advantages over using the standard log library alone. I really wanted a very straightforward library that could seamlessly do the following things. -1. Replace all the println, printf, etc statements thought my code with +1. Replace all the println, printf, etc statements thoughout my code with something more useful 2. Allow the user to easily control what levels are printed to stdout 3. Allow the user to easily control what levels are logged @@ -44,7 +44,7 @@ Available Loggers are: * FATAL These each are loggers based on the log standard library and follow the -standard usage. Eg.. +standard usage. Eg. ```go import ( @@ -79,6 +79,13 @@ standard usage. Eg.. ``` +NOTE: You can also use the library in a non-global setting by creating an instance of a Notebook: + +```go +notepad = jww.NewNotepad(jww.LevelInfo, jww.LevelTrace, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) +notepad.WARN.Println("Some warning"") +``` + _Why 7 levels?_ Maybe you think that 7 levels are too much for any application... and you @@ -118,35 +125,15 @@ verbosity. Note that JWW's own internal output uses log levels as well, so set the log level before making any other calls if you want to see what it's up to. -### Using a temp log file - -JWW conveniently creates a temporary file and sets the log Handle to -a io.Writer created for it. You should call this early in your application -initialization routine as it will only log calls made after it is executed. -When this option is used, the library will fmt.Println where to find the -log file. - -```go - import ( - jww "github.com/spf13/jwalterweatherman" - ) - - jww.UseTempLogFile("YourAppName") - -``` ### Setting a log file -JWW can log to any file you provide a path to (provided it’s writable). -Will only append to this file. +JWW can log to any `io.Writer`: ```go - import ( - jww "github.com/spf13/jwalterweatherman" - ) - jww.SetLogFile("/path/to/logfile") + jww.SetLogOutput(customWriter) ``` @@ -157,5 +144,5 @@ This is an early release. I’ve been using it for a while and this is the third interface I’ve tried. I like this one pretty well, but no guarantees that it won’t change a bit. -I wrote this for use in [hugo](http://hugo.spf13.com). If you are looking +I wrote this for use in [hugo](https://gohugo.io). If you are looking for a static website engine that’s super fast please checkout Hugo. diff --git a/vendor/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go b/vendor/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go deleted file mode 100644 index b64ed469c..000000000 --- a/vendor/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright © 2016 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jwalterweatherman - -import ( - "fmt" - "io" - "io/ioutil" - "log" - "os" - "sync/atomic" -) - -// Level describes the chosen log level between -// debug and critical. -type Level int - -type NotePad struct { - Handle io.Writer - Level Level - Prefix string - Logger **log.Logger - counter uint64 -} - -func (n *NotePad) incr() { - atomic.AddUint64(&n.counter, 1) -} - -func (n *NotePad) resetCounter() { - atomic.StoreUint64(&n.counter, 0) -} - -func (n *NotePad) getCount() uint64 { - return atomic.LoadUint64(&n.counter) -} - -type countingWriter struct { - incrFunc func() -} - -func (cw *countingWriter) Write(p []byte) (n int, err error) { - cw.incrFunc() - - return 0, nil -} - -// Feedback is special. It writes plainly to the output while -// logging with the standard extra information (date, file, etc) -// Only Println and Printf are currently provided for this -type Feedback struct{} - -const ( - LevelTrace Level = iota - LevelDebug - LevelInfo - LevelWarn - LevelError - LevelCritical - LevelFatal - DefaultLogThreshold = LevelWarn - DefaultStdoutThreshold = LevelError -) - -var ( - TRACE *log.Logger - DEBUG *log.Logger - INFO *log.Logger - WARN *log.Logger - ERROR *log.Logger - CRITICAL *log.Logger - FATAL *log.Logger - LOG *log.Logger - FEEDBACK Feedback - LogHandle io.Writer = ioutil.Discard - OutHandle io.Writer = os.Stdout - BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle) - NotePads []*NotePad = []*NotePad{trace, debug, info, warn, err, critical, fatal} - - trace *NotePad = &NotePad{Level: LevelTrace, Handle: os.Stdout, Logger: &TRACE, Prefix: "TRACE: "} - debug *NotePad = &NotePad{Level: LevelDebug, Handle: os.Stdout, Logger: &DEBUG, Prefix: "DEBUG: "} - info *NotePad = &NotePad{Level: LevelInfo, Handle: os.Stdout, Logger: &INFO, Prefix: "INFO: "} - warn *NotePad = &NotePad{Level: LevelWarn, Handle: os.Stdout, Logger: &WARN, Prefix: "WARN: "} - err *NotePad = &NotePad{Level: LevelError, Handle: os.Stdout, Logger: &ERROR, Prefix: "ERROR: "} - critical *NotePad = &NotePad{Level: LevelCritical, Handle: os.Stdout, Logger: &CRITICAL, Prefix: "CRITICAL: "} - fatal *NotePad = &NotePad{Level: LevelFatal, Handle: os.Stdout, Logger: &FATAL, Prefix: "FATAL: "} - logThreshold Level = DefaultLogThreshold - outputThreshold Level = DefaultStdoutThreshold -) - -const ( - DATE = log.Ldate - TIME = log.Ltime - SFILE = log.Lshortfile - LFILE = log.Llongfile - MSEC = log.Lmicroseconds -) - -var logFlags = DATE | TIME | SFILE - -func init() { - SetStdoutThreshold(DefaultStdoutThreshold) -} - -// initialize will setup the jWalterWeatherman standard approach of providing the user -// some feedback and logging a potentially different amount based on independent log and output thresholds. -// By default the output has a lower threshold than logged -// Don't use if you have manually set the Handles of the different levels as it will overwrite them. -func initialize() { - BothHandle = io.MultiWriter(LogHandle, OutHandle) - - for _, n := range NotePads { - if n.Level < outputThreshold && n.Level < logThreshold { - n.Handle = ioutil.Discard - } else if n.Level >= outputThreshold && n.Level >= logThreshold { - n.Handle = BothHandle - } else if n.Level >= outputThreshold && n.Level < logThreshold { - n.Handle = OutHandle - } else { - n.Handle = LogHandle - } - } - - for _, n := range NotePads { - n.Handle = io.MultiWriter(n.Handle, &countingWriter{n.incr}) - *n.Logger = log.New(n.Handle, n.Prefix, logFlags) - } - - LOG = log.New(LogHandle, - "LOG: ", - logFlags) -} - -// Set the log Flags (Available flag: DATE, TIME, SFILE, LFILE and MSEC) -func SetLogFlag(flags int) { - logFlags = flags - initialize() -} - -// Level returns the current global log threshold. -func LogThreshold() Level { - return logThreshold -} - -// Level returns the current global output threshold. -func StdoutThreshold() Level { - return outputThreshold -} - -// Ensures that the level provided is within the bounds of available levels -func levelCheck(level Level) Level { - switch { - case level <= LevelTrace: - return LevelTrace - case level >= LevelFatal: - return LevelFatal - default: - return level - } -} - -// Establishes a threshold where anything matching or above will be logged -func SetLogThreshold(level Level) { - logThreshold = levelCheck(level) - initialize() -} - -// Establishes a threshold where anything matching or above will be output -func SetStdoutThreshold(level Level) { - outputThreshold = levelCheck(level) - initialize() -} - -// Conveniently Sets the Log Handle to a io.writer created for the file behind the given filepath -// Will only append to this file -func SetLogFile(path string) { - file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) - if err != nil { - CRITICAL.Println("Failed to open log file:", path, err) - os.Exit(-1) - } - - INFO.Println("Logging to", file.Name()) - - LogHandle = file - initialize() -} - -// Conveniently Creates a temporary file and sets the Log Handle to a io.writer created for it -func UseTempLogFile(prefix string) { - file, err := ioutil.TempFile(os.TempDir(), prefix) - if err != nil { - CRITICAL.Println(err) - } - - INFO.Println("Logging to", file.Name()) - - LogHandle = file - initialize() -} - -// LogCountForLevel returns the number of log invocations for a given level. -func LogCountForLevel(l Level) uint64 { - for _, np := range NotePads { - if np.Level == l { - return np.getCount() - } - } - return 0 -} - -// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations -// greater than or equal to a given level threshold. -func LogCountForLevelsGreaterThanorEqualTo(threshold Level) uint64 { - var cnt uint64 - for _, np := range NotePads { - if np.Level >= threshold { - cnt += np.getCount() - } - } - return cnt -} - -// ResetLogCounters resets the invocation counters for all levels. -func ResetLogCounters() { - for _, np := range NotePads { - np.resetCounter() - } -} - -// Disables logging for the entire JWW system -func DiscardLogging() { - LogHandle = ioutil.Discard - initialize() -} - -// Feedback is special. It writes plainly to the output while -// logging with the standard extra information (date, file, etc) -// Only Println and Printf are currently provided for this -func (fb *Feedback) Println(v ...interface{}) { - s := fmt.Sprintln(v...) - fmt.Print(s) - LOG.Output(2, s) -} - -// Feedback is special. It writes plainly to the output while -// logging with the standard extra information (date, file, etc) -// Only Println and Printf are currently provided for this -func (fb *Feedback) Printf(format string, v ...interface{}) { - s := fmt.Sprintf(format, v...) - fmt.Print(s) - LOG.Output(2, s) -} diff --git a/vendor/github.com/tdewolff/minify/v2/.gitignore b/vendor/github.com/tdewolff/minify/v2/.gitignore index c9ea38dbc..e2cf6cf8e 100644 --- a/vendor/github.com/tdewolff/minify/v2/.gitignore +++ b/vendor/github.com/tdewolff/minify/v2/.gitignore @@ -23,8 +23,10 @@ bindings/js/example/node_modules bindings/js/example/test.min.html bindings/py/go.mod bindings/py/go.sum -bindings/py/minify.h -bindings/py/minify.so -bindings/py/tdewolff_minify.egg-info +bindings/py/**/*.h +bindings/py/**/*.so +bindings/py/**/*.egg-info bindings/py/example/example.min.html bindings/py/dist +bindings/py/build +bindings/py/**/*.pyc diff --git a/vendor/github.com/tdewolff/minify/v2/README.md b/vendor/github.com/tdewolff/minify/v2/README.md index d2bfff407..81d91b8ed 100644 --- a/vendor/github.com/tdewolff/minify/v2/README.md +++ b/vendor/github.com/tdewolff/minify/v2/README.md @@ -1,27 +1,30 @@ -# Minify [![API reference](https://img.shields.io/badge/godoc-reference-5272B4)](https://pkg.go.dev/github.com/tdewolff/minify/v2?tab=doc) [![Go Report Card](https://goreportcard.com/badge/github.com/tdewolff/minify)](https://goreportcard.com/report/github.com/tdewolff/minify) [![codecov](https://codecov.io/gh/tdewolff/minify/branch/master/graph/badge.svg?token=Cr7r2EKPj2)](https://codecov.io/gh/tdewolff/minify) [![Donate](https://img.shields.io/badge/patreon-donate-DFB317)](https://www.patreon.com/tdewolff) +# Minify [![API reference](https://img.shields.io/badge/godoc-reference-5272B4)](https://pkg.go.dev/github.com/tdewolff/minify/v2?tab=doc) [![Go Report Card](https://goreportcard.com/badge/github.com/tdewolff/minify)](https://goreportcard.com/report/github.com/tdewolff/minify) [![codecov](https://codecov.io/gh/tdewolff/minify/branch/master/graph/badge.svg?token=Cr7r2EKPj2)](https://codecov.io/gh/tdewolff/minify) **[Online demo](https://go.tacodewolff.nl/minify)** if you need to minify files *now*. **[Binaries](https://github.com/tdewolff/minify/releases) of CLI for various platforms.** See [CLI](https://github.com/tdewolff/minify/tree/master/cmd/minify) for more installation instructions. +**[Windows binary from scoop](https://scoop.sh/#/apps?q=minify)** install with `scoop install main/minify` + **[Python bindings](https://pypi.org/project/tdewolff-minify/)** install with `pip install tdewolff-minify` **[JavaScript bindings](https://www.npmjs.com/package/@tdewolff/minify)** install with `npm i @tdewolff/minify` +**[.NET bindings](https://github.com/JKamsker/NMinify)** install with `Install-Package NMinify` or `dotnet add package NMinify`, thanks to Jonas Kamsker for the port + --- *Did you know that the shortest valid piece of HTML5 is `x`? See for yourself at the [W3C Validator](http://validator.w3.org/)!* -Minify is a minifier package written in [Go][1]. It provides HTML5, CSS3, JS, JSON, SVG and XML minifiers and an interface to implement any other minifier. Minification is the process of removing bytes from a file (such as whitespace) without changing its output and therefore shrinking its size and speeding up transmission over the internet and possibly parsing. The implemented minifiers are designed for high performance. +Minify is a minifier package written in [Go][1]. It provides HTML5, CSS3, JS, JSON, SVG and XML minifiers and an interface to implement any other minifier. Minification is the process of removing bytes from a file (such as whitespace) without changing its output and therefore shrinking its size and speeding up transmission over the internet and possibly parsing. The implemented minifiers are designed for high performance (see https://github.com/privatenumber/minification-benchmarks where this library is (one of) the fastest JS minifiers). The core functionality associates mimetypes with minification functions, allowing embedded resources (like CSS or JS within HTML files) to be minified as well. Users can add new implementations that are triggered based on a mimetype (or pattern), or redirect to an external command (like ClosureCompiler, UglifyCSS, ...). ### Sponsors +I'm actively looking for support in the form of donations or sponsorships to keep developing this library and highly appreciate any gesture. Please see the Sponsors button in GitHub for ways to contribute, or contact me directly. [![SiteGround](https://www.siteground.com/img/downloads/siteground-logo-black-transparent-vector.svg)](https://www.siteground.com/) -Please see https://www.patreon.com/tdewolff for ways to contribute, otherwise please contact me directly! - #### Table of Contents - [Minify](#minify) @@ -77,7 +80,7 @@ Minifiers or bindings to minifiers exist in almost all programming languages. So This minifier proves to be that fast and extensive minifier that can handle HTML and any other filetype it may contain (CSS, JS, ...). It is usually orders of magnitude faster than existing minifiers. ## Installation -Make sure you have [Git](https://git-scm.com/) and [Go](https://golang.org/dl/) (1.13 or higher) installed, run +Make sure you have [Git](https://git-scm.com/) and [Go](https://golang.org/dl/) (1.18 or higher) installed, run ``` mkdir Project cd Project @@ -196,12 +199,13 @@ The HTML5 minifier uses these minifications: Options: -- `KeepConditionalComments` preserve all IE conditional comments such as `` and ``, see https://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx#syntax +- `KeepSpecialComments` preserve all special comments, including Server Side Includes such as `` and IE conditional comments such as `` and ``, see https://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx#syntax - `KeepDefaultAttrVals` preserve default attribute values such as `