(ctx context.Context, val AnyResult)
| 2182 | } |
| 2183 | |
| 2184 | func (s *Server) toSelectable(ctx context.Context, val AnyResult) (AnyObjectResult, error) { |
| 2185 | if sel, ok := val.(AnyObjectResult); ok { |
| 2186 | // We always support returning something that's already Selectable, e.g. an |
| 2187 | // object loaded from its ID. |
| 2188 | return sel, nil |
| 2189 | } |
| 2190 | |
| 2191 | className := val.Type().Name() |
| 2192 | if class, ok := s.ObjectType(className); ok { |
| 2193 | return class.New(val) |
| 2194 | } |
| 2195 | // Current server doesn't know the type; fall back to the class captured on |
| 2196 | // the result's shared payload when it was first wrapped. This handles |
| 2197 | // cross-module cases where the concrete type lives in a module not |
| 2198 | // installed in this server's schema. |
| 2199 | shared := val.cacheSharedResult() |
| 2200 | if shared != nil { |
| 2201 | if state := shared.loadPayloadState(); state.objClass != nil && state.objClass.TypeName() == className { |
| 2202 | return state.objClass.New(val) |
| 2203 | } |
| 2204 | } |
| 2205 | // Last resort: rebuild a dep-aware resolver from the result's call frame. |
| 2206 | // Reached when class capture missed a path; once we resolve here we |
| 2207 | // remember the class on the shared so subsequent hits skip this branch. |
| 2208 | if shared != nil && s.resultServerForCall != nil { |
| 2209 | if depResolver, err := resolverForSharedResultObject(ctx, s, shared, className); err == nil && depResolver != nil { |
| 2210 | if class, ok := depResolver.ObjectType(className); ok { |
| 2211 | shared.setObjClass(class) |
| 2212 | return class.New(val) |
| 2213 | } |
| 2214 | } |
| 2215 | } |
| 2216 | return nil, fmt.Errorf("toSelectable: unknown type %q", className) |
| 2217 | } |
| 2218 | |
| 2219 | // typeConditionMatches returns true if the given type condition (from a |
| 2220 | // fragment spread or inline fragment) matches the given object type name. |
no test coverage detected