From e889c4a2b8b4258d788a6e9466b4c0e693918acc Mon Sep 17 00:00:00 2001
From: Gisle Aas <gisle@aas.no>
Date: Mon, 22 Feb 2010 08:10:00 -0500
Subject: [PATCH] Faster escapejs #11778

---
 django/template/defaultfilters.py |   44 ++++++++++++++++++++----------------
 1 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index e6492dc..950cc16 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -68,29 +68,33 @@ def capfirst(value):
 capfirst.is_safe=True
 capfirst = stringfilter(capfirst)
 
-_base_js_escapes = (
-    ('\\', r'\x5C'),
-    ('\'', r'\x27'),
-    ('"', r'\x22'),
-    ('>', r'\x3E'),
-    ('<', r'\x3C'),
-    ('&', r'\x26'),
-    ('=', r'\x3D'),
-    ('-', r'\x2D'),
-    (';', r'\x3B'),
-    (u'\u2028', r'\u2028'),
-    (u'\u2029', r'\u2029')
-)
-
-# Escape every ASCII character with a value less than 32.
-_js_escapes = (_base_js_escapes +
-               tuple([('%c' % z, '\\x%02X' % z) for z in range(32)]))
+_js_escapes_dict = {
+    '\\': r'\x5C',
+    '\'': r'\x27',
+    '"': r'\x22',
+    '>': r'\x3E',
+    '<': r'\x3C',
+    '&': r'\x26',
+    '=': r'\x3D',
+    '-': r'\x2D',
+    ';': r'\x3B',
+    u'\u2028': r'\u2028',
+    u'\u2029': r'\u2029',
+}
+
+# also escape every ASCII character with a value less than 32.
+for z in range(32):
+    _js_escapes_dict[chr(z)] = '\\x%02X' % z
+
+# construct a Regex object matching the keys in _js_escapes_dict
+_js_escapes_re = u''.join(sorted(_js_escapes_dict.keys()))
+_js_escapes_re = re.sub(r'[\\\\\-\]]', r'\\\g<0>', _js_escapes_re) # escape \-]
+_js_escapes_re = '[' + _js_escapes_re + ']'
+_js_escapes_re = re.compile(_js_escapes_re)
 
 def escapejs(value):
     """Hex encodes characters for use in JavaScript strings."""
-    for bad, good in _js_escapes:
-        value = value.replace(bad, good)
-    return value
+    return _js_escapes_re.sub(lambda m: _js_escapes_dict[m.group(0)], value)
 escapejs = stringfilter(escapejs)
 
 def fix_ampersands(value):
-- 
1.6.6.rc4

