Skip to content

Commit 0a95869

Browse files
committed
Improve Caml_obj equal function to support errors
1 parent 6077950 commit 0a95869

File tree

8 files changed

+189
-243
lines changed

8 files changed

+189
-243
lines changed

jscomp/core/js_exp_make.ml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,6 @@ let eight_int_literal : t =
309309
let nine_int_literal : t =
310310
{ expression_desc = Number (Int { i = 9l; c = None }); comment = None }
311311

312-
let obj_int_tag_literal : t =
313-
{ expression_desc = Number (Int { i = 248l; c = None }); comment = None }
314-
315312
let int ?comment ?c i : t = { expression_desc = Number (Int { i; c }); comment }
316313

317314
let bigint ?comment sign i : t = { expression_desc = Number (BigInt {positive=sign; value=i}); comment}
@@ -330,7 +327,6 @@ let small_int i : t =
330327
| 7 -> seven_int_literal
331328
| 8 -> eight_int_literal
332329
| 9 -> nine_int_literal
333-
| 248 -> obj_int_tag_literal
334330
| i -> int (Int32.of_int i)
335331

336332
let true_ : t = { comment = None; expression_desc = Bool true }

jscomp/core/js_exp_make.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ val zero_int_literal : t
122122

123123
(* val one_int_literal : t *)
124124
val zero_float_lit : t
125-
(* val obj_int_tag_literal : t *)
126125

127126
val zero_bigint_literal : t
128127

