Skip to content

Commit 2554e2a

Browse files
authored
Merge pull request #4443 from BuckleScript/tweak
provide a generic serializer
2 parents 6f29ca8 + bd6789d commit 2554e2a

11 files changed

+502
-245
lines changed

jscomp/main/builtin_cmi_datasets.ml

+3-3
Large diffs are not rendered by default.

jscomp/main/builtin_cmj_datasets.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(* 2c3c6335ffa623676e66eba29ac46b90 *)
1+
(* 6b7a15eb37c6d562fecdc27a2b979270 *)
22
let module_names : string array = Obj.magic (
33
"Gc" (* 220 *),
44
"Js" (* 23 *),
@@ -42,7 +42,7 @@ let module_names : string array = Obj.magic (
4242
"Js_cast" (* 23 *),
4343
"Js_date" (* 23 *),
4444
"Js_dict" (* 137 *),
45-
"Js_json" (* 181 *),
45+
"Js_json" (* 228 *),
4646
"Js_list" (* 612 *),
4747
"Js_math" (* 295 *),
4848
"Js_null" (* 181 *),
@@ -177,7 +177,7 @@ let module_data : string array = Obj.magic (
177177
(* Js_cast *)"\132\149\166\190\000\000\000\003\000\000\000\001\000\000\000\003\000\000\000\003\160\128A",
178178
(* Js_date *)"\132\149\166\190\000\000\000\003\000\000\000\001\000\000\000\003\000\000\000\003\160\128A",
179179
(* Js_dict *)"\132\149\166\190\000\000\000u\000\000\000%\000\000\000v\000\000\000p\160\240\176#get\144\160\160B@@@\176#map\144\160\160B@@@\176&values\144\160\160A@@@\176'entries\144\160\160A@@@\176(fromList\144\160\160A@@@\176)fromArray\144\160\160A@@@\176/unsafeDeleteKey\144\160\160B@@@A",
180-
(* Js_json *)"\132\149\166\190\000\000\000\161\000\000\000*\000\000\000\143\000\000\000\131\160\b\000\000 \000\176$test\144\160\160B@@@\176(classify\144\160\160A@@@\176*decodeNull\144\160\160A@@@\176+decodeArray\144\160\160A@@@\176,decodeNumber\144\160\160A@@@\176,decodeObject\144\160\160A@@@\176,decodeString\144\160\160A@@@\176-decodeBoolean\144\160\160A@@@A",
180+
(* Js_json *)"\132\149\166\190\000\000\000\208\000\000\0004\000\000\000\180\000\000\000\164\160\b\000\000(\000\176$test\144\160\160B@@@\176(classify\144\160\160A@@@\176*decodeNull\144\160\160A@@@\176+decodeArray\144\160\160A@@@\176,decodeNumber\144\160\160A@@@\176,decodeObject\144\160\160A@@@\176,decodeString\144\160\160A@@@\176,serializeExn\144\160\160A@@@\176-decodeBoolean\144\160\160A@@@\1761deserializeUnsafe\144\160\160A@@@A",
181181
(* Js_list *)"\132\149\166\190\000\000\002P\000\000\000\189\000\000\002]\000\000\002F\160\b\000\000T\000\176\"hd\144\160\160A@@@\176\"tl\144\160\160A@@@\176#map\144\160\160B@@@\176#nth\144\160\160B@@@\176#rev\144\160\160A@@@\176$cons\144\160\160B@@\144\180B\160\176\001\003\242!x@\160\176\001\003\243\"xs@@\151\176\176@\166\"::A@\160\144\004\012\160\144\004\011@\176\1921others/js_list.mld\001\005\190\001\005\207\192\004\002d\001\005\190\001\005\214@\176$init\144\160\160B@@\144\180B\160\176\001\004\200!n@\160\176\001\004\201!f@@\147\192\151\176\161G\146&toList\160\145\176@)Js_vectorA@\176\192&_none_A@\000\255\004\002A\160\147\192\151\176\161L\146$init\160\145\176@)Js_vectorA@\004\015\160\144\004!\160\144\004 @\176\192\004/\001\000\152\001\014>\001\014Q\192\0040\001\000\152\001\014>\001\014f@A@\176\192\0042\001\000\152\001\014>\001\014@\004\003@A\176$iter\144\160\160B@@@\176%equal\144\160\160C@@@\176%iteri\144\160\160B@@@\176&filter\144\160\160B@@@\176&length\144\160\160A@@@\176&mapRev\144\160\160B@@@\176'countBy\144\160\160B@@@\176'flatten\144\160\160A@@@\176'isEmpty\144\160\160A@@\144\180A\160\176\001\003\245!x@@\151\176\153@\160\144\004\007\160\146\168@\176\"[]AA@\176\192\004pf\001\005\216\001\005\233\192\004qf\001\005\216\001\005\239@\176(foldLeft\144\160\160C@@@\176(toVector\144\160\160A@@@\176)filterMap\144\160\160B@@@\176)foldRight\144\160\160C@@@\176)revAppend\144\160\160B@@@A",
182182
(* Js_math *)"\132\149\166\190\000\000\001\019\000\000\000H\000\000\000\246\000\000\000\229\160\240\176$ceil\144\160\160A@@@\176%floor\144\160\160A@@@\176(ceil_int\144\004\n@\176)floor_int\144\004\b@\176*random_int\144\160\160B@@@\176+unsafe_ceil\144\160\160A@@\144\180A\160\176\001\004y$prim@@\151\176\181$ceil\160\160AA@\196$ceil@@\160$Math@\160\144\004\014@\176\1921others/js_math.ml\000S\001\rr\001\r\132\192\004\002\000S\001\rr\001\r\147@\176,unsafe_floor\144\160\160A@@\144\180A\160\176\001\004x\004\026@@\151\176\181%floor\160\004\025@\196%floor@@\160$Math@\160\144\004\012@\176\192\004\024\000s\001\018u\001\018\136\192\004\025\000s\001\018u\001\018\152@A",
183183
(* Js_null *)"\132\149\166\190\000\000\000\161\000\000\000/\000\000\000\153\000\000\000\144\160\224\176$bind\144\160\160B@@@\176$iter\144\160\160B@@@\176$test\144\160\160A@@\144\180A\160\176\001\004A!x@@\151\176\148*caml_equal\160\144\004\b\160\146@@\176\1921others/js_null.mla\001\006\020\001\0067\192\004\002a\001\006\020\001\006B@\176&getExn\144\160\160A@@@\176(from_opt\144\160\160A@@@\176*fromOption\144\004\005@A",

jscomp/others/js_json.ml

+64
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,67 @@ external stringify: t -> string = "stringify"
129129
[@@bs.val] [@@bs.scope "JSON"]
130130
external stringifyWithSpace: t -> (_ [@bs.as {json|null|json}]) -> int -> string = "stringify"
131131
[@@bs.val] [@@bs.scope "JSON"]
132+
133+
134+
(* in memory modification does not work until your root is
135+
actually None, so we need wrap it as `[v]` and
136+
return the first element instead *)
137+
138+
let patch : _ -> _ = [%raw{|function (json) {
139+
var x = [json];
140+
var q = [{ kind: 0, i: 0, parent: x }];
141+
while (q.length !== 0) {
142+
// begin pop the stack
143+
var cur = q[q.length - 1];
144+
if (cur.kind === 0) {
145+
cur.val = cur.parent[cur.i]; // patch the undefined value for array
146+
if (++cur.i === cur.parent.length) {
147+
q.pop();
148+
}
149+
} else {
150+
q.pop();
151+
}
152+
// finish
153+
var task = cur.val;
154+
if (typeof task === "object") {
155+
if (Array.isArray(task) && task.length !== 0) {
156+
q.push({ kind: 0, i: 0, parent: task, val: undefined });
157+
} else {
158+
for (var k in task) {
159+
if (k === "RE_PRIVATE_NONE") {
160+
if (cur.kind === 0) {
161+
cur.parent[cur.i - 1] = undefined;
162+
} else {
163+
cur.parent[cur.i] = undefined;
164+
}
165+
continue;
166+
}
167+
q.push({ kind: 1, i: k, parent: task, val: task[k] });
168+
}
169+
}
170+
}
171+
}
172+
return x[0];
173+
}
174+
|}]
175+
176+
177+
let serializeExn (type t) (x : t) : string = [%raw{| function(obj){
178+
var output= JSON.stringify(obj,function(_,value){
179+
if(value===undefined){
180+
return {RE_PRIVATE_NONE : true}
181+
}
182+
return value
183+
});
184+
185+
if(output === undefined){
186+
// JSON.stringify will raise TypeError when it detects cylic objects
187+
throw new TypeError("output is undefined")
188+
}
189+
return output
190+
}
191+
|}] x
192+
193+
let deserializeUnsafe (s: string) : 'a =
194+
patch (parseExn s)
195+

jscomp/others/js_json.mli

+17
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,21 @@ Js.log \@\@ Js.Json.stringifyAny [| "foo"; "bar" |]
236236
*)
237237

238238

239+
(** Best-effort serialization, it tries to seralize as
240+
many objects as possible and deserialize it back*)
239241

242+
(**
243+
It is unsafe in two aspects
244+
- It may throw during parsing
245+
- when you cast it to a specific type, it may have a type mismatch
246+
*)
247+
val deserializeUnsafe : string -> 'a
248+
249+
250+
(**
251+
It will raise in such situations:
252+
- The object can not be serlialized to a JSON
253+
- There are cycles
254+
- Some JS engines can not stringify deeply nested json objects
255+
*)
256+
val serializeExn : 'a -> string

0 commit comments

Comments
 (0)