Skip to content

Commit d452f95

Browse files
committed
Decode JS objects, maps, weakmaps
1 parent f5585ad commit d452f95

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

src/gleam_stdlib_decode_ffi.mjs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,18 @@ export function dict(data) {
6464
if (data instanceof Dict) {
6565
return new Ok(data);
6666
}
67-
return new Error();
67+
if (data instanceof Map || data instanceof WeakMap) {
68+
return new Ok(Dict.fromMap(data));
69+
}
70+
if (data == null) {
71+
return new Error("Dict");
72+
}
73+
if (typeof data !== "object") {
74+
return new Error("Dict");
75+
}
76+
const proto = Object.getPrototypeOf(data);
77+
if (proto === Object.prototype || proto === null) {
78+
return new Ok(Dict.fromObject(data));
79+
}
80+
return new Error("Dict");
6881
}

test/gleam/dynamic/decode_test.gleam

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import gleam/dict
2-
import gleam/dynamic.{DecodeError}
2+
import gleam/dynamic.{type Dynamic, DecodeError}
33
import gleam/dynamic/decode
44
import gleam/float
55
import gleam/int
@@ -903,3 +903,27 @@ pub fn optionally_at_no_path_error_test() {
903903
|> should.be_ok
904904
|> should.equal(100)
905905
}
906+
907+
@external(erlang, "maps", "from_list")
908+
@external(javascript, "../../gleam_stdlib_test_ffi.mjs", "object")
909+
fn make_object(items: List(#(String, t))) -> Dynamic
910+
911+
@external(erlang, "maps", "from_list")
912+
@external(javascript, "../../gleam_stdlib_test_ffi.mjs", "map")
913+
fn make_map(items: List(#(String, t))) -> Dynamic
914+
915+
pub fn js_object_test() {
916+
[#("a", 10), #("b", 20), #("c", 30)]
917+
|> make_object
918+
|> decode.run(decode.dict(decode.string, decode.int))
919+
|> should.be_ok
920+
|> should.equal(dict.from_list([#("a", 10), #("b", 20), #("c", 30)]))
921+
}
922+
923+
pub fn js_map_test() {
924+
[#("a", 10), #("b", 20), #("c", 30)]
925+
|> make_map
926+
|> decode.run(decode.dict(decode.string, decode.int))
927+
|> should.be_ok
928+
|> should.equal(dict.from_list([#("a", 10), #("b", 20), #("c", 30)]))
929+
}

test/gleam_stdlib_test_ffi.mjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,18 @@ export function uint8array(list) {
1010
export function get_null() {
1111
return null;
1212
}
13+
14+
export function object(items) {
15+
const object = {};
16+
for (const [k, v] of items) {
17+
object[k] = v;
18+
}
19+
return object;
20+
}
21+
export function map(items) {
22+
const object = new Map();
23+
for (const [k, v] of items) {
24+
object.set(k, v);
25+
}
26+
return object;
27+
}

0 commit comments

Comments
 (0)