Skip to content
This repository
Browse code

Update to fix failing test. Rewrite of the resolveObject function, an…

…d some tweaks to format.
  • Loading branch information...
commit 4526308560201bfcb9ae927abb96c2103ba31344 1 parent f65b36e
authored December 12, 2009 ry committed December 18, 2009
140  lib/uri.js
@@ -126,6 +126,7 @@ function uri_format (object) {
126 126
     throw new Error("UrlError: URL undefined for urls#format");
127 127
   if (object instanceof String || typeof(object) === 'string')
128 128
     return object;
  129
+  
129 130
   var domain =
130 131
     object.domains ?
131 132
     object.domains.join(".") :
@@ -138,7 +139,7 @@ function uri_format (object) {
138 139
       (object.password ? ":" + object.password : "") 
139 140
     ) :
140 141
     object.userInfo;
141  
-  var authority = (
  142
+  var authority = object.authority || ((
142 143
       userInfo ||
143 144
       domain ||
144 145
       object.port
@@ -146,20 +147,18 @@ function uri_format (object) {
146 147
       (userInfo ? userInfo + "@" : "") +
147 148
       (domain || "") + 
148 149
       (object.port ? ":" + object.port : "")
149  
-    ) :
150  
-    object.authority || "";
151  
-    
  150
+    ) : "");
  151
+  
152 152
   var directory =
153 153
     object.directories ?
154 154
     object.directories.join("/") :
155 155
     object.directory;
156 156
   var path =
157  
-    directory || object.file ?
158  
-    (
159  
-      (directory ? directory + "/" : "") +
160  
-      (object.file || "")
161  
-    ) :
162  
-    object.path;
  157
+    object.path ? object.path.substr(1) : (
  158
+      (directory || object.file) ? (
  159
+        (directory ? directory + "/" : "") +
  160
+        (object.file || "")
  161
+      ) : "");
163 162
   var authorityRoot = 
164 163
     object.authorityRoot
165 164
     || authority ? "//" : "";
@@ -175,74 +174,79 @@ function uri_format (object) {
175 174
   ) || object.url || "");
176 175
 };
177 176
 
