diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d9f3a65c1..f3a352bbf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ # 12.0.0-alpha.2 (Unreleased) +#### :rocket: New Feature + +- Updated `==` to improve performance and start supporting comparison of `Error` instances. Also, it stopped raising error on comparison of two different functions. https://github.com/rescript-lang/rescript-compiler/pull/6937 + #### :nail_care: Polish - Improve formatting in the generated js code. https://github.com/rescript-lang/rescript-compiler/pull/6932 diff --git a/jscomp/core/js_exp_make.ml b/jscomp/core/js_exp_make.ml index 229a99337b..c51729144b 100644 --- a/jscomp/core/js_exp_make.ml +++ b/jscomp/core/js_exp_make.ml @@ -309,9 +309,6 @@ let eight_int_literal : t = let nine_int_literal : t = { expression_desc = Number (Int { i = 9l; c = None }); comment = None } -let obj_int_tag_literal : t = - { expression_desc = Number (Int { i = 248l; c = None }); comment = None } - let int ?comment ?c i : t = { expression_desc = Number (Int { i; c }); comment } let bigint ?comment sign i : t = { expression_desc = Number (BigInt {positive=sign; value=i}); comment} @@ -330,7 +327,6 @@ let small_int i : t = | 7 -> seven_int_literal | 8 -> eight_int_literal | 9 -> nine_int_literal - | 248 -> obj_int_tag_literal | i -> int (Int32.of_int i) let true_ : t = { comment = None; expression_desc = Bool true } diff --git a/jscomp/core/js_exp_make.mli b/jscomp/core/js_exp_make.mli index 63b50a916d..22c0ed63d4 100644 --- a/jscomp/core/js_exp_make.mli +++ b/jscomp/core/js_exp_make.mli @@ -122,7 +122,6 @@ val zero_int_literal : t (* val one_int_literal : t *) val zero_float_lit : t -(* val obj_int_tag_literal : t *) val zero_bigint_literal : t diff --git a/jscomp/runtime/caml_hash.res b/jscomp/runtime/caml_hash.res index b33bedb049..edf0575e2a 100644 --- a/jscomp/runtime/caml_hash.res +++ b/jscomp/runtime/caml_hash.res @@ -117,22 +117,18 @@ let hash = (count: int, _limit, seed: int, obj: Obj.t): int => { if size != 0 { let obj_tag = Obj.tag(obj) let tag = lor(lsl(size, 10), obj_tag) - if obj_tag == 248 /* Obj.object_tag */ { - s.contents = hash_mix_int(s.contents, (Obj.obj(Obj.field(obj, 1)): int)) - } else { - s.contents = hash_mix_int(s.contents, tag) - let block = { - let v = size - 1 - if v < num.contents { - v - } else { - num.contents - } - } - for i in 0 to block { - push_back(queue, Obj.field(obj, i)) + s.contents = hash_mix_int(s.contents, tag) + let block = { + let v = size - 1 + if v < num.contents { + v + } else { + num.contents } } + for i in 0 to block { + push_back(queue, Obj.field(obj, i)) + } } else { let size: int = %raw(`function(obj,cb){ var size = 0 diff --git a/jscomp/runtime/caml_obj.res b/jscomp/runtime/caml_obj.res index f9fcff04f0..438e880a51 100644 --- a/jscomp/runtime/caml_obj.res +++ b/jscomp/runtime/caml_obj.res @@ -198,11 +198,7 @@ let rec compare = (a: Obj.t, b: Obj.t): int => } else { let tag_a = Obj.tag(a) let tag_b = Obj.tag(b) - if tag_a == 248 /* object/exception */ { - Pervasives.compare((Obj.magic(Obj.field(a, 1)): int), Obj.magic(Obj.field(b, 1))) - } else if tag_a == 251 /* abstract_tag */ { - raise(Invalid_argument("equal: abstract value")) - } else if tag_a != tag_b { + if tag_a != tag_b { if tag_a < tag_b { -1 } else { @@ -303,53 +299,46 @@ type eq = (Obj.t, Obj.t) => bool basic type is not the same, it will not equal */ let rec equal = (a: Obj.t, b: Obj.t): bool => - /* front and formoest, we do not compare function values */ if a === b { true } else { let a_type = Js.typeof(a) - if ( - a_type == "string" || - (a_type == "number" || - (a_type == "bigint" || - (a_type == "boolean" || - (a_type == "undefined" || a === %raw(`null`))))) - ) { + if a_type !== "object" || a === %raw(`null`) { false } else { let b_type = Js.typeof(b) - if a_type == "function" || b_type == "function" { - raise(Invalid_argument("equal: functional value")) - } /* first, check using reference equality */ - else if ( - /* a_type = "object" || "symbol" */ - b_type == "number" || (b_type == "bigint" || (b_type == "undefined" || b === %raw(`null`))) - ) { + if b_type !== "object" || b === %raw(`null`) { false } else { /* [a] [b] could not be null, so it can not raise */ let tag_a = Obj.tag(a) let tag_b = Obj.tag(b) - if tag_a == 248 /* object/exception */ { - Obj.magic(Obj.field(a, 1)) === Obj.magic(Obj.field(b, 1)) - } else if tag_a == 251 /* abstract_tag */ { - raise(Invalid_argument("equal: abstract value")) - } else if tag_a != tag_b { + if tag_a !== tag_b { false - } else { + } else if O.isArray(a) { let len_a = Obj.size(a) let len_b = Obj.size(b) - if len_a == len_b { - if O.isArray(a) { - aux_equal_length((Obj.magic(a): array), (Obj.magic(b): array), 0, len_a) - } else if %raw(`a instanceof Date && b instanceof Date`) { - !(Js.unsafe_gt(a, b) || Js.unsafe_lt(a, b)) - } else { - aux_obj_equal(a, b) - } + if len_a !== len_b { + false + } else { + aux_equal_length((Obj.magic(a): array), (Obj.magic(b): array), 0, len_a) + } + } else if %raw(`a instanceof Error`) { + let a: {..} = Obj.magic(a) + let b: {..} = Obj.magic(b) + if %raw(`b instanceof Error`) && a["message"] === b["message"] { + equal(a["cause"], b["cause"]) } else { false } + } else if %raw(`a instanceof Date`) { + if %raw(`b instanceof Date`) { + !(Js.unsafe_gt(a, b) || Js.unsafe_lt(a, b)) + } else { + false + } + } else { + aux_obj_equal(a, b) } } } diff --git a/jscomp/test/caml_compare_test.js b/jscomp/test/caml_compare_test.js index 2df1c2ab5b..10eaeb67fd 100644 --- a/jscomp/test/caml_compare_test.js +++ b/jscomp/test/caml_compare_test.js @@ -3,25 +3,19 @@ let Mt = require("./mt.js"); let Caml_obj = require("../../lib/js/caml_obj.js"); -let Caml_js_exceptions = require("../../lib/js/caml_js_exceptions.js"); -let function_equal_test; +function fn1(x) { + return x + 1 | 0; +} -try { - function_equal_test = Caml_obj.equal((function (x) { - return x + 1 | 0; - }), (function (x) { - return x + 2 | 0; - })); -} catch (raw_exn) { - let exn = Caml_js_exceptions.internalToOCamlException(raw_exn); - function_equal_test = exn.RE_EXN_ID === "Invalid_argument" && exn._1 === "equal: functional value" ? true : false; +function fn2(x) { + return x + 2 | 0; } let suites = { contents: { hd: [ - "File \"caml_compare_test.res\", line 12, characters 5-12", + "File \"caml_compare_test.res\", line 10, characters 5-12", (function () { return { TAG: "Eq", @@ -43,7 +37,7 @@ let suites = { ], tl: { hd: [ - "File \"caml_compare_test.res\", line 14, characters 5-12", + "File \"caml_compare_test.res\", line 12, characters 5-12", (function () { return { TAG: "Eq", @@ -198,181 +192,101 @@ let suites = { return { TAG: "Eq", _0: true, - _1: function_equal_test + _1: Caml_obj.equal(fn1, fn1) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 20, characters 5-12", + "function2", (function () { return { TAG: "Eq", - _0: true, - _1: Caml_obj.lessthan(undefined, 1) + _0: false, + _1: Caml_obj.equal(fn1, fn2) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 21, characters 5-12", + "exn", (function () { return { TAG: "Eq", _0: true, - _1: Caml_obj.lessthan(undefined, [ - 1, - 30 - ]) + _1: Caml_obj.equal({ + RE_EXN_ID: "Not_found" + }, { + RE_EXN_ID: "Not_found" + }) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 22, characters 5-12", + "File \"caml_compare_test.res\", line 20, characters 5-12", (function () { return { TAG: "Eq", _0: true, - _1: Caml_obj.greaterthan([ - 1, - 30 - ], undefined) + _1: Caml_obj.lessthan(undefined, 1) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 24, characters 6-13", + "File \"caml_compare_test.res\", line 21, characters 5-12", (function () { return { TAG: "Eq", _0: true, - _1: Caml_obj.lessthan({ - hd: 2, - tl: { - hd: 6, - tl: { - hd: 1, - tl: { - hd: 1, - tl: { - hd: 2, - tl: { - hd: 1, - tl: { - hd: 4, - tl: { - hd: 2, - tl: { - hd: 1, - tl: /* [] */0 - } - } - } - } - } - } - } - } - }, { - hd: 2, - tl: { - hd: 6, - tl: { - hd: 1, - tl: { - hd: 1, - tl: { - hd: 2, - tl: { - hd: 1, - tl: { - hd: 4, - tl: { - hd: 2, - tl: { - hd: 1, - tl: { - hd: 409, - tl: /* [] */0 - } - } - } - } - } - } - } - } - } - }) + _1: Caml_obj.lessthan(undefined, [ + 1, + 30 + ]) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 27, characters 5-12", + "File \"caml_compare_test.res\", line 22, characters 5-12", (function () { return { TAG: "Eq", _0: true, - _1: Caml_obj.lessthan({ - hd: 1, - tl: /* [] */0 - }, { - hd: 1, - tl: { - hd: 409, - tl: /* [] */0 - } - }) + _1: Caml_obj.greaterthan([ + 1, + 30 + ], undefined) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 28, characters 5-12", + "File \"caml_compare_test.res\", line 24, characters 6-13", (function () { return { TAG: "Eq", _0: true, - _1: Caml_obj.lessthan(/* [] */0, { - hd: 409, - tl: /* [] */0 - }) - }; - }) - ], - tl: { - hd: [ - "File \"caml_compare_test.res\", line 30, characters 6-13", - (function () { - return { - TAG: "Eq", - _0: true, - _1: Caml_obj.greaterthan({ - hd: 2, + _1: Caml_obj.lessthan({ + hd: 2, + tl: { + hd: 6, tl: { - hd: 6, + hd: 1, tl: { hd: 1, tl: { - hd: 1, + hd: 2, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 4, tl: { - hd: 4, + hd: 2, tl: { - hd: 2, - tl: { - hd: 1, - tl: { - hd: 409, - tl: /* [] */0 - } - } + hd: 1, + tl: /* [] */0 } } } @@ -380,24 +294,27 @@ let suites = { } } } - }, { - hd: 2, + } + }, { + hd: 2, + tl: { + hd: 6, tl: { - hd: 6, + hd: 1, tl: { hd: 1, tl: { - hd: 1, + hd: 2, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 4, tl: { - hd: 4, + hd: 2, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 409, tl: /* [] */0 } } @@ -407,57 +324,72 @@ let suites = { } } } + } + }) + }; + }) + ], + tl: { + hd: [ + "File \"caml_compare_test.res\", line 27, characters 5-12", + (function () { + return { + TAG: "Eq", + _0: true, + _1: Caml_obj.lessthan({ + hd: 1, + tl: /* [] */0 + }, { + hd: 1, + tl: { + hd: 409, + tl: /* [] */0 + } }) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 33, characters 5-12", + "File \"caml_compare_test.res\", line 28, characters 5-12", (function () { return { TAG: "Eq", - _0: false, - _1: false + _0: true, + _1: Caml_obj.lessthan(/* [] */0, { + hd: 409, + tl: /* [] */0 + }) }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 34, characters 5-12", + "File \"caml_compare_test.res\", line 30, characters 6-13", (function () { return { TAG: "Eq", - _0: false, - _1: false - }; - }) - ], - tl: { - hd: [ - "File \"caml_compare_test.res\", line 36, characters 6-13", - (function () { - return { - TAG: "Eq", - _0: false, - _1: Caml_obj.equal({ - hd: 2, + _0: true, + _1: Caml_obj.greaterthan({ + hd: 2, + tl: { + hd: 6, tl: { - hd: 6, + hd: 1, tl: { hd: 1, tl: { - hd: 1, + hd: 2, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 4, tl: { - hd: 4, + hd: 2, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 409, tl: /* [] */0 } } @@ -467,29 +399,26 @@ let suites = { } } } - }, { - hd: 2, + } + }, { + hd: 2, + tl: { + hd: 6, tl: { - hd: 6, + hd: 1, tl: { hd: 1, tl: { - hd: 1, + hd: 2, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 4, tl: { - hd: 4, + hd: 2, tl: { - hd: 2, - tl: { - hd: 1, - tl: { - hd: 409, - tl: /* [] */0 - } - } + hd: 1, + tl: /* [] */0 } } } @@ -497,37 +426,58 @@ let suites = { } } } - }) + } + }) + }; + }) + ], + tl: { + hd: [ + "File \"caml_compare_test.res\", line 33, characters 5-12", + (function () { + return { + TAG: "Eq", + _0: false, + _1: false }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 40, characters 6-13", + "File \"caml_compare_test.res\", line 34, characters 5-12", (function () { return { TAG: "Eq", _0: false, - _1: Caml_obj.equal({ - hd: 2, - tl: { - hd: 6, + _1: false + }; + }) + ], + tl: { + hd: [ + "File \"caml_compare_test.res\", line 36, characters 6-13", + (function () { + return { + TAG: "Eq", + _0: false, + _1: Caml_obj.equal({ + hd: 2, tl: { - hd: 1, + hd: 6, tl: { hd: 1, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 2, tl: { - hd: 4, + hd: 1, tl: { - hd: 2, + hd: 4, tl: { - hd: 1, + hd: 2, tl: { - hd: 409, + hd: 1, tl: /* [] */0 } } @@ -537,26 +487,29 @@ let suites = { } } } - } - }, { - hd: 2, - tl: { - hd: 6, + }, { + hd: 2, tl: { - hd: 1, + hd: 6, tl: { hd: 1, tl: { - hd: 2, + hd: 1, tl: { - hd: 1, + hd: 2, tl: { - hd: 4, + hd: 1, tl: { - hd: 2, + hd: 4, tl: { - hd: 1, - tl: /* [] */0 + hd: 2, + tl: { + hd: 1, + tl: { + hd: 409, + tl: /* [] */0 + } + } } } } @@ -564,169 +517,198 @@ let suites = { } } } - } - }) - }; - }) - ], - tl: { - hd: [ - "cmp_id", - (function () { - return { - TAG: "Eq", - _0: Caml_obj.compare({ - x: 1, - y: 2 - }, { - x: 1, - y: 2 - }), - _1: 0 + }) }; }) ], tl: { hd: [ - "cmp_val", + "File \"caml_compare_test.res\", line 40, characters 6-13", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({ - x: 1 + _0: false, + _1: Caml_obj.equal({ + hd: 2, + tl: { + hd: 6, + tl: { + hd: 1, + tl: { + hd: 1, + tl: { + hd: 2, + tl: { + hd: 1, + tl: { + hd: 4, + tl: { + hd: 2, + tl: { + hd: 1, + tl: { + hd: 409, + tl: /* [] */0 + } + } + } + } + } + } + } + } + } }, { - x: 2 - }), - _1: -1 + hd: 2, + tl: { + hd: 6, + tl: { + hd: 1, + tl: { + hd: 1, + tl: { + hd: 2, + tl: { + hd: 1, + tl: { + hd: 4, + tl: { + hd: 2, + tl: { + hd: 1, + tl: /* [] */0 + } + } + } + } + } + } + } + } + }) }; }) ], tl: { hd: [ - "cmp_val2", + "cmp_id", (function () { return { TAG: "Eq", _0: Caml_obj.compare({ - x: 2 + x: 1, + y: 2 }, { - x: 1 + x: 1, + y: 2 }), - _1: 1 + _1: 0 }; }) ], tl: { hd: [ - "cmp_empty", + "cmp_val", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({}, {}), - _1: 0 + _0: Caml_obj.compare({ + x: 1 + }, { + x: 2 + }), + _1: -1 }; }) ], tl: { hd: [ - "cmp_empty2", + "cmp_val2", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({}, {x:1}), - _1: -1 + _0: Caml_obj.compare({ + x: 2 + }, { + x: 1 + }), + _1: 1 }; }) ], tl: { hd: [ - "cmp_swap", + "cmp_empty", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({ - x: 1, - y: 2 - }, { - y: 2, - x: 1 - }), + _0: Caml_obj.compare({}, {}), _1: 0 }; }) ], tl: { hd: [ - "cmp_size", + "cmp_empty2", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({x:1}, {x:1, y:2}), + _0: Caml_obj.compare({}, {x:1}), _1: -1 }; }) ], tl: { hd: [ - "cmp_size2", + "cmp_swap", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({x:1, y:2}, {x:1}), - _1: 1 + _0: Caml_obj.compare({ + x: 1, + y: 2 + }, { + y: 2, + x: 1 + }), + _1: 0 }; }) ], tl: { hd: [ - "cmp_order", + "cmp_size", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({ - x: 0, - y: 1 - }, { - x: 1, - y: 0 - }), + _0: Caml_obj.compare({x:1}, {x:1, y:2}), _1: -1 }; }) ], tl: { hd: [ - "cmp_order2", + "cmp_size2", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({ - x: 1, - y: 0 - }, { - x: 0, - y: 1 - }), + _0: Caml_obj.compare({x:1, y:2}, {x:1}), _1: 1 }; }) ], tl: { hd: [ - "cmp_in_list", + "cmp_order", (function () { return { TAG: "Eq", _0: Caml_obj.compare({ - hd: { - x: 1 - }, - tl: /* [] */0 + x: 0, + y: 1 }, { - hd: { - x: 2 - }, - tl: /* [] */0 + x: 1, + y: 0 }), _1: -1 }; @@ -734,20 +716,16 @@ let suites = { ], tl: { hd: [ - "cmp_in_list2", + "cmp_order2", (function () { return { TAG: "Eq", _0: Caml_obj.compare({ - hd: { - x: 2 - }, - tl: /* [] */0 + x: 1, + y: 0 }, { - hd: { - x: 1 - }, - tl: /* [] */0 + x: 0, + y: 1 }), _1: 1 }; @@ -755,20 +733,20 @@ let suites = { ], tl: { hd: [ - "cmp_with_list", + "cmp_in_list", (function () { return { TAG: "Eq", _0: Caml_obj.compare({ - x: { - hd: 0, - tl: /* [] */0 - } + hd: { + x: 1 + }, + tl: /* [] */0 }, { - x: { - hd: 1, - tl: /* [] */0 - } + hd: { + x: 2 + }, + tl: /* [] */0 }), _1: -1 }; @@ -776,20 +754,20 @@ let suites = { ], tl: { hd: [ - "cmp_with_list2", + "cmp_in_list2", (function () { return { TAG: "Eq", _0: Caml_obj.compare({ - x: { - hd: 1, - tl: /* [] */0 - } + hd: { + x: 2 + }, + tl: /* [] */0 }, { - x: { - hd: 0, - tl: /* [] */0 - } + hd: { + x: 1 + }, + tl: /* [] */0 }), _1: 1 }; @@ -797,278 +775,322 @@ let suites = { ], tl: { hd: [ - "eq_id", + "cmp_with_list", (function () { return { - TAG: "Ok", - _0: Caml_obj.equal({ - x: 1, - y: 2 + TAG: "Eq", + _0: Caml_obj.compare({ + x: { + hd: 0, + tl: /* [] */0 + } }, { - x: 1, - y: 2 - }) + x: { + hd: 1, + tl: /* [] */0 + } + }), + _1: -1 }; }) ], tl: { hd: [ - "eq_val", + "cmp_with_list2", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({ - x: 1 + _0: Caml_obj.compare({ + x: { + hd: 1, + tl: /* [] */0 + } }, { - x: 2 + x: { + hd: 0, + tl: /* [] */0 + } }), - _1: false + _1: 1 }; }) ], tl: { hd: [ - "eq_val2", + "eq_id", (function () { return { - TAG: "Eq", + TAG: "Ok", _0: Caml_obj.equal({ - x: 2 + x: 1, + y: 2 }, { - x: 1 - }), - _1: false + x: 1, + y: 2 + }) }; }) ], tl: { hd: [ - "eq_empty", + "eq_val", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({}, {}), - _1: true + _0: Caml_obj.equal({ + x: 1 + }, { + x: 2 + }), + _1: false }; }) ], tl: { hd: [ - "eq_empty2", + "eq_val2", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({}, {x:1}), + _0: Caml_obj.equal({ + x: 2 + }, { + x: 1 + }), _1: false }; }) ], tl: { hd: [ - "eq_swap", + "eq_empty", (function () { return { - TAG: "Ok", - _0: Caml_obj.equal({ - x: 1, - y: 2 - }, { - y: 2, - x: 1 - }) + TAG: "Eq", + _0: Caml_obj.equal({}, {}), + _1: true }; }) ], tl: { hd: [ - "eq_size", + "eq_empty2", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({x:1}, {x:1, y:2}), + _0: Caml_obj.equal({}, {x:1}), _1: false }; }) ], tl: { hd: [ - "eq_size2", + "eq_swap", (function () { return { - TAG: "Eq", - _0: Caml_obj.equal({x:1, y:2}, {x:1}), - _1: false + TAG: "Ok", + _0: Caml_obj.equal({ + x: 1, + y: 2 + }, { + y: 2, + x: 1 + }) }; }) ], tl: { hd: [ - "eq_in_list", + "eq_size", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({ - hd: { - x: 1 - }, - tl: /* [] */0 - }, { - hd: { - x: 2 - }, - tl: /* [] */0 - }), + _0: Caml_obj.equal({x:1}, {x:1, y:2}), _1: false }; }) ], tl: { hd: [ - "eq_in_list2", + "eq_size2", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({ - hd: { - x: 2 - }, - tl: /* [] */0 - }, { - hd: { - x: 2 - }, - tl: /* [] */0 - }), - _1: true + _0: Caml_obj.equal({x:1, y:2}, {x:1}), + _1: false }; }) ], tl: { hd: [ - "eq_with_list", + "eq_in_list", (function () { return { TAG: "Eq", _0: Caml_obj.equal({ - x: { - hd: 0, - tl: /* [] */0 - } + hd: { + x: 1 + }, + tl: /* [] */0 }, { - x: { - hd: 0, - tl: /* [] */0 - } + hd: { + x: 2 + }, + tl: /* [] */0 }), - _1: true + _1: false }; }) ], tl: { hd: [ - "eq_with_list2", + "eq_in_list2", (function () { return { TAG: "Eq", _0: Caml_obj.equal({ - x: { - hd: 0, - tl: /* [] */0 - } + hd: { + x: 2 + }, + tl: /* [] */0 }, { - x: { - hd: 1, - tl: /* [] */0 - } + hd: { + x: 2 + }, + tl: /* [] */0 }), - _1: false + _1: true }; }) ], tl: { hd: [ - "eq_no_prototype", + "eq_with_list", (function () { return { TAG: "Eq", - _0: Caml_obj.equal({x:1}, ((function(){let o = Object.create(null);o.x = 1;return o;})())), + _0: Caml_obj.equal({ + x: { + hd: 0, + tl: /* [] */0 + } + }, { + x: { + hd: 0, + tl: /* [] */0 + } + }), _1: true }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 76, characters 5-12", + "eq_with_list2", (function () { return { TAG: "Eq", - _0: Caml_obj.compare(null, { - hd: 3, - tl: /* [] */0 + _0: Caml_obj.equal({ + x: { + hd: 0, + tl: /* [] */0 + } + }, { + x: { + hd: 1, + tl: /* [] */0 + } }), - _1: -1 + _1: false }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 77, characters 5-12", + "eq_no_prototype", (function () { return { TAG: "Eq", - _0: Caml_obj.compare({ - hd: 3, - tl: /* [] */0 - }, null), - _1: 1 + _0: Caml_obj.equal({x:1}, ((function(){let o = Object.create(null);o.x = 1;return o;})())), + _1: true }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 78, characters 5-12", + "File \"caml_compare_test.res\", line 76, characters 5-12", (function () { return { TAG: "Eq", - _0: Caml_obj.compare(null, 0), + _0: Caml_obj.compare(null, { + hd: 3, + tl: /* [] */0 + }), _1: -1 }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 79, characters 5-12", + "File \"caml_compare_test.res\", line 77, characters 5-12", (function () { return { TAG: "Eq", - _0: Caml_obj.compare(0, null), + _0: Caml_obj.compare({ + hd: 3, + tl: /* [] */0 + }, null), _1: 1 }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 80, characters 5-12", + "File \"caml_compare_test.res\", line 78, characters 5-12", (function () { return { TAG: "Eq", - _0: Caml_obj.compare(undefined, 0), + _0: Caml_obj.compare(null, 0), _1: -1 }; }) ], tl: { hd: [ - "File \"caml_compare_test.res\", line 81, characters 5-12", + "File \"caml_compare_test.res\", line 79, characters 5-12", (function () { return { TAG: "Eq", - _0: Caml_obj.compare(0, undefined), + _0: Caml_obj.compare(0, null), _1: 1 }; }) ], - tl: /* [] */0 + tl: { + hd: [ + "File \"caml_compare_test.res\", line 80, characters 5-12", + (function () { + return { + TAG: "Eq", + _0: Caml_obj.compare(undefined, 0), + _1: -1 + }; + }) + ], + tl: { + hd: [ + "File \"caml_compare_test.res\", line 81, characters 5-12", + (function () { + return { + TAG: "Eq", + _0: Caml_obj.compare(0, undefined), + _1: 1 + }; + }) + ], + tl: /* [] */0 + } + } } } } @@ -1152,8 +1174,9 @@ eq("File \"caml_compare_test.res\", line 92, characters 3-10", false, Caml_obj.l Mt.from_pair_suites("Caml_compare_test", suites.contents); -exports.function_equal_test = function_equal_test; +exports.fn1 = fn1; +exports.fn2 = fn2; exports.suites = suites; exports.test_id = test_id; exports.eq = eq; -/* function_equal_test Not a pure module */ +/* Not a pure module */ diff --git a/jscomp/test/caml_compare_test.res b/jscomp/test/caml_compare_test.res index 4dc811e82c..49fb3c115d 100644 --- a/jscomp/test/caml_compare_test.res +++ b/jscomp/test/caml_compare_test.res @@ -1,10 +1,8 @@ @@warning("-45") type u = A(int) | B(int, bool) | C(int) -let function_equal_test = try (x => x + 1) == (x => x + 2) catch { -| Invalid_argument("equal: functional value") => true -| _ => false -} +let fn1 = x => x + 1 +let fn2 = x => x + 2 let suites = ref({ open Mt @@ -16,7 +14,9 @@ let suites = ref({ ("listneq", _ => Eq(true, list{1, 2, 3} > list{1, 2, 2})), ("custom_u", _ => Eq(true, (A(3), B(2, false), C(1)) > (A(3), B(2, false), C(0)))), ("custom_u2", _ => Eq(true, (A(3), B(2, false), C(1)) == (A(3), B(2, false), C(1)))), - ("function", _ => Eq(true, function_equal_test)), + ("function", _ => Eq(true, fn1 == fn1)), + ("function2", _ => Eq(false, fn1 == fn2)), + ("exn", _ => Eq(true, Not_found == Not_found)), (__LOC__, _ => Eq(true, None < Some(1))), (__LOC__, _ => Eq(true, None < Some([1, 30]))), (__LOC__, _ => Eq(true, Some([1, 30]) > None)), diff --git a/lib/es6/caml_hash.js b/lib/es6/caml_hash.js index 054d821630..9d9412f65c 100644 --- a/lib/es6/caml_hash.js +++ b/lib/es6/caml_hash.js @@ -66,15 +66,11 @@ function hash(count, _limit, seed, obj) { if (size !== 0) { let obj_tag = obj$1.TAG; let tag = (size << 10) | obj_tag; - if (obj_tag === 248) { - s = Caml_hash_primitive.hash_mix_int(s, obj$1[1]); - } else { - s = Caml_hash_primitive.hash_mix_int(s, tag); - let v = size - 1 | 0; - let block = v < num ? v : num; - for (let i = 0; i <= block; ++i) { - push_back(queue, obj$1[i]); - } + s = Caml_hash_primitive.hash_mix_int(s, tag); + let v = size - 1 | 0; + let block = v < num ? v : num; + for (let i = 0; i <= block; ++i) { + push_back(queue, obj$1[i]); } } else { let size$1 = (function(obj,cb){ diff --git a/lib/es6/caml_obj.js b/lib/es6/caml_obj.js index 8fc4b04320..9b3515d31e 100644 --- a/lib/es6/caml_obj.js +++ b/lib/es6/caml_obj.js @@ -132,17 +132,6 @@ function compare(a, b) { } let tag_a = a.TAG; let tag_b = b.TAG; - if (tag_a === 248) { - return Caml.int_compare(a[1], b[1]); - } - if (tag_a === 251) { - throw new Error("Invalid_argument", { - cause: { - RE_EXN_ID: "Invalid_argument", - _1: "equal: abstract value" - } - }); - } if (tag_a !== tag_b) { if (tag_a < tag_b) { return -1; @@ -256,87 +245,85 @@ function aux_obj_compare(a, b) { } } -function equal(a, b) { - if (a === b) { - return true; - } - let a_type = typeof a; - if (a_type === "string" || a_type === "number" || a_type === "bigint" || a_type === "boolean" || a_type === "undefined" || a === null) { - return false; - } - let b_type = typeof b; - if (a_type === "function" || b_type === "function") { - throw new Error("Invalid_argument", { - cause: { - RE_EXN_ID: "Invalid_argument", - _1: "equal: functional value" - } - }); - } - if (b_type === "number" || b_type === "bigint" || b_type === "undefined" || b === null) { - return false; - } - let tag_a = a.TAG; - let tag_b = b.TAG; - if (tag_a === 248) { - return a[1] === b[1]; - } - if (tag_a === 251) { - throw new Error("Invalid_argument", { - cause: { - RE_EXN_ID: "Invalid_argument", - _1: "equal: abstract value" - } - }); - } - if (tag_a !== tag_b) { - return false; - } - let len_a = a.length | 0; - let len_b = b.length | 0; - if (len_a === len_b) { +function equal(_a, _b) { + while (true) { + let b = _b; + let a = _a; + if (a === b) { + return true; + } + let a_type = typeof a; + if (a_type !== "object" || a === null) { + return false; + } + let b_type = typeof b; + if (b_type !== "object" || b === null) { + return false; + } + let tag_a = a.TAG; + let tag_b = b.TAG; + if (tag_a !== tag_b) { + return false; + } if (Array.isArray(a)) { - let _i = 0; - while (true) { - let i = _i; - if (i === len_a) { - return true; - } - if (!equal(a[i], b[i])) { + let len_a = a.length | 0; + let len_b = b.length | 0; + if (len_a !== len_b) { + return false; + } else { + let _i = 0; + while (true) { + let i = _i; + if (i === len_a) { + return true; + } + if (!equal(a[i], b[i])) { + return false; + } + _i = i + 1 | 0; + continue; + }; + } + } + if (!(a instanceof Error)) { + if ((a instanceof Date)) { + if ((b instanceof Date)) { + return !(a > b || a < b); + } else { return false; } - _i = i + 1 | 0; - continue; - }; - } else if ((a instanceof Date && b instanceof Date)) { - return !(a > b || a < b); - } else { - let result = { - contents: true - }; - let do_key_a = function (key) { - if (!Object.prototype.hasOwnProperty.call(b, key)) { - result.contents = false; - return; - } - - }; - let do_key_b = function (key) { - if (!Object.prototype.hasOwnProperty.call(a, key) || !equal(b[key], a[key])) { - result.contents = false; - return; + } else { + let result = { + contents: true + }; + let do_key_a = function (key) { + if (!Object.prototype.hasOwnProperty.call(b, key)) { + result.contents = false; + return; + } + + }; + let do_key_b = function (key) { + if (!Object.prototype.hasOwnProperty.call(a, key) || !equal(b[key], a[key])) { + result.contents = false; + return; + } + + }; + for_in(a, do_key_a); + if (result.contents) { + for_in(b, do_key_b); } - - }; - for_in(a, do_key_a); - if (result.contents) { - for_in(b, do_key_b); + return result.contents; } - return result.contents; } - } else { - return false; - } + if (!((b instanceof Error) && a.message === b.message)) { + return false; + } + _b = b.cause; + _a = a.cause; + continue; + }; } function equal_null(x, y) { diff --git a/lib/js/caml_hash.js b/lib/js/caml_hash.js index 0fbd07cb73..925d119941 100644 --- a/lib/js/caml_hash.js +++ b/lib/js/caml_hash.js @@ -66,15 +66,11 @@ function hash(count, _limit, seed, obj) { if (size !== 0) { let obj_tag = obj$1.TAG; let tag = (size << 10) | obj_tag; - if (obj_tag === 248) { - s = Caml_hash_primitive.hash_mix_int(s, obj$1[1]); - } else { - s = Caml_hash_primitive.hash_mix_int(s, tag); - let v = size - 1 | 0; - let block = v < num ? v : num; - for (let i = 0; i <= block; ++i) { - push_back(queue, obj$1[i]); - } + s = Caml_hash_primitive.hash_mix_int(s, tag); + let v = size - 1 | 0; + let block = v < num ? v : num; + for (let i = 0; i <= block; ++i) { + push_back(queue, obj$1[i]); } } else { let size$1 = (function(obj,cb){ diff --git a/lib/js/caml_obj.js b/lib/js/caml_obj.js index 65e0d78ebc..b545a4ab99 100644 --- a/lib/js/caml_obj.js +++ b/lib/js/caml_obj.js @@ -132,17 +132,6 @@ function compare(a, b) { } let tag_a = a.TAG; let tag_b = b.TAG; - if (tag_a === 248) { - return Caml.int_compare(a[1], b[1]); - } - if (tag_a === 251) { - throw new Error("Invalid_argument", { - cause: { - RE_EXN_ID: "Invalid_argument", - _1: "equal: abstract value" - } - }); - } if (tag_a !== tag_b) { if (tag_a < tag_b) { return -1; @@ -256,87 +245,85 @@ function aux_obj_compare(a, b) { } } -function equal(a, b) { - if (a === b) { - return true; - } - let a_type = typeof a; - if (a_type === "string" || a_type === "number" || a_type === "bigint" || a_type === "boolean" || a_type === "undefined" || a === null) { - return false; - } - let b_type = typeof b; - if (a_type === "function" || b_type === "function") { - throw new Error("Invalid_argument", { - cause: { - RE_EXN_ID: "Invalid_argument", - _1: "equal: functional value" - } - }); - } - if (b_type === "number" || b_type === "bigint" || b_type === "undefined" || b === null) { - return false; - } - let tag_a = a.TAG; - let tag_b = b.TAG; - if (tag_a === 248) { - return a[1] === b[1]; - } - if (tag_a === 251) { - throw new Error("Invalid_argument", { - cause: { - RE_EXN_ID: "Invalid_argument", - _1: "equal: abstract value" - } - }); - } - if (tag_a !== tag_b) { - return false; - } - let len_a = a.length | 0; - let len_b = b.length | 0; - if (len_a === len_b) { +function equal(_a, _b) { + while (true) { + let b = _b; + let a = _a; + if (a === b) { + return true; + } + let a_type = typeof a; + if (a_type !== "object" || a === null) { + return false; + } + let b_type = typeof b; + if (b_type !== "object" || b === null) { + return false; + } + let tag_a = a.TAG; + let tag_b = b.TAG; + if (tag_a !== tag_b) { + return false; + } if (Array.isArray(a)) { - let _i = 0; - while (true) { - let i = _i; - if (i === len_a) { - return true; - } - if (!equal(a[i], b[i])) { + let len_a = a.length | 0; + let len_b = b.length | 0; + if (len_a !== len_b) { + return false; + } else { + let _i = 0; + while (true) { + let i = _i; + if (i === len_a) { + return true; + } + if (!equal(a[i], b[i])) { + return false; + } + _i = i + 1 | 0; + continue; + }; + } + } + if (!(a instanceof Error)) { + if ((a instanceof Date)) { + if ((b instanceof Date)) { + return !(a > b || a < b); + } else { return false; } - _i = i + 1 | 0; - continue; - }; - } else if ((a instanceof Date && b instanceof Date)) { - return !(a > b || a < b); - } else { - let result = { - contents: true - }; - let do_key_a = function (key) { - if (!Object.prototype.hasOwnProperty.call(b, key)) { - result.contents = false; - return; - } - - }; - let do_key_b = function (key) { - if (!Object.prototype.hasOwnProperty.call(a, key) || !equal(b[key], a[key])) { - result.contents = false; - return; + } else { + let result = { + contents: true + }; + let do_key_a = function (key) { + if (!Object.prototype.hasOwnProperty.call(b, key)) { + result.contents = false; + return; + } + + }; + let do_key_b = function (key) { + if (!Object.prototype.hasOwnProperty.call(a, key) || !equal(b[key], a[key])) { + result.contents = false; + return; + } + + }; + for_in(a, do_key_a); + if (result.contents) { + for_in(b, do_key_b); } - - }; - for_in(a, do_key_a); - if (result.contents) { - for_in(b, do_key_b); + return result.contents; } - return result.contents; } - } else { - return false; - } + if (!((b instanceof Error) && a.message === b.message)) { + return false; + } + _b = b.cause; + _a = a.cause; + continue; + }; } function equal_null(x, y) {