diff options
Diffstat (limited to 'vendor/github.com/playwright-community/playwright-go/helpers.go')
| -rw-r--r-- | vendor/github.com/playwright-community/playwright-go/helpers.go | 628 |
1 files changed, 0 insertions, 628 deletions
diff --git a/vendor/github.com/playwright-community/playwright-go/helpers.go b/vendor/github.com/playwright-community/playwright-go/helpers.go deleted file mode 100644 index b2244f1..0000000 --- a/vendor/github.com/playwright-community/playwright-go/helpers.go +++ /dev/null @@ -1,628 +0,0 @@ -package playwright - -import ( - "errors" - "fmt" - "reflect" - "regexp" - "strings" - "sync" - "sync/atomic" - - mapset "github.com/deckarep/golang-set/v2" -) - -type ( - routeHandler = func(Route) -) - -func skipFieldSerialization(val reflect.Value) bool { - typ := val.Type() - return (typ.Kind() == reflect.Ptr || - typ.Kind() == reflect.Interface || - typ.Kind() == reflect.Map || - typ.Kind() == reflect.Slice) && val.IsNil() || (val.Kind() == reflect.Interface && val.Elem().Kind() == reflect.Ptr && val.Elem().IsNil()) -} - -func transformStructValues(in interface{}) interface{} { - v := reflect.ValueOf(in) - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - if _, ok := in.(*channel); ok { - return in - } - if v.Kind() == reflect.Map || v.Kind() == reflect.Struct { - return transformStructIntoMapIfNeeded(in) - } - if v.Kind() == reflect.Slice { - outSlice := []interface{}{} - for i := 0; i < v.Len(); i++ { - if !skipFieldSerialization(v.Index(i)) { - outSlice = append(outSlice, transformStructValues(v.Index(i).Interface())) - } - } - return outSlice - } - if v.Interface() == Null() || (v.Kind() == reflect.String && v.String() == Null().(string)) { - return "null" - } - return in -} - -func transformStructIntoMapIfNeeded(inStruct interface{}) map[string]interface{} { - out := make(map[string]interface{}) - v := reflect.ValueOf(inStruct) - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - typ := v.Type() - if v.Kind() == reflect.Struct { - // Merge into the base map by the JSON struct tag - for i := 0; i < v.NumField(); i++ { - fi := typ.Field(i) - // Skip the values when the field is a pointer (like *string) and nil. - if fi.IsExported() && !skipFieldSerialization(v.Field(i)) { - // We use the JSON struct fields for getting the original names - // out of the field. - tagv := fi.Tag.Get("json") - key := strings.Split(tagv, ",")[0] - if key == "" { - key = fi.Name - } - out[key] = transformStructValues(v.Field(i).Interface()) - } - } - } else if v.Kind() == reflect.Map { - // Merge into the base map - for _, key := range v.MapKeys() { - if !skipFieldSerialization(v.MapIndex(key)) { - out[key.String()] = transformStructValues(v.MapIndex(key).Interface()) - } - } - } - return out -} - -// transformOptions handles the parameter data transformation -func transformOptions(options ...interface{}) map[string]interface{} { - var base map[string]interface{} - var option interface{} - // Case 1: No options are given - if len(options) == 0 { - return make(map[string]interface{}) - } - if len(options) == 1 { - // Case 2: a single value (either struct or map) is given. - base = make(map[string]interface{}) - option = options[0] - } else if len(options) == 2 { - // Case 3: two values are given. The first one needs to be transformed - // to a map, the sencond one will be then get merged into the first - // base map. - if reflect.ValueOf(options[0]).Kind() != reflect.Map { - base = transformOptions(options[0]) - } else { - base = transformStructIntoMapIfNeeded(options[0]) - } - option = options[1] - } - v := reflect.ValueOf(option) - if v.Kind() == reflect.Slice { - if v.Len() == 0 { - return base - } - option = v.Index(0).Interface() - } - - if option == nil { - return base - } - v = reflect.ValueOf(option) - - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - - optionMap := transformStructIntoMapIfNeeded(v.Interface()) - for key, value := range optionMap { - base[key] = value - } - return base -} - -func remapValue(inMapValue reflect.Value, outStructValue reflect.Value) { - switch outStructValue.Type().Kind() { - case reflect.Bool: - outStructValue.SetBool(inMapValue.Bool()) - case reflect.String: - outStructValue.SetString(inMapValue.String()) - case reflect.Float64: - outStructValue.SetFloat(inMapValue.Float()) - case reflect.Int: - outStructValue.SetInt(int64(inMapValue.Float())) - case reflect.Slice: - outStructValue.Set(reflect.MakeSlice(outStructValue.Type(), inMapValue.Len(), inMapValue.Cap())) - for i := 0; i < inMapValue.Len(); i++ { - remapValue(inMapValue.Index(i).Elem(), outStructValue.Index(i)) - } - case reflect.Struct: - structTyp := outStructValue.Type() - for i := 0; i < outStructValue.NumField(); i++ { - fi := structTyp.Field(i) - key := strings.Split(fi.Tag.Get("json"), ",")[0] - structField := outStructValue.Field(i) - structFieldDeref := outStructValue.Field(i) - if structField.Type().Kind() == reflect.Ptr { - structField.Set(reflect.New(structField.Type().Elem())) - structFieldDeref = structField.Elem() - } - for _, e := range inMapValue.MapKeys() { - if key == e.String() { - value := inMapValue.MapIndex(e) - remapValue(value.Elem(), structFieldDeref) - } - } - } - default: - panic(inMapValue.Interface()) - } -} - -func remapMapToStruct(inputMap interface{}, outStruct interface{}) { - remapValue(reflect.ValueOf(inputMap), reflect.ValueOf(outStruct).Elem()) -} - -type urlMatcher struct { - raw interface{} - pattern *regexp.Regexp - matchFn func(url string) bool -} - -func newURLMatcher(urlOrPredicate interface{}, baseURL *string, isWsUrl ...bool) *urlMatcher { - switch v := urlOrPredicate.(type) { - case *regexp.Regexp: - return &urlMatcher{pattern: v, raw: urlOrPredicate} - case string: - return &urlMatcher{ - pattern: resolveGlobToRegex(baseURL, v, len(isWsUrl) > 0 && isWsUrl[0]), - raw: urlOrPredicate, - } - } - fn, ok := urlOrPredicate.(func(string) bool) - if ok { - return &urlMatcher{ - matchFn: fn, - raw: urlOrPredicate, - } - } - panic(fmt.Errorf("invalid urlOrPredicate: %v", urlOrPredicate)) -} - -func (u *urlMatcher) Matches(url string) bool { - if u.matchFn != nil { - return u.matchFn(url) - } - if u.pattern != nil { - return u.pattern.MatchString(url) - } - return false -} - -// SameWith compares String() if urlOrPredicate is *regexp.Regexp -func (u *urlMatcher) SameWith(urlOrPredicate interface{}) bool { - switch v := urlOrPredicate.(type) { - case *regexp.Regexp: - return u.pattern.String() == v.String() - default: - return u.raw == urlOrPredicate - } -} - -type routeHandlerInvocation struct { - route Route - complete chan bool -} - -type routeHandlerEntry struct { - matcher *urlMatcher - handler routeHandler - times int - count int32 - ignoreErrors *atomic.Bool - activeInvocations mapset.Set[*routeHandlerInvocation] -} - -func (r *routeHandlerEntry) Matches(url string) bool { - return r.matcher.Matches(url) -} - -func (r *routeHandlerEntry) Handle(route Route) chan bool { - handlerInvocation := &routeHandlerInvocation{ - route: route, - complete: make(chan bool, 1), - } - r.activeInvocations.Add(handlerInvocation) - - defer func() { - handlerInvocation.complete <- true - r.activeInvocations.Remove(handlerInvocation) - }() - defer func() { - // If the handler was stopped (without waiting for completion), we ignore all exceptions. - if r.ignoreErrors.Load() { - _ = recover() - route.(*routeImpl).reportHandled(false) - } else { - e := recover() - if e != nil { - err, ok := e.(error) - if ok && errors.Is(err, ErrTargetClosed) { - panic(fmt.Errorf("\"%w\" while running route callback.\nConsider awaiting `page.UnrouteAll(playwright.PageUnrouteAllOptions{Behavior: playwright.UnrouteBehaviorIgnoreErrors})`\nbefore the end of the test to ignore remaining routes in flight.", err)) - } - panic(e) - } - } - }() - - return r.handleInternal(route) -} - -func (r *routeHandlerEntry) Stop(behavior string) { - // When a handler is manually unrouted or its page/context is closed we either - // - wait for the current handler invocations to finish - // - or do not wait, if the user opted out of it, but swallow all exceptions - // that happen after the unroute/close. - if behavior == string(*UnrouteBehaviorIgnoreErrors) { - r.ignoreErrors.Store(true) - } else { - wg := &sync.WaitGroup{} - r.activeInvocations.Each(func(activation *routeHandlerInvocation) bool { - if !activation.route.(*routeImpl).didThrow { - wg.Add(1) - go func(complete chan bool) { - <-complete - wg.Done() - }(activation.complete) - } - return false - }) - wg.Wait() - } -} - -func (r *routeHandlerEntry) handleInternal(route Route) chan bool { - handled := route.(*routeImpl).startHandling() - atomic.AddInt32(&r.count, 1) - r.handler(route) - return handled -} - -func (r *routeHandlerEntry) WillExceed() bool { - if r.times == 0 { - return false - } - return int(atomic.LoadInt32(&r.count)+1) >= r.times -} - -func newRouteHandlerEntry(matcher *urlMatcher, handler routeHandler, times ...int) *routeHandlerEntry { - n := 0 - if len(times) > 0 { - n = times[0] - } - return &routeHandlerEntry{ - matcher: matcher, - handler: handler, - times: n, - count: 0, - ignoreErrors: &atomic.Bool{}, - activeInvocations: mapset.NewSet[*routeHandlerInvocation](), - } -} - -func prepareInterceptionPatterns(handlers []*routeHandlerEntry) []map[string]interface{} { - patterns := []map[string]interface{}{} - all := false - for _, h := range handlers { - switch h.matcher.raw.(type) { - case *regexp.Regexp: - pattern, flags := convertRegexp(h.matcher.raw.(*regexp.Regexp)) - patterns = append(patterns, map[string]interface{}{ - "regexSource": pattern, - "regexFlags": flags, - }) - case string: - patterns = append(patterns, map[string]interface{}{ - "glob": h.matcher.raw.(string), - }) - default: - all = true - } - } - if all { - return []map[string]interface{}{ - { - "glob": "**/*", - }, - } - } - return patterns -} - -const defaultTimeout = 30 * 1000 - -type timeoutSettings struct { - sync.RWMutex - parent *timeoutSettings - defaultTimeout *float64 - defaultNavigationTimeout *float64 -} - -func (t *timeoutSettings) SetDefaultTimeout(timeout *float64) { - t.Lock() - defer t.Unlock() - t.defaultTimeout = timeout -} - -func (t *timeoutSettings) DefaultTimeout() *float64 { - t.RLock() - defer t.RUnlock() - return t.defaultTimeout -} - -func (t *timeoutSettings) Timeout(timeout ...float64) float64 { - t.RLock() - defer t.RUnlock() - if len(timeout) == 1 { - return timeout[0] - } - if t.defaultTimeout != nil { - return *t.defaultTimeout - } - if t.parent != nil { - return t.parent.Timeout() - } - return defaultTimeout -} - -func (t *timeoutSettings) DefaultNavigationTimeout() *float64 { - t.RLock() - defer t.RUnlock() - return t.defaultNavigationTimeout -} - -func (t *timeoutSettings) SetDefaultNavigationTimeout(navigationTimeout *float64) { - t.Lock() - defer t.Unlock() - t.defaultNavigationTimeout = navigationTimeout -} - -func (t *timeoutSettings) NavigationTimeout() float64 { - t.RLock() - defer t.RUnlock() - if t.defaultNavigationTimeout != nil { - return *t.defaultNavigationTimeout - } - if t.parent != nil { - return t.parent.NavigationTimeout() - } - return defaultTimeout -} - -func newTimeoutSettings(parent *timeoutSettings) *timeoutSettings { - return &timeoutSettings{ - parent: parent, - defaultTimeout: nil, - defaultNavigationTimeout: nil, - } -} - -// SelectOptionValues is the option struct for ElementHandle.Select() etc. -type SelectOptionValues struct { - ValuesOrLabels *[]string - Values *[]string - Indexes *[]int - Labels *[]string - Elements *[]ElementHandle -} - -func convertSelectOptionSet(values SelectOptionValues) map[string]interface{} { - out := make(map[string]interface{}) - if values == (SelectOptionValues{}) { - return out - } - - var o []map[string]interface{} - if values.ValuesOrLabels != nil { - for _, v := range *values.ValuesOrLabels { - m := map[string]interface{}{"valueOrLabel": v} - o = append(o, m) - } - } - if values.Values != nil { - for _, v := range *values.Values { - m := map[string]interface{}{"value": v} - o = append(o, m) - } - } - if values.Indexes != nil { - for _, i := range *values.Indexes { - m := map[string]interface{}{"index": i} - o = append(o, m) - } - } - if values.Labels != nil { - for _, l := range *values.Labels { - m := map[string]interface{}{"label": l} - o = append(o, m) - } - } - if o != nil { - out["options"] = o - } - - var e []*channel - if values.Elements != nil { - for _, eh := range *values.Elements { - e = append(e, eh.(*elementHandleImpl).channel) - } - } - if e != nil { - out["elements"] = e - } - - return out -} - -func unroute(inRoutes []*routeHandlerEntry, url interface{}, handlers ...routeHandler) ([]*routeHandlerEntry, []*routeHandlerEntry, error) { - var handler routeHandler - if len(handlers) == 1 { - handler = handlers[0] - } - handlerPtr := reflect.ValueOf(handler).Pointer() - - removed := make([]*routeHandlerEntry, 0) - remaining := make([]*routeHandlerEntry, 0) - - for _, route := range inRoutes { - routeHandlerPtr := reflect.ValueOf(route.handler).Pointer() - // note: compare regex expression if url is a regexp, not pointer - if !route.matcher.SameWith(url) || - (handler != nil && routeHandlerPtr != handlerPtr) { - remaining = append(remaining, route) - } else { - removed = append(removed, route) - } - } - - return removed, remaining, nil -} - -func serializeMapToNameAndValue(headers map[string]string) []map[string]string { - serialized := make([]map[string]string, 0) - for name, value := range headers { - serialized = append(serialized, map[string]string{ - "name": name, - "value": value, - }) - } - return serialized -} - -// assignStructFields assigns fields from src to dest, -// -// omitExtra determines whether to omit src's extra fields -func assignStructFields(dest, src interface{}, omitExtra bool) error { - destValue := reflect.ValueOf(dest) - if destValue.Kind() != reflect.Ptr || destValue.IsNil() { - return fmt.Errorf("dest must be a non-nil pointer") - } - destValue = destValue.Elem() - if destValue.Kind() != reflect.Struct { - return fmt.Errorf("dest must be a struct") - } - - srcValue := reflect.ValueOf(src) - if srcValue.Kind() == reflect.Ptr { - srcValue = srcValue.Elem() - } - if srcValue.Kind() != reflect.Struct { - return fmt.Errorf("src must be a struct") - } - - for i := 0; i < destValue.NumField(); i++ { - destField := destValue.Field(i) - destFieldType := destField.Type() - destFieldName := destValue.Type().Field(i).Name - - if srcField := srcValue.FieldByName(destFieldName); srcField.IsValid() && srcField.Type() != destFieldType { - return fmt.Errorf("mismatched field type for field %s", destFieldName) - } else if srcField.IsValid() { - destField.Set(srcField) - } - } - - if !omitExtra { - for i := 0; i < srcValue.NumField(); i++ { - srcFieldName := srcValue.Type().Field(i).Name - - if destField := destValue.FieldByName(srcFieldName); !destField.IsValid() { - return fmt.Errorf("extra field %s in src", srcFieldName) - } - } - } - - return nil -} - -func deserializeNameAndValueToMap(headersArray []map[string]string) map[string]string { - unserialized := make(map[string]string) - for _, item := range headersArray { - unserialized[item["name"]] = item["value"] - } - return unserialized -} - -type recordHarOptions struct { - Path string `json:"path"` - Content *HarContentPolicy `json:"content,omitempty"` - Mode *HarMode `json:"mode,omitempty"` - UrlGlob *string `json:"urlGlob,omitempty"` - UrlRegexSource *string `json:"urlRegexSource,omitempty"` - UrlRegexFlags *string `json:"urlRegexFlags,omitempty"` -} - -type recordHarInputOptions struct { - Path string - URL interface{} - Mode *HarMode - Content *HarContentPolicy - OmitContent *bool -} - -type harRecordingMetadata struct { - Path string - Content *HarContentPolicy -} - -func prepareRecordHarOptions(option recordHarInputOptions) recordHarOptions { - out := recordHarOptions{ - Path: option.Path, - } - if option.URL != nil { - switch option.URL.(type) { - case *regexp.Regexp: - pattern, flags := convertRegexp(option.URL.(*regexp.Regexp)) - out.UrlRegexSource = String(pattern) - out.UrlRegexFlags = String(flags) - case string: - out.UrlGlob = String(option.URL.(string)) - } - } - if option.Mode != nil { - out.Mode = option.Mode - } - if option.Content != nil { - out.Content = option.Content - } else if option.OmitContent != nil && *option.OmitContent { - out.Content = HarContentPolicyOmit - } - return out -} - -type safeValue[T any] struct { - sync.Mutex - v T -} - -func (s *safeValue[T]) Set(v T) { - s.Lock() - defer s.Unlock() - s.v = v -} - -func (s *safeValue[T]) Get() T { - s.Lock() - defer s.Unlock() - return s.v -} |