178  
-/**** resolveObject
179  
-  returns an object representing a URL resolved from
180  
-  a relative location and a source location.
181  
-*/
182 177
 function uri_resolveObject (source, relative) {
183  
-  if (!source) 
  178
+  if (!source) return relative;
  179
+  
  180
+  // parse a string, or get new objects
  181
+  source = uri_parse(uri_format(source));
  182
+  relative = uri_parse(uri_format(relative));
  183
+  
  184
+  if (relative.url === "") return source;
  185
+  
  186
+  // links to xyz:... from abc:... are always absolute.
  187
+  if (relative.protocol && source.protocol && relative.protocol !== source.protocol) {
184 188
     return relative;
  189
+  }
  190
+  
  191
+  // if there's an authority root, but no protocol, then keep the current protocol
  192
+  if (relative.authorityRoot && !relative.protocol) {
  193
+    relative.protocol = source.protocol;
  194
+  }
  195
+  // if we have an authority root, then it's absolute
  196
+  if (relative.authorityRoot) return relative;
185 197
 
186  
-  source = uri_parse(source);
187  
-  relative = uri_parse(relative);
188  
-
189  
-  if (relative.url == "")
190  
-    return source;
191  
-
192  
-  delete source.url;
193  
-  delete source.authority;
194  
-  delete source.domain;
195  
-  delete source.userInfo;
196  
-  delete source.path;
197  
-  delete source.directory;
  198
+  
  199
+  // at this point, we start doing the tricky stuff
  200
+  // we know that relative doesn't have an authority, but might have root,
  201
+  // path, file, query, etc.
  202
+  // also, the directory segments might contain .. or .
  203
+  // start mutating "source", and then return that.
198 204
 
199  
-  if (
200  
-    relative.protocol && relative.protocol != source.protocol ||
201  
-    relative.authority && relative.authority != source.authority
202  
-  ) {
203  
-    source = relative;
  205
+  // relative urls that start with / are absolute to the authority/protocol
  206
+  if (relative.root) {
  207
+    [
  208
+      "path", "root", "directory", "directories", "file", "query", "anchor"
  209
+    ].forEach(function (part) { source[part] = relative[part] });
204 210
   } else {
205  
-    if (relative.root) {
206  
-      source.directories = relative.directories;
207  
-    } else {
208  
-
209  
-      var directories = relative.directories;
210  
-      for (var i = 0; i < directories.length; i++) {
211  
-        var directory = directories[i];
212  
-        if (directory == ".") {
213  
-        } else if (directory == "..") {
214  
-          if (source.directories.length) {
215  
-            source.directories.pop();
216  
-          } else {
217  
-            source.directories.push('..');
218  
-          }
219  
-        } else {
220  
-          source.directories.push(directory);
221  
-        }
222  
-      }
223  
-
224  
-      if (relative.file == ".") {
225  
-        relative.file = "";
226  
-      } else if (relative.file == "..") {
227  
-        source.directories.pop();
228  
-        relative.file = "";
229  
-      }
  211
+    // if you have /a/b/c and you're going to x/y/z, then that's /a/b/x/y/z
  212
+    // if you have /a/b/c/ and you're going ot x/y/z, then that's /a/b/c/x/y/z
  213
+    // if you have /a/b/c and you're going to ?foo, then that's /a/b/c?foo
  214
+    if (relative.file || relative.directory) {
  215
+      source.file = relative.file;
  216
+      source.query = relative.query;
  217
+      source.anchor = relative.anchor;
230 218
     }
  219
+    if (relative.query) source.query = relative.query;
  220
+    if (relative.query || relative.anchor) source.anchor = relative.anchor;
  221
+    
  222
+    // just append the dirs. we'll sort out .. and . later
  223
+    source.directories = source.directories.concat(relative.directories);
231 224
   }
232  
-
233  
-  if (relative.root)
234  
-    source.root = relative.root;
235  
-  if (relative.protcol)
236  
-    source.protocol = relative.protocol;
237  
-  if (!(!relative.path && relative.anchor))
238  
-    source.file = relative.file;
239  
-  source.query = relative.query;
240  
-  source.anchor = relative.anchor;
241  
-
  225
+  
  226
+  // back up "file" to the first non-dot
  227
+  // one step for ., two for ..
  228
+  var file = source.file;
  229
+  while (file === ".." || file === ".") {
  230
+    if (file === "..") source.directories.pop();
  231
+    file = source.directories.pop();
  232
+  }
  233
+  source.file = file || "";
  234
+  
  235
+  // walk over the dirs, replacing a/b/c/.. with a/b/ and a/b/c/. with a/b/c
  236
+  var dirs = [];
  237
+  source.directories.forEach(function (dir, i) {
  238
+    if (dir === "..") dirs.pop();
  239
+    else if (dir !== "." && dir !== "") dirs.push(dir);
  240
+  });
  241
+  
  242
+  // now construct path/etc.
  243
+  source.directories = dirs;
  244
+  source.directory = dirs.concat("").join("/");
  245
+  source.path = source.root + source.directory + source.file;
  246
+  source.url = uri_format(source);
242 247
   return source;
243 248
 };
244 249
 
245  
-
246 250
 /**** resolve
247 251
   returns a URL resovled to a relative URL from a source URL.
248 252
 */
8  test/mjsunit/test-uri.js
@@ -168,6 +168,7 @@ for (var url in parseTests) {
168 168
   
169 169
   var expected = url,
170 170
     actual = uri.format(parseTests[url]);
  171
+  
171 172
   assert.equal(expected, actual, "format("+url+") == "+url+"\nactual:"+actual);
172 173
 }
173 174
 
@@ -175,12 +176,13 @@ for (var url in parseTests) {
175 176
   // [from, path, expected]
176 177
   ["/foo/bar/baz", "quux", "/foo/bar/quux"],
177 178
   ["/foo/bar/baz", "quux/asdf", "/foo/bar/quux/asdf"],
178  
-  ["/foo/bar/baz", "quux/baz", "/foo/bar/quux/baz"], //TODO: failing test
179  
-  ["/foo/bar/baz", "../quux/baz", "/foo/quux/baz"], //TODO: failing test
  179
+  ["/foo/bar/baz", "quux/baz", "/foo/bar/quux/baz"],
  180
+  ["/foo/bar/baz", "../quux/baz", "/foo/quux/baz"],
180 181
   ["/foo/bar/baz", "/bar", "/bar"],
181 182
   ["/foo/bar/baz/", "quux", "/foo/bar/baz/quux"],
182 183
   ["/foo/bar/baz/", "quux/baz", "/foo/bar/baz/quux/baz"],
183  
-  ["/foo/bar/baz", "../../../../../../../../quux/baz", "/quux/baz"]
  184
+  ["/foo/bar/baz", "../../../../../../../../quux/baz", "/quux/baz"],
  185
+  ["/foo/bar/baz", "../../../../../../../quux/baz", "/quux/baz"]
184 186
 ].forEach(function (relativeTest) {
185 187
   var a = uri.resolve(relativeTest[0], relativeTest[1]),
186 188
     e = relativeTest[2];

0 notes on commit 4526308

Please sign in to comment.
Something went wrong with that request. Please try again.