Skip to content

Commit 32d9180

Browse files
committed
1. Fix an edge case of base name
basename /// = / 2. When in same package, no longer need play the trick of node_module resolution, fix #1180
1 parent 23f11d1 commit 32d9180

17 files changed

+757
-225
lines changed

jscomp/bin/all_ounit_tests.i.ml

Lines changed: 171 additions & 69 deletions
Large diffs are not rendered by default.

jscomp/bin/all_ounit_tests.ml

Lines changed: 118 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,9 @@ val inter4 : string -> string -> string -> string -> string
17441744
val concat_array : string -> string array -> string
17451745

17461746
val single_colon : string
1747+
1748+
val parent_dir_lit : string
1749+
val current_dir_lit : string
17471750
end = struct
17481751
#1 "ext_string.ml"
17491752
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
@@ -2217,6 +2220,8 @@ let inter4 a b c d =
22172220
concat_array single_space [| a; b ; c; d|]
22182221

22192222

2223+
let parent_dir_lit = ".."
2224+
let current_dir_lit = "."
22202225
end
22212226
module Ounit_array_tests
22222227
= struct
@@ -9658,7 +9663,7 @@ val path_as_directory : string -> string
96589663
just treat it as a library instead
96599664
*)
96609665

9661-
val node_relative_path : t -> [`File of string] -> string
9666+
val node_relative_path : bool -> t -> [`File of string] -> string
96629667

96639668
val chop_extension : ?loc:string -> string -> string
96649669

@@ -9867,12 +9872,15 @@ let relative_path file_or_dir_1 file_or_dir_2 =
98679872

98689873
[file1] is currently compilation file
98699874
[file2] is the dependency
9875+
9876+
TODO: this is a hackish function: FIXME
98709877
*)
9871-
let node_relative_path (file1 : t)
9878+
let node_relative_path node_modules_shorten (file1 : t)
98729879
(`File file2 as dep_file : [`File of string]) =
98739880
let v = Ext_string.find file2 ~sub:Literals.node_modules in
98749881
let len = String.length file2 in
9875-
if v >= 0 then
9882+
if node_modules_shorten && v >= 0 then
9883+
98769884
let rec skip i =
98779885
if i >= len then
98789886
Ext_pervasives.failwithf ~loc:__LOC__ "invalid path: %s" file2
@@ -9958,34 +9966,64 @@ let combine p1 p2 =
99589966
split_aux "//ghosg//ghsogh/";;
99599967
- : string * string list = ("/", ["ghosg"; "ghsogh"])
99609968
]}
9969+
Note that
9970+
{[
9971+
Filename.dirname "/a/" = "/"
9972+
Filename.dirname "/a/b/" = Filename.dirname "/a/b" = "/a"
9973+
]}
9974+
Special case:
9975+
{[
9976+
basename "//" = "/"
9977+
basename "///" = "/"
9978+
]}
9979+
{[
9980+
basename "" = "."
9981+
basename "" = "."
9982+
dirname "" = "."
9983+
dirname "" = "."
9984+
]}
99619985
*)
99629986
let split_aux p =
99639987
let rec go p acc =
99649988
let dir = Filename.dirname p in
99659989
if dir = p then dir, acc
9966-
else go dir (Filename.basename p :: acc)
9990+
else
9991+
let new_path = Filename.basename p in
9992+
if Ext_string.equal new_path Filename.dir_sep then
9993+
go dir acc
9994+
(* We could do more path simplification here
9995+
leave to [rel_normalized_absolute_path]
9996+
*)
9997+
else
9998+
go dir (new_path :: acc)
9999+
996710000
in go p []
996810001

