diff --git a/CHANGES.md b/CHANGES.md index 639c3b5af4..c3e6ce6392 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ * Runtime: remove polyfill for Map to simplify MlObjectTable implementation (#1846) * Runtime: refactor caml_xmlhttprequest_create implementation (#1846) * Runtime: update constant imports to use `node:fs` module (#1850) +* Runtime: make Obj.dup work with floats and boxed numbers (#1871) ## Bug fixes * Runtime: fix path normalization (#1848) diff --git a/compiler/lib/generate.ml b/compiler/lib/generate.ml index 112eba3265..f3493e7129 100644 --- a/compiler/lib/generate.ml +++ b/compiler/lib/generate.ml @@ -1159,8 +1159,6 @@ let _ = register_tern_prim "caml_array_unsafe_set" (fun cx cy cz _ -> J.EBin (J.Eq, Mlvalue.Array.field cx cy, cz)); register_un_prim "caml_alloc_dummy" `Pure (fun _ _ -> J.array []); - register_un_prim "caml_obj_dup" ~need_loc:true `Mutable (fun cx loc -> - J.call (J.dot cx (Utf8_string.of_string_exn "slice")) [] loc); register_un_prim "caml_int_of_float" `Pure (fun cx _loc -> to_int cx); register_un_math_prim "caml_abs_float" "abs"; register_un_math_prim "caml_acos_float" "acos"; diff --git a/compiler/tests-compiler/obj.ml b/compiler/tests-compiler/obj.ml index d1ca861a55..b114cd1eac 100644 --- a/compiler/tests-compiler/obj.ml +++ b/compiler/tests-compiler/obj.ml @@ -58,5 +58,5 @@ let%expect_test "static eval of string get" = //end function my_new_block(x, l){return runtime.caml_obj_block(x + 1 | 0, 3);} //end - function my_dup(t){return [0, t, 0].slice();} + function my_dup(t){return runtime.caml_obj_dup([0, t, 0]);} //end |}] diff --git a/compiler/tests-full/stdlib.cma.expected.js b/compiler/tests-full/stdlib.cma.expected.js index 0f97ac1161..b904d0ddac 100644 --- a/compiler/tests-full/stdlib.cma.expected.js +++ b/compiler/tests-full/stdlib.cma.expected.js @@ -22432,13 +22432,13 @@ /*<>*/ } var errors = - /*<>*/ [0, - cst$4, - "(Cannot print locations:\n bytecode executable program file not found)", - "(Cannot print locations:\n bytecode executable program file appears to be corrupt)", - "(Cannot print locations:\n bytecode executable program file has wrong magic number)", - "(Cannot print locations:\n bytecode executable program file cannot be opened;\n -- too many open files. Try running with OCAMLRUNPARAM=b=2)"].slice - (), + /*<>*/ runtime.caml_obj_dup + ([0, + cst$4, + "(Cannot print locations:\n bytecode executable program file not found)", + "(Cannot print locations:\n bytecode executable program file appears to be corrupt)", + "(Cannot print locations:\n bytecode executable program file has wrong magic number)", + "(Cannot print locations:\n bytecode executable program file cannot be opened;\n -- too many open files. Try running with OCAMLRUNPARAM=b=2)"]), _o_ = [0, [11, cst_Fatal_error_exception, [2, 0, [12, 10, 0]]], @@ -31106,7 +31106,7 @@ Stdlib_List = global_data.Stdlib__List, Stdlib_Map = global_data.Stdlib__Map; function copy(o){ - var o$0 = /*<>*/ o.slice(); + var o$0 = /*<>*/ runtime.caml_obj_dup(o); /*<>*/ return caml_set_oo_id(o$0) /*<>*/ ; } var params = /*<>*/ [0, 1, 1, 1, 3, 16]; diff --git a/compiler/tests-jsoo/test_obj.ml b/compiler/tests-jsoo/test_obj.ml index 84ea39f0da..ddcad72bbf 100644 --- a/compiler/tests-jsoo/test_obj.ml +++ b/compiler/tests-jsoo/test_obj.ml @@ -45,7 +45,7 @@ let%expect_test "is_int" = (* https://github.com/ocsigen/js_of_ocaml/issues/666 *) (* https://github.com/ocsigen/js_of_ocaml/pull/725 *) -let%expect_test "dup" = +let%expect_test "dup string/bytes" = let magic = "abcd" in let js_string_enabled = match Sys.backend_type with @@ -71,6 +71,55 @@ let%expect_test "dup" = true |}] +let%expect_test "dup tuple" = + let x = 1, "a", 2.1 in + let x' = Obj.obj (Obj.dup (Obj.repr x)) in + print_bool (x = x'); + print_bool (x != x'); + [%expect {| + true + true + |}] + +let%expect_test "dup numbers" = + let js = + match Sys.backend_type with + | Other "js_of_ocaml" -> true + | _ -> false + in + let x = 2.1 in + let x' = Obj.obj (Obj.dup (Obj.repr x)) in + print_bool (x = x'); + print_bool ((not js) = (x != x')); + [%expect {| + true + true + |}]; + let x = 21L in + let x' = Obj.obj (Obj.dup (Obj.repr x)) in + print_bool (x = x'); + print_bool (x != x'); + [%expect {| + true + true + |}]; + let x = 21l in + let x' = Obj.obj (Obj.dup (Obj.repr x)) in + print_bool (x = x'); + print_bool ((not js) = (x != x')); + [%expect {| + true + true + |}]; + let x = 21n in + let x' = Obj.obj (Obj.dup (Obj.repr x)) in + print_bool (x = x'); + print_bool ((not js) = (x != x')); + [%expect {| + true + true + |}] + let%expect_test "sameness" = (* FIXME: Jsoo returns the wrong opposite result for cases below. Would be fixed by GH#1410 *) diff --git a/runtime/js/int64.js b/runtime/js/int64.js index f0843c9c08..293fca122c 100644 --- a/runtime/js/int64.js +++ b/runtime/js/int64.js @@ -30,7 +30,7 @@ class MlInt64 { this.caml_custom = "_j"; } - copy() { + slice() { return new MlInt64(this.lo, this.mi, this.hi); } @@ -179,8 +179,8 @@ class MlInt64 { udivmod(x) { var offset = 0; - var modulus = this.copy(); - var divisor = x.copy(); + var modulus = this.slice(); + var divisor = x.slice(); var quotient = new MlInt64(0, 0, 0); while (modulus.ucompare(divisor) > 0) { offset++; diff --git a/runtime/js/obj.js b/runtime/js/obj.js index 0a4ede2d2a..d0df309b40 100644 --- a/runtime/js/obj.js +++ b/runtime/js/obj.js @@ -81,10 +81,7 @@ function caml_obj_with_tag(tag, x) { //Provides: caml_obj_dup mutable (mutable) function caml_obj_dup(x) { - var l = x.length; - var a = new Array(l); - for (var i = 0; i < l; i++) a[i] = x[i]; - return a; + return typeof x === "number" ? x : x.slice(); } //Provides: caml_obj_truncate (mutable, const)