anchor.diff:  validate_funterm(FunTerm) ->
       throw({"cannot parse funterm", FunTerm}).
   
  -   
  +%% Decode a bucket property that was set using JSON/HTTP interface
  +erlify_json_funterm(<<"erlang">>, Props) ->
  +    Mod = to_modfun(proplists:get_value(<<"module">>, Props, undefined)),
  +    Fun = to_modfun(proplists:get_value(<<"function">>, Props, undefined)),
  +    Arg = proplists:get_value(<<"arg">>, Props, undefined),
  +    {{modfun, Mod, Fun}, Arg};
  +erlify_json_funterm(<<"javascript">>, Props) ->
  +    Source = proplists:get_value(<<"source">>, Props, undefined),
  +    Name = proplists:get_value(<<"name">>, Props, undefined),
  +    Arg = proplists:get_value(<<"arg">>, Props, undefined),
  +    case Source of
  +        undefined ->
  +            case Name of
  +                undefined ->
  +                    throw("javascript kv/search extractor must have name or source");
  +                _ ->
  +                    {{jsfun, Name}, Arg}
  +            end;
  +        _ ->
  +            {{jsanon, Source}, Arg}
  +    end;
  +erlify_json_funterm(Lang, _Props) ->
  +    throw({"kv/search extractors must be written in erlang or javascript", Lang}).
  +
  +     
  +
   -spec to_modfun(list() | atom()) -> atom().
   to_modfun(List) when is_list(List) ->
       %% Using list_to_atom here so that the extractor module
  
positive.code:                          {user_funterm(), args()}) -> {funterm(), args()}.
  validate_extractor(undefined) ->
      {?DEFAULT_EXTRACTOR, ?DEFAULT_ARGS};
  validate_extractor({FunTerm, Args}) when is_tuple(FunTerm) ->
      {validate_funterm(FunTerm), Args};
  validate_extractor(FunTerm) ->
  
negative.code: 
  -type index() :: binary().
  -type docid() :: binary().
  -type idxdoc() :: tuple(). % #riak_indexed_doc{}
  
  -type search_fields() :: [{search_field(),search_data()}].
  -type search_field() :: string().
  