diff options
author | Giacomo Cavalieri <giacomo.cavalieri@icloud.com> | 2023-04-21 15:04:50 +0200 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2023-04-29 14:33:18 +0100 |
commit | 54b22b142d17f0fd893ec2465e53b92109aadb48 (patch) | |
tree | c7a6bba9e1c1f35e0285570cda7e4468eb9283b0 /src | |
parent | 8924398359342ad33e99d707a3c8a7fb44d99da0 (diff) | |
download | gleam_stdlib-54b22b142d17f0fd893ec2465e53b92109aadb48.tar.gz gleam_stdlib-54b22b142d17f0fd893ec2465e53b92109aadb48.zip |
Fix `dynamic.field` behaviour
Diffstat (limited to 'src')
-rw-r--r-- | src/gleam/dynamic.gleam | 21 | ||||
-rw-r--r-- | src/gleam_stdlib.erl | 10 | ||||
-rw-r--r-- | src/gleam_stdlib.mjs | 19 |
3 files changed, 35 insertions, 15 deletions
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index a845b1c..4f0708f 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -474,20 +474,29 @@ if javascript { /// pub fn field(named name: a, of inner_type: Decoder(t)) -> Decoder(t) { fn(value) { - value - |> decode_field(name) - |> result.try(inner_type) - |> map_errors(push_path(_, name)) + case decode_field(value, name) { + Error(not_a_map_errors) -> Error(not_a_map_errors) + Ok(dynamic_field_result) -> + dynamic_field_result + |> result.try(inner_type) + |> map_errors(push_path(_, name)) + } } } if erlang { - external fn decode_field(Dynamic, name) -> Result(Dynamic, DecodeErrors) = + external fn decode_field( + Dynamic, + name, + ) -> Result(Result(Dynamic, DecodeErrors), DecodeErrors) = "gleam_stdlib" "decode_field" } if javascript { - external fn decode_field(Dynamic, name) -> Result(Dynamic, DecodeErrors) = + external fn decode_field( + Dynamic, + name, + ) -> Result(Result(Dynamic, DecodeErrors), DecodeErrors) = "../gleam_stdlib.mjs" "decode_field" } diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl index 33c9609..4c59893 100644 --- a/src/gleam_stdlib.erl +++ b/src/gleam_stdlib.erl @@ -78,12 +78,14 @@ decode_bool(Data) -> decode_error_msg(<<"Bool">>, Data). decode_list(Data) when is_list(Data) -> {ok, Data}; decode_list(Data) -> decode_error_msg(<<"List">>, Data). -decode_field(Data, Key) -> +decode_field(Data, Key) when is_map(Data) -> case Data of - #{Key := Value} -> {ok, Value}; + #{Key := Value} -> {ok, {ok, Value}}; _ -> - decode_error(<<"field"/utf8>>, <<"nothing"/utf8>>) - end. + {ok, decode_error(<<"field"/utf8>>, <<"nothing"/utf8>>)} + end; +decode_field(Data, _) -> + decode_error_msg(<<"Map">>, Data). size_of_tuple(Data) -> tuple_size(Data). diff --git a/src/gleam_stdlib.mjs b/src/gleam_stdlib.mjs index 2b0a6e1..52fbc89 100644 --- a/src/gleam_stdlib.mjs +++ b/src/gleam_stdlib.mjs @@ -663,14 +663,23 @@ export function decode_option(data, decoder) { } export function decode_field(value, name) { - let error = () => decoder_error_no_classify("field", "nothing"); - if (value instanceof PMap) { + let missing_field_error = () => decoder_error_no_classify("field", "nothing"); + let not_a_map_error = () => decoder_error("Map", value); + + if (value instanceof PMap || value instanceof WeakMap || value instanceof Map) { let entry = map_get(value, name); - return entry.isOk() ? entry : error(); + return new Ok(entry.isOk() ? entry : missing_field_error()); + } else if (Object.getPrototypeOf(value) == Object.prototype) { + return try_get_field(value, name, () => new Ok(missing_field_error())); + } else { + return try_get_field(value, name, not_a_map_error); } +} + +function try_get_field(value, field, or_else) { try { - return name in value ? new Ok(value[name]) : error(); + return field in value ? new Ok(new Ok(value[field])) : or_else(); } catch { - return error(); + return or_else(); } } |