jscomp/runtime/caml_hash.res

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,18 @@ let hash = (count: int, _limit, seed: int, obj: Obj.t): int => {
117117
if size != 0 {
118118
let obj_tag = Obj.tag(obj)
119119
let tag = lor(lsl(size, 10), obj_tag)
120-
if obj_tag == 248 /* Obj.object_tag */ {
121-
s.contents = hash_mix_int(s.contents, (Obj.obj(Obj.field(obj, 1)): int))
122-
} else {
123-
s.contents = hash_mix_int(s.contents, tag)
124-
let block = {
125-
let v = size - 1
126-
if v < num.contents {
127-
v
128-
} else {
129-
num.contents
130-
}
131-
}
132-
for i in 0 to block {
133-
push_back(queue, Obj.field(obj, i))
120+
s.contents = hash_mix_int(s.contents, tag)
121+
let block = {
122+
let v = size - 1
123+
if v < num.contents {
124+
v
125+
} else {
126+
num.contents
134127
}
135128
}
129+
for i in 0 to block {
130+
push_back(queue, Obj.field(obj, i))
131+
}
136132
} else {
137133
let size: int = %raw(`function(obj,cb){
138134
var size = 0

jscomp/runtime/caml_obj.res

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,7 @@ let rec compare = (a: Obj.t, b: Obj.t): int =>
198198
} else {
199199
let tag_a = Obj.tag(a)
200200
let tag_b = Obj.tag(b)
201-
if tag_a == 248 /* object/exception */ {
202-
Pervasives.compare((Obj.magic(Obj.field(a, 1)): int), Obj.magic(Obj.field(b, 1)))
203-
} else if tag_a == 251 /* abstract_tag */ {
204-
raise(Invalid_argument("equal: abstract value"))
205-
} else if tag_a != tag_b {
201+
if tag_a != tag_b {
206202
if tag_a < tag_b {
207203
-1
208204
} else {
@@ -303,53 +299,46 @@ type eq = (Obj.t, Obj.t) => bool
303299
basic type is not the same, it will not equal
304300
*/
305301
let rec equal = (a: Obj.t, b: Obj.t): bool =>
306-
/* front and formoest, we do not compare function values */
307302
if a === b {
308303
true
309304
} else {
310305
let a_type = Js.typeof(a)
311-
if (
312-
a_type == "string" ||
313-
(a_type == "number" ||
314-
(a_type == "bigint" ||
315-
(a_type == "boolean" ||
316-
(a_type == "undefined" || a === %raw(`null`)))))
317-
) {
306+
if a_type !== "object" || a === %raw(`null`) {
318307
false
319308
} else {
320309
let b_type = Js.typeof(b)
321-
if a_type == "function" || b_type == "function" {
322-
raise(Invalid_argument("equal: functional value"))
323-
} /* first, check using reference equality */
324-
else if (
325-
/* a_type = "object" || "symbol" */
326-
b_type == "number" || (b_type == "bigint" || (b_type == "undefined" || b === %raw(`null`)))
327-
) {
310+
if b_type !== "object" || b === %raw(`null`) {
328311
false
329312
} else {
330313
/* [a] [b] could not be null, so it can not raise */
331314
let tag_a = Obj.tag(a)
332315
let tag_b = Obj.tag(b)
333-
if tag_a == 248 /* object/exception */ {
334-
Obj.magic(Obj.field(a, 1)) === Obj.magic(Obj.field(b, 1))
335-
} else if tag_a == 251 /* abstract_tag */ {
336-
raise(Invalid_argument("equal: abstract value"))
337-
} else if tag_a != tag_b {
316+
if tag_a !== tag_b {
338317
false
339-
} else {
318+
} else if O.isArray(a) {
340319
let len_a = Obj.size(a)
341320
let len_b = Obj.size(b)
342-
if len_a == len_b {
343-
if O.isArray(a) {
344-
aux_equal_length((Obj.magic(a): array<Obj.t>), (Obj.magic(b): array<Obj.t>), 0, len_a)
345-
} else if %raw(`a instanceof Date && b instanceof Date`) {
346-
!(Js.unsafe_gt(a, b) || Js.unsafe_lt(a, b))
347-
} else {
348-
aux_obj_equal(a, b)
349-
}
321+
if len_a !== len_b {
322+
false
323+
} else {
324+
aux_equal_length((Obj.magic(a): array<Obj.t>), (Obj.magic(b): array<Obj.t>), 0, len_a)
325+
}
326+
} else if %raw(`a instanceof Error`) {
327+
let a: {..} = Obj.magic(a)
328+
let b: {..} = Obj.magic(b)
329+
if %raw(`b instanceof Error`) && a["message"] === b["message"] {
330+
equal(a["clause"], b["clause"])
350331
} else {
351332
false
352333
}
334+
} else if %raw(`a instanceof Date`) {
335+
if %raw(`b instanceof Date`) {
336+
!(Js.unsafe_gt(a, b) || Js.unsafe_lt(a, b))
337+
} else {
338+
false
339+
}
340+
} else {
341+
aux_obj_equal(a, b)
353342
}
354343
}
355344
}

lib/es6/caml_hash.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,11 @@ function hash(count, _limit, seed, obj) {
6666
if (size !== 0) {
6767
let obj_tag = obj$1.TAG;
6868
let tag = (size << 10) | obj_tag;
69-
if (obj_tag === 248) {
70-
s = Caml_hash_primitive.hash_mix_int(s, obj$1[1]);
71-
} else {
72-
s = Caml_hash_primitive.hash_mix_int(s, tag);
73-
let v = size - 1 | 0;
74-
let block = v < num ? v : num;
75-
for (let i = 0; i <= block; ++i) {
76-
push_back(queue, obj$1[i]);
77-
}
69+
s = Caml_hash_primitive.hash_mix_int(s, tag);
70+
let v = size - 1 | 0;
71+
let block = v < num ? v : num;
72+
for (let i = 0; i <= block; ++i) {
73+
push_back(queue, obj$1[i]);
7874
}
7975
} else {
8076
let size$1 = (function(obj,cb){

lib/es6/caml_obj.js

Lines changed: 73 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,6 @@ function compare(a, b) {
132132
}
133133
let tag_a = a.TAG;
134134
let tag_b = b.TAG;
135-
if (tag_a === 248) {
136-
return Caml.int_compare(a[1], b[1]);
137-
}
138-
if (tag_a === 251) {
139-
throw new Error("Invalid_argument", {
140-
cause: {
141-
RE_EXN_ID: "Invalid_argument",
142-
_1: "equal: abstract value"
143-
}
144-
});
145-
}
146135
if (tag_a !== tag_b) {
147136
if (tag_a < tag_b) {
148137
return -1;
@@ -256,87 +245,85 @@ function aux_obj_compare(a, b) {
256245
}
257246
}
258247

259-
function equal(a, b) {
260-
if (a === b) {
261-
return true;
262-
}
263-
let a_type = typeof a;
264-
if (a_type === "string" || a_type === "number" || a_type === "bigint" || a_type === "boolean" || a_type === "undefined" || a === null) {
265-
return false;
266-
}
267-
let b_type = typeof b;
268-
if (a_type === "function" || b_type === "function") {
269-
throw new Error("Invalid_argument", {
270-
cause: {
271-
RE_EXN_ID: "Invalid_argument",
272-
_1: "equal: functional value"
273-
}
274-
});
275-
}
276-
if (b_type === "number" || b_type === "bigint" || b_type === "undefined" || b === null) {
277-
return false;
278-
}
279-
let tag_a = a.TAG;
280-
let tag_b = b.TAG;
281-
if (tag_a === 248) {
282-
return a[1] === b[1];
283-
}
284-
if (tag_a === 251) {
285-
throw new Error("Invalid_argument", {
286-
cause: {
287-
RE_EXN_ID: "Invalid_argument",
288-
_1: "equal: abstract value"
289-
}
290-
});
291-
}
292-
if (tag_a !== tag_b) {
293-
return false;
294-
}
295-
let len_a = a.length | 0;
296-
let len_b = b.length | 0;
297-
if (len_a === len_b) {
248+
function equal(_a, _b) {
249+
while (true) {
250+
let b = _b;
251+
let a = _a;
252+
if (a === b) {
253+
return true;
254+
}
255+
let a_type = typeof a;
256+
if (a_type !== "object" || a === null) {
257+
return false;
258+
}
259+
let b_type = typeof b;
260+
if (b_type !== "object" || b === null) {
261+
return false;
262+
}
263+
let tag_a = a.TAG;
264+
let tag_b = b.TAG;
265+
if (tag_a !== tag_b) {
266+
return false;
267+
}
298268
if (Array.isArray(a)) {
299-
let _i = 0;
300-
while (true) {
301-
let i = _i;
302-
if (i === len_a) {
303-
return true;
304-
}
305-
if (!equal(a[i], b[i])) {
269+
let len_a = a.length | 0;
270+
let len_b = b.length | 0;
271+
if (len_a !== len_b) {
272+
return false;
273+
} else {
274+
let _i = 0;
275+
while (true) {
276+
let i = _i;
277+
if (i === len_a) {
278+
return true;
279+
}
280+
if (!equal(a[i], b[i])) {
281+
return false;
282+
}
283+
_i = i + 1 | 0;
284+
continue;
285+
};
286+
}
287+
}
288+
if (!(a instanceof Error)) {
289+
if ((a instanceof Date)) {
290+
if ((b instanceof Date)) {
291+
return !(a > b || a < b);
292+
} else {
306293
return false;
307294
}
308-
_i = i + 1 | 0;
309-
continue;
310-
};
311-
} else if ((a instanceof Date && b instanceof Date)) {
312-
return !(a > b || a < b);
313-
} else {
314-
let result = {
315-
contents: true
316-
};
317-
let do_key_a = function (key) {
318-
if (!Object.prototype.hasOwnProperty.call(b, key)) {
319-
result.contents = false;
320-
return;
321-
}
322-
323-
};
324-
let do_key_b = function (key) {
325-
if (!Object.prototype.hasOwnProperty.call(a, key) || !equal(b[key], a[key])) {
326-
result.contents = false;
327-
return;
295+
} else {
296+
let result = {
297+
contents: true
298+
};
299+
let do_key_a = function (key) {
300+
if (!Object.prototype.hasOwnProperty.call(b, key)) {
301+
result.contents = false;
302+
return;
303+
}
304+
305+
};
306+
let do_key_b = function (key) {
307+
if (!Object.prototype.hasOwnProperty.call(a, key) || !equal(b[key], a[key])) {
308+
result.contents = false;
309+
return;
310+
}
311+
312+
};
313+
for_in(a, do_key_a);
314+
if (result.contents) {
315+
for_in(b, do_key_b);
328316
}
329-
330-
};
331-
for_in(a, do_key_a);
332-
if (result.contents) {
333-
for_in(b, do_key_b);
317+
return result.contents;
334318
}
335-
return result.contents;
336319
}
337-
} else {
338-
return false;
339-
}
320+
if (!((b instanceof Error) && a.message === b.message)) {
321+
return false;
322+
}
323+
_b = b.clause;
324+
_a = a.clause;
325+
continue;
326+
};
340327
}
341328

342329
function equal_null(x, y) {

lib/js/caml_hash.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,11 @@ function hash(count, _limit, seed, obj) {
6666
if (size !== 0) {
6767
let obj_tag = obj$1.TAG;
6868
let tag = (size << 10) | obj_tag;
69-
if (obj_tag === 248) {
70-
s = Caml_hash_primitive.hash_mix_int(s, obj$1[1]);
71-
} else {
72-
s = Caml_hash_primitive.hash_mix_int(s, tag);
73-
let v = size - 1 | 0;
74-
let block = v < num ? v : num;
75-
for (let i = 0; i <= block; ++i) {
76-
push_back(queue, obj$1[i]);
77-
}
69+
s = Caml_hash_primitive.hash_mix_int(s, tag);
70+
let v = size - 1 | 0;
71+
let block = v < num ? v : num;
72+
for (let i = 0; i <= block; ++i) {
73+
push_back(queue, obj$1[i]);
7874
}
7975
} else {
8076
let size$1 = (function(obj,cb){

0 commit comments

Comments
 (0)