10002+
10003+
996910004
(**
997010005
TODO: optimization
997110006
if [from] and [to] resolve to the same path, a zero-length string is returned
997210007
*)
997310008
let rel_normalized_absolute_path from to_ =
997410009
let root1, paths1 = split_aux from in
997510010
let root2, paths2 = split_aux to_ in
9976-
if root1 <> root2 then root2 else
10011+
if root1 <> root2 then root2
10012+
else
997710013
let rec go xss yss =
997810014
match xss, yss with
997910015
| x::xs, y::ys ->
9980-
if x = y then go xs ys
10016+
if Ext_string.equal x y then go xs ys
998110017
else
998210018
let start =
9983-
List.fold_left (fun acc _ -> acc // ".." ) ".." xs in
10019+
List.fold_left (fun acc _ -> acc // Ext_string.parent_dir_lit )
10020+
Ext_string.parent_dir_lit xs in
998410021
List.fold_left (fun acc v -> acc // v) start yss
9985-
| [], [] -> ""
10022+
| [], [] -> Ext_string.empty
998610023
| [], y::ys -> List.fold_left (fun acc x -> acc // x) y ys
998710024
| x::xs, [] ->
9988-
List.fold_left (fun acc _ -> acc // ".." ) ".." xs in
10025+
List.fold_left (fun acc _ -> acc // Ext_string.parent_dir_lit )
10026+
Ext_string.parent_dir_lit xs in
998910027
go paths1 paths2
999010028

999110029
(*TODO: could be hgighly optimized later
@@ -10007,6 +10045,7 @@ let rel_normalized_absolute_path from to_ =
1000710045
normalize_absolute_path "/a";;
1000810046
]}
1000910047
*)
10048+
(** See tests in {!Ounit_path_tests} *)
1001010049
let normalize_absolute_path x =
1001110050
let drop_if_exist xs =
1001210051
match xs with
@@ -10015,11 +10054,13 @@ let normalize_absolute_path x =
1001510054
let rec normalize_list acc paths =
1001610055
match paths with
1001710056
| [] -> acc
10018-
| "." :: xs -> normalize_list acc xs
10019-
| ".." :: xs ->
10020-
normalize_list (drop_if_exist acc ) xs
1002110057
| x :: xs ->
10022-
normalize_list (x::acc) xs
10058+
if Ext_string.equal x Ext_string.current_dir_lit then
10059+
normalize_list acc xs
10060+
else if Ext_string.equal x Ext_string.parent_dir_lit then
10061+
normalize_list (drop_if_exist acc ) xs
10062+
else
10063+
normalize_list (x::acc) xs
1002310064
in
1002410065
let root, paths = split_aux x in
1002510066
let rev_paths = normalize_list [] paths in
@@ -10048,13 +10089,13 @@ module Ounit_path_tests
1004810089
= struct
1004910090
#1 "ounit_path_tests.ml"
1005010091
let ((>::),
10051-
(>:::)) = OUnit.((>::),(>:::))
10092+
(>:::)) = OUnit.((>::),(>:::))
1005210093

1005310094

1005410095
let normalize = Ext_filename.normalize_absolute_path
1005510096
let (=~) x y =
1005610097
OUnit.assert_equal ~cmp:(fun x y -> Ext_string.equal x y ) x y
10057-
10098+
1005810099
let suites =
1005910100
__FILE__
1006010101
>:::
@@ -10093,7 +10134,68 @@ let suites =
1009310134
end;
1009410135
__LOC__ >:: begin fun _ ->
1009510136
normalize "/./a/.////////j/k//../////..///././b/./c/d/././../" =~ "/a/b/c"
10096-
end
10137+
end;
10138+
10139+
__LOC__ >:: begin fun _ ->
10140+
let aux a b result =
10141+
10142+
Ext_filename.rel_normalized_absolute_path
10143+
a b =~ result ;
10144+
10145+
Ext_filename.rel_normalized_absolute_path
10146+
(String.sub a 0 (String.length a - 1))
10147+
b =~ result ;
10148+
10149+
Ext_filename.rel_normalized_absolute_path
10150+
a
10151+
(String.sub b 0 (String.length b - 1)) =~ result
10152+
;
10153+
10154+
10155+
Ext_filename.rel_normalized_absolute_path
10156+
(String.sub a 0 (String.length a - 1 ))
10157+
(String.sub b 0 (String.length b - 1))
10158+
=~ result
10159+
in
10160+
aux
10161+
"/a/b/c/"
10162+
"/a/b/c/d/" "d";
10163+
aux
10164+
"/a/b/c/"
10165+
"/a/b/c/d/e/f/" "d/e/f" ;
10166+
aux
10167+
"/a/b/c/d/"
10168+
"/a/b/c/" ".." ;
10169+
aux
10170+
"/a/b/c/d/"
10171+
"/a/b/" "../.." ;
10172+
aux
10173+
"/a/b/c/d/"
10174+
"/a/" "../../.." ;
10175+
aux
10176+
"/a/b/c/d/"
10177+
"//" "../../../.." ;
10178+
10179+
10180+
end;
10181+
(* This is still correct just not optimal depends
10182+
on user's perspective *)
10183+
__LOC__ >:: begin fun _ ->
10184+
Ext_filename.rel_normalized_absolute_path
10185+
"/a/b/c/d"
10186+
"/x/y" =~ "../../../../x/y"
10187+
10188+
end;
10189+
10190+
__LOC__ >:: begin fun _ ->
10191+
Ext_filename.rel_normalized_absolute_path
10192+
"/usr/local/lib/node_modules/"
10193+
"//" =~ "../../../..";
10194+
Ext_filename.rel_normalized_absolute_path
10195+
"/usr/local/lib/node_modules/"
10196+
"/" =~ "../../../.."
10197+
end;
10198+
1009710199
]
1009810200

1009910201
end

jscomp/bin/bsb.ml

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,9 @@ val inter4 : string -> string -> string -> string -> string
830830
val concat_array : string -> string array -> string
831831

832832
val single_colon : string
833+
834+
val parent_dir_lit : string
835+
val current_dir_lit : string
833836
end = struct
834837
#1 "ext_string.ml"
835838
(* Copyright (C) 2015-2016 Bloomberg Finance L.P.
@@ -1303,6 +1306,8 @@ let inter4 a b c d =
13031306
concat_array single_space [| a; b ; c; d|]
13041307

13051308

1309+
let parent_dir_lit = ".."
1310+
let current_dir_lit = "."
13061311
end
13071312
module Ext_filename : sig
13081313
#1 "ext_filename.mli"
@@ -1358,7 +1363,7 @@ val path_as_directory : string -> string
13581363
just treat it as a library instead
13591364
*)
13601365

1361-
val node_relative_path : t -> [`File of string] -> string
1366+
val node_relative_path : bool -> t -> [`File of string] -> string
13621367

13631368
val chop_extension : ?loc:string -> string -> string
13641369

@@ -1567,12 +1572,15 @@ let relative_path file_or_dir_1 file_or_dir_2 =
15671572
15681573
[file1] is currently compilation file
15691574
[file2] is the dependency
1575+
1576+
TODO: this is a hackish function: FIXME
15701577
*)
1571-
let node_relative_path (file1 : t)
1578+
let node_relative_path node_modules_shorten (file1 : t)
15721579
(`File file2 as dep_file : [`File of string]) =
15731580
let v = Ext_string.find file2 ~sub:Literals.node_modules in
15741581
let len = String.length file2 in
1575-
if v >= 0 then
1582+
if node_modules_shorten && v >= 0 then
1583+
15761584
let rec skip i =
15771585
if i >= len then
15781586
Ext_pervasives.failwithf ~loc:__LOC__ "invalid path: %s" file2
@@ -1658,34 +1666,64 @@ let combine p1 p2 =
16581666
split_aux "//ghosg//ghsogh/";;
16591667
- : string * string list = ("/", ["ghosg"; "ghsogh"])
16601668
]}
1669+
Note that
1670+
{[
1671+
Filename.dirname "/a/" = "/"
1672+
Filename.dirname "/a/b/" = Filename.dirname "/a/b" = "/a"
1673+
]}
1674+
Special case:
1675+
{[
1676+
basename "//" = "/"
1677+
basename "///" = "/"
1678+
]}
1679+
{[
1680+
basename "" = "."
1681+
basename "" = "."
1682+
dirname "" = "."
1683+
dirname "" = "."
1684+
]}
16611685
*)
16621686
let split_aux p =
16631687
let rec go p acc =
16641688
let dir = Filename.dirname p in
16651689
if dir = p then dir, acc
1666-
else go dir (Filename.basename p :: acc)
1690+
else
1691+
let new_path = Filename.basename p in
1692+
if Ext_string.equal new_path Filename.dir_sep then
1693+
go dir acc
1694+
(* We could do more path simplification here
1695+
leave to [rel_normalized_absolute_path]
1696+
*)
1697+
else
1698+
go dir (new_path :: acc)
1699+
16671700
in go p []
16681701

