// any existing path and the resulting path cleaned of any ./ or ../ elements.
 // Any sequences of multiple / characters will be reduced to a single /.
 func (u *URL) JoinPath(elem ...string) *URL {
-       url := *u
-       if len(elem) > 0 {
-               elem = append([]string{u.EscapedPath()}, elem...)
-               p := path.Join(elem...)
-               // path.Join will remove any trailing slashes.
-               // Preserve at least one.
-               if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
-                       p += "/"
-               }
-               url.setPath(p)
+       elem = append([]string{u.EscapedPath()}, elem...)
+       var p string
+       if !strings.HasPrefix(elem[0], "/") {
+               // Return a relative path if u is relative,
+               // but ensure that it contains no ../ elements.
+               elem[0] = "/" + elem[0]
+               p = path.Join(elem...)[1:]
+       } else {
+               p = path.Join(elem...)
        }
+       // path.Join will remove any trailing slashes.
+       // Preserve at least one.
+       if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
+               p += "/"
+       }
+       url := *u
+       url.setPath(p)
        return &url
 }
 
 
                        elem: []string{"../../../go"},
                        out:  "https://go.googlesource.com/go",
                },
+               {
+                       base: "https://go.googlesource.com/",
+                       elem: []string{"../go"},
+                       out:  "https://go.googlesource.com/go",
+               },
+               {
+                       base: "https://go.googlesource.com",
+                       elem: []string{"../go"},
+                       out:  "https://go.googlesource.com/go",
+               },
+               {
+                       base: "https://go.googlesource.com",
+                       elem: []string{"../go", "../../go", "../../../go"},
+                       out:  "https://go.googlesource.com/go",
+               },
+               {
+                       base: "https://go.googlesource.com/../go",
+                       elem: nil,
+                       out:  "https://go.googlesource.com/go",
+               },
                {
                        base: "https://go.googlesource.com/",
                        elem: []string{"./go"},
                {
                        base: "https://go.googlesource.com",
                        elem: nil,
-                       out:  "https://go.googlesource.com",
+                       out:  "https://go.googlesource.com/",
                },
                {
                        base: "https://go.googlesource.com/",
                        elem: []string{"c%2fd"},
                        out:  "https://go.googlesource.com/a%2fb/c%2fd",
                },
+               {
+                       base: "https://go.googlesource.com/a/b",
+                       elem: []string{"/go"},
+                       out:  "https://go.googlesource.com/a/b/go",
+               },
                {
                        base: "/",
                        elem: nil,
                        out:  "/",
                },
+               {
+                       base: "a",
+                       elem: nil,
+                       out:  "a",
+               },
+               {
+                       base: "a",
+                       elem: []string{"b"},
+                       out:  "a/b",
+               },
+               {
+                       base: "a",
+                       elem: []string{"../b"},
+                       out:  "b",
+               },
+               {
+                       base: "a",
+                       elem: []string{"../../b"},
+                       out:  "b",
+               },
+               {
+                       base: "",
+                       elem: []string{"a"},
+                       out:  "a",
+               },
+               {
+                       base: "",
+                       elem: []string{"../a"},
+                       out:  "a",
+               },
        }
        for _, tt := range tests {
                wantErr := "nil"