diff --git a/backbone.js b/backbone.js index bcf8c596..d903c6e8 100644 --- a/backbone.js +++ b/backbone.js @@ -623,8 +623,9 @@ // Cached regular expressions for matching named param parts and splatted // parts of route strings. - var namedParam = /:([\w\d]+)/g; - var splatParam = /\*([\w\d]+)/g; + var namedParam = /:([\w\d]+)/g; + var splatParam = /\*([\w\d]+)/g; + var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g; // Set up all inheritable **Backbone.Controller** properties and methods. _.extend(Backbone.Controller.prototype, Backbone.Events, { @@ -667,7 +668,9 @@ // Convert a route string into a regular expression, suitable for matching // against the current location fragment. _routeToRegExp : function(route) { - route = route.replace(namedParam, "([^\/]*)").replace(splatParam, "(.*?)"); + route = route.replace(escapeRegExp, "\\$&") + .replace(namedParam, "([^\/]*)") + .replace(splatParam, "(.*?)"); return new RegExp('^' + route + '$'); }, diff --git a/test/controller.js b/test/controller.js index 316806b3..144e1ec4 100644 --- a/test/controller.js +++ b/test/controller.js @@ -8,7 +8,8 @@ $(document).ready(function() { "search/:query": "search", "search/:query/p:page": "search", "splat/*args/end": "splat", - "*first/complex-:part/*rest": "complex" + "*first/complex-:part/*rest": "complex", + "query?*args": "query" }, initialize : function(options) { @@ -28,6 +29,10 @@ $(document).ready(function() { this.first = first; this.part = part; this.rest = rest; + }, + + query : function(args) { + this.queryArgs = args; } }); @@ -74,6 +79,14 @@ $(document).ready(function() { equals(controller.part, 'part'); equals(controller.rest, 'four/five/six/seven'); start(); + }, 10); + }); + + asyncTest("Controller: routes (query)", function() { + window.location.hash = 'query?a=b&c=d'; + setTimeout(function() { + equals(controller.queryArgs, 'a=b&c=d'); + start(); window.location.hash = ''; }, 10); });