From ca02cd2290e672f2967538ceeccacf7cf47bb543 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Fri, 9 Sep 2016 10:41:46 -0400 Subject: [PATCH] bug fix for #743 --- docs/Manual.html | 22 ++++++++- jscomp/runtime/caml_string.ml | 44 +++++++++++++----- jscomp/test/.depend | 4 ++ jscomp/test/Makefile | 3 +- jscomp/test/bytes_split_gpr_743.js | 74 ++++++++++++++++++++++++++++++ jscomp/test/bytes_split_gpr_743.ml | 35 ++++++++++++++ lib/js/caml_string.js | 49 ++++++++++++++++---- site/docsource/CHANGELOG.adoc | 7 ++- 8 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 jscomp/test/bytes_split_gpr_743.js create mode 100644 jscomp/test/bytes_split_gpr_743.ml diff --git a/docs/Manual.html b/docs/Manual.html index 4e248b22dbf..aa9e53a00f8 100644 --- a/docs/Manual.html +++ b/docs/Manual.html @@ -639,6 +639,7 @@

BuckleScript User Ma
  • Appendix A: CHANGES
  • +
  • 1.02 (dev)
  • 1.01
  • 1.0
  • @@ -4096,6 +4097,25 @@

    Appendix A: CHANGES

    +
    + +
    +

    1.02 (dev)

    +
    +
    +
      +
    • +

      Bug fixes and enhancement

      +
      +
        +
      • +

        Fix Bytes.blit when src==dst #743

        +
      • +
      +
      +
    • +
    +
    @@ -4119,7 +4139,7 @@

    1.01

  • -

    Bug fixes and enhancment

    +

    Bug fixes and enhancement

    • diff --git a/jscomp/runtime/caml_string.ml b/jscomp/runtime/caml_string.ml index e60e982b42f..64a90afca3d 100644 --- a/jscomp/runtime/caml_string.ml +++ b/jscomp/runtime/caml_string.ml @@ -87,25 +87,45 @@ let caml_blit_string s1 i1 s2 i2 (len : int ) = done end +(** Same as {!Array.prototype.copyWithin} *) +let copyWithin s1 i1 i2 len = + if i1 < i2 then (* nop for i1 = i2 *) + let range_a = length s1 - i2 - 1 in + let range_b = len - 1 in + let range = if range_a > range_b then range_b else range_a in + for j = range downto 0 do + unsafe_set s1 (i2 + j) (unsafe_get s1 (i1 + j)) + done + else if i1 > i2 then + let range_a = length s1 - i1 - 1 in + let range_b = len - 1 in + let range = if range_a > range_b then range_b else range_a in + for k = 0 to range do + unsafe_set s1 (i2 + k) (unsafe_get s1 (i1 + k)) + done + (* TODO: when the compiler could optimize small function calls, use high order functions instead *) let caml_blit_bytes s1 i1 s2 i2 len = if len > 0 then - let off1 = length s1 - i1 in - if len <= off1 then - for i = 0 to len - 1 do - unsafe_set s2 (i2 + i) (unsafe_get s1 (i1 + i)) - done - else - begin - for i = 0 to off1 - 1 do + if s1 == s2 then + copyWithin s1 i1 i2 len + else + let off1 = length s1 - i1 in + if len <= off1 then + for i = 0 to len - 1 do unsafe_set s2 (i2 + i) (unsafe_get s1 (i1 + i)) - done; - for i = off1 to len - 1 do - unsafe_set s2 (i2 + i) '\000' done - end + else + begin + for i = 0 to off1 - 1 do + unsafe_set s2 (i2 + i) (unsafe_get s1 (i1 + i)) + done; + for i = off1 to len - 1 do + unsafe_set s2 (i2 + i) '\000' + done + end (** checkout [Bytes.empty] -- to be inlined? *) let bytes_of_string s = diff --git a/jscomp/test/.depend b/jscomp/test/.depend index bb234d751c3..338e0365759 100644 --- a/jscomp/test/.depend +++ b/jscomp/test/.depend @@ -114,6 +114,8 @@ buffer_test.cmj : ../stdlib/string.cmi mt.cmi ../stdlib/bytes.cmi \ ../stdlib/buffer.cmi buffer_test.cmx : ../stdlib/string.cmx mt.cmx ../stdlib/bytes.cmx \ ../stdlib/buffer.cmx +bytes_split_gpr_743.cmj : mt.cmi ../runtime/js.cmj ../stdlib/bytes.cmi +bytes_split_gpr_743.cmx : mt.cmx ../runtime/js.cmx ../stdlib/bytes.cmx caml_compare_test.cmj : mt.cmi caml_compare_test.cmx : mt.cmx caml_format_test.cmj : ../stdlib/printf.cmi mt.cmi ../stdlib/int64.cmi \ @@ -926,6 +928,8 @@ buffer_test.cmo : ../stdlib/string.cmi mt.cmi ../stdlib/bytes.cmi \ ../stdlib/buffer.cmi buffer_test.cmj : ../stdlib/string.cmj mt.cmj ../stdlib/bytes.cmj \ ../stdlib/buffer.cmj +bytes_split_gpr_743.cmo : mt.cmi ../runtime/js.cmo ../stdlib/bytes.cmi +bytes_split_gpr_743.cmj : mt.cmj ../runtime/js.cmj ../stdlib/bytes.cmj caml_compare_test.cmo : mt.cmi caml_compare_test.cmj : mt.cmj caml_format_test.cmo : ../stdlib/printf.cmi mt.cmi ../stdlib/int64.cmi \ diff --git a/jscomp/test/Makefile b/jscomp/test/Makefile index b9e05d6399d..0970e0395ab 100644 --- a/jscomp/test/Makefile +++ b/jscomp/test/Makefile @@ -65,7 +65,8 @@ OTHERS := literals a test_ari test_export2 test_internalOO test_obj_simple_ffi t watch_test bs_node_string_buffer_test \ bs_ignore_test bs_ignore_effect \ ppx_this_obj_field single_module_alias \ - CCSexpM CCSexpM_test CCSexp js_json_test array_subtle_test + CCSexpM CCSexpM_test CCSexp js_json_test array_subtle_test bytes_split_gpr_743 + diff --git a/jscomp/test/bytes_split_gpr_743.js b/jscomp/test/bytes_split_gpr_743.js new file mode 100644 index 00000000000..5e181516578 --- /dev/null +++ b/jscomp/test/bytes_split_gpr_743.js @@ -0,0 +1,74 @@ +'use strict'; + +var Bytes = require("../../lib/js/bytes"); +var Mt = require("./mt"); +var Block = require("../../lib/js/block"); +var Caml_string = require("../../lib/js/caml_string"); + +var suites = [/* [] */0]; + +var test_id = [0]; + +function eq(loc, param) { + var y = param[1]; + var x = param[0]; + test_id[0] = test_id[0] + 1 | 0; + suites[0] = /* :: */[ + /* tuple */[ + loc + (" id " + test_id[0]), + function () { + return /* Eq */Block.__(0, [ + x, + y + ]); + } + ], + suites[0] + ]; + return /* () */0; +} + +var b = new Array(3); + +b[0] = /* "a" */97; + +b[1] = /* "b" */98; + +b[2] = /* "c" */99; + +Bytes.blit(b, 0, b, 1, 2); + +var res = Caml_string.bytes_to_string(b); + +console.log(res); + +eq('File "bytes_split_gpr_743.ml", line 17, characters 5-12', /* tuple */[ + "aab", + res + ]); + +var b$1 = new Array(3); + +b$1[0] = /* "a" */97; + +b$1[1] = /* "b" */98; + +b$1[2] = /* "c" */99; + +Bytes.blit(b$1, 1, b$1, 0, 2); + +var res2 = Caml_string.bytes_to_string(b$1); + +console.log(res2); + +eq('File "bytes_split_gpr_743.ml", line 32, characters 5-12', /* tuple */[ + "bcc", + res2 + ]); + +Mt.from_pair_suites("bytes_split_gpr_743.ml", suites[0]); + +exports.suites = suites; +exports.test_id = test_id; +exports.eq = eq; +/* Not a pure module */ diff --git a/jscomp/test/bytes_split_gpr_743.ml b/jscomp/test/bytes_split_gpr_743.ml new file mode 100644 index 00000000000..4b6a9ece077 --- /dev/null +++ b/jscomp/test/bytes_split_gpr_743.ml @@ -0,0 +1,35 @@ +let suites : Mt.pair_suites ref = ref [] +let test_id = ref 0 +let eq loc (x, y) = + incr test_id ; + suites := + (loc ^" id " ^ (string_of_int !test_id), (fun _ -> Mt.Eq(x,y))) :: !suites + + +let () = + let b = Bytes.create 3 in + Bytes.set b 0 'a'; + Bytes.set b 1 'b'; + Bytes.set b 2 'c'; + Bytes.blit b 0 b 1 2; + let res = (Bytes.unsafe_to_string b) in + Js.log res; (* "aab"*) + eq __LOC__ ("aab", res) + (* assert('a' = Bytes.get b 0); *) + (* assert('a' = Bytes.get b 1); *) + (* assert('b' = Bytes.get b 2); *) + (* () *) + + +let () = + let b = Bytes.create 3 in + Bytes.set b 0 'a'; + Bytes.set b 1 'b'; + Bytes.set b 2 'c'; + Bytes.blit b 1 b 0 2; + let res2 = (Bytes.unsafe_to_string b) in + Js.log res2 (* "bcc"*); + eq __LOC__ ("bcc", res2) + + +let () = Mt.from_pair_suites __FILE__ !suites diff --git a/lib/js/caml_string.js b/lib/js/caml_string.js index eb0978faca3..15026f4672b 100644 --- a/lib/js/caml_string.js +++ b/lib/js/caml_string.js @@ -80,21 +80,50 @@ function caml_blit_string(s1, i1, s2, i2, len) { function caml_blit_bytes(s1, i1, s2, i2, len) { if (len > 0) { - var off1 = s1.length - i1 | 0; - if (len <= off1) { - for(var i = 0 ,i_finish = len - 1 | 0; i <= i_finish; ++i){ - s2[i2 + i | 0] = s1[i1 + i | 0]; + if (s1 === s2) { + var s1$1 = s1; + var i1$1 = i1; + var i2$1 = i2; + var len$1 = len; + if (i1$1 < i2$1) { + var range_a = (s1$1.length - i2$1 | 0) - 1 | 0; + var range_b = len$1 - 1 | 0; + var range = range_a > range_b ? range_b : range_a; + for(var j = range; j >= 0; --j){ + s1$1[i2$1 + j | 0] = s1$1[i1$1 + j | 0]; + } + return /* () */0; + } + else if (i1$1 > i2$1) { + var range_a$1 = (s1$1.length - i1$1 | 0) - 1 | 0; + var range_b$1 = len$1 - 1 | 0; + var range$1 = range_a$1 > range_b$1 ? range_b$1 : range_a$1; + for(var k = 0; k <= range$1; ++k){ + s1$1[i2$1 + k | 0] = s1$1[i1$1 + k | 0]; + } + return /* () */0; + } + else { + return 0; } - return /* () */0; } else { - for(var i$1 = 0 ,i_finish$1 = off1 - 1 | 0; i$1 <= i_finish$1; ++i$1){ - s2[i2 + i$1 | 0] = s1[i1 + i$1 | 0]; + var off1 = s1.length - i1 | 0; + if (len <= off1) { + for(var i = 0 ,i_finish = len - 1 | 0; i <= i_finish; ++i){ + s2[i2 + i | 0] = s1[i1 + i | 0]; + } + return /* () */0; } - for(var i$2 = off1 ,i_finish$2 = len - 1 | 0; i$2 <= i_finish$2; ++i$2){ - s2[i2 + i$2 | 0] = /* "\000" */0; + else { + for(var i$1 = 0 ,i_finish$1 = off1 - 1 | 0; i$1 <= i_finish$1; ++i$1){ + s2[i2 + i$1 | 0] = s1[i1 + i$1 | 0]; + } + for(var i$2 = off1 ,i_finish$2 = len - 1 | 0; i$2 <= i_finish$2; ++i$2){ + s2[i2 + i$2 | 0] = /* "\000" */0; + } + return /* () */0; } - return /* () */0; } } else { diff --git a/site/docsource/CHANGELOG.adoc b/site/docsource/CHANGELOG.adoc index 9d62e273b91..2cb33a09e9a 100644 --- a/site/docsource/CHANGELOG.adoc +++ b/site/docsource/CHANGELOG.adoc @@ -3,6 +3,11 @@ ## CHANGES :issues: https://github.com/bloomberg/bucklescript/issues +== 1.02 (dev) + +* Bug fixes and enhancement + +- Fix Bytes.blit when src==dst {issues}743[#743] == 1.01 @@ -12,7 +17,7 @@ - Introduce phantom arguments (`bs.ignore`) for ad-hoc polymorphism {issues}/686[#686] -* Bug fixes and enhancment +* Bug fixes and enhancement - Enforce `#=` always return unit {issues}718[#718] for better error messages