1702+
1703+
16691704
(**
16701705
TODO: optimization
16711706
if [from] and [to] resolve to the same path, a zero-length string is returned
16721707
*)
16731708
let rel_normalized_absolute_path from to_ =
16741709
let root1, paths1 = split_aux from in
16751710
let root2, paths2 = split_aux to_ in
1676-
if root1 <> root2 then root2 else
1711+
if root1 <> root2 then root2
1712+
else
16771713
let rec go xss yss =
16781714
match xss, yss with
16791715
| x::xs, y::ys ->
1680-
if x = y then go xs ys
1716+
if Ext_string.equal x y then go xs ys
16811717
else
16821718
let start =
1683-
List.fold_left (fun acc _ -> acc // ".." ) ".." xs in
1719+
List.fold_left (fun acc _ -> acc // Ext_string.parent_dir_lit )
1720+
Ext_string.parent_dir_lit xs in
16841721
List.fold_left (fun acc v -> acc // v) start yss
1685-
| [], [] -> ""
1722+
| [], [] -> Ext_string.empty
16861723
| [], y::ys -> List.fold_left (fun acc x -> acc // x) y ys
16871724
| x::xs, [] ->
1688-
List.fold_left (fun acc _ -> acc // ".." ) ".." xs in
1725+
List.fold_left (fun acc _ -> acc // Ext_string.parent_dir_lit )
1726+
Ext_string.parent_dir_lit xs in
16891727
go paths1 paths2
16901728

16911729
(*TODO: could be hgighly optimized later
@@ -1707,6 +1745,7 @@ let rel_normalized_absolute_path from to_ =
17071745
normalize_absolute_path "/a";;
17081746
]}
17091747
*)
1748+
(** See tests in {!Ounit_path_tests} *)
17101749
let normalize_absolute_path x =
17111750
let drop_if_exist xs =
17121751
match xs with
@@ -1715,11 +1754,13 @@ let normalize_absolute_path x =
17151754
let rec normalize_list acc paths =
17161755
match paths with
17171756
| [] -> acc
1718-
| "." :: xs -> normalize_list acc xs
1719-
| ".." :: xs ->
1720-
normalize_list (drop_if_exist acc ) xs
17211757
| x :: xs ->
1722-
normalize_list (x::acc) xs
1758+
if Ext_string.equal x Ext_string.current_dir_lit then
1759+
normalize_list acc xs
1760+
else if Ext_string.equal x Ext_string.parent_dir_lit then
1761+
normalize_list (drop_if_exist acc ) xs
1762+
else
1763+
normalize_list (x::acc) xs
17231764
in
17241765
let root, paths = split_aux x in
17251766
let rev_paths = normalize_list [] paths in

0 commit comments

Comments
 (0)