shithub: libmujs

Download patch

ref: 8c7f4dc57396e542b1e24a849f95561739a88887
parent: dbc00e4e019f6a4ecf0bdc5279a80e554f80f66f
author: Tor Andersson <[email protected]>
date: Sat Jan 18 11:13:23 EST 2014

Handle \uXXXX escapes in identifiers.

--- a/jslex.c
+++ b/jslex.c
@@ -152,6 +152,23 @@
 	J->lexchar = c;
 }
 
+static void unescape(js_State *J, const char **sp)
+{
+	if (ACCEPT('\\')) {
+		if (ACCEPT('u')) {
+			int x = 0;
+			if (!ishex(PEEK)) goto error; x |= tohex(PEEK) << 12; NEXT();
+			if (!ishex(PEEK)) goto error; x |= tohex(PEEK) << 8; NEXT();
+			if (!ishex(PEEK)) goto error; x |= tohex(PEEK) << 4; NEXT();
+			if (!ishex(PEEK)) goto error; x |= tohex(PEEK);
+			J->lexchar = x;
+			return;
+		}
+error:
+		jsP_error(J, "unexpected escape sequence");
+	}
+}
+
 static void textinit(js_State *J)
 {
 	if (!J->buf.text) {
@@ -294,16 +311,16 @@
 	switch (PEEK) {
 	case 'u':
 		NEXT();
-		if (!ishex(PEEK)) return 1; else { x |= PEEK << 12; NEXT(); }
-		if (!ishex(PEEK)) return 1; else { x |= PEEK << 8; NEXT(); }
-		if (!ishex(PEEK)) return 1; else { x |= PEEK << 4; NEXT(); }
-		if (!ishex(PEEK)) return 1; else { x |= PEEK; NEXT(); }
+		if (!ishex(PEEK)) return 1; else { x |= tohex(PEEK) << 12; NEXT(); }
+		if (!ishex(PEEK)) return 1; else { x |= tohex(PEEK) << 8; NEXT(); }
+		if (!ishex(PEEK)) return 1; else { x |= tohex(PEEK) << 4; NEXT(); }
+		if (!ishex(PEEK)) return 1; else { x |= tohex(PEEK); NEXT(); }
 		textpush(J, x);
 		break;
 	case 'x':
 		NEXT();
-		if (!ishex(PEEK)) return 1; else { x |= PEEK << 4; NEXT(); }
-		if (!ishex(PEEK)) return 1; else { x |= PEEK; NEXT(); }
+		if (!ishex(PEEK)) return 1; else { x |= tohex(PEEK) << 4; NEXT(); }
+		if (!ishex(PEEK)) return 1; else { x |= tohex(PEEK); NEXT(); }
 		textpush(J, x);
 		break;
 	case '0': textpush(J, 0); NEXT(); break;
@@ -469,22 +486,6 @@
 			}
 		}
 
-		// TODO: \uXXXX escapes
-		if (isidentifierstart(PEEK)) {
-			textinit(J);
-			textpush(J, PEEK);
-
-			NEXT();
-			while (isidentifierpart(PEEK)) {
-				textpush(J, PEEK);
-				NEXT();
-			}
-
-			textend(J);
-
-			return findkeyword(J, J->buf.text);
-		}
-
 		if (PEEK >= '0' && PEEK <= '9') {
 			return lexnumber(J, sp);
 		}
@@ -606,6 +607,25 @@
 
 		case 0:
 			return 0; /* EOF */
+		}
+
+		/* Handle \uXXXX escapes in identifiers */
+		unescape(J, sp);
+		if (isidentifierstart(PEEK)) {
+			textinit(J);
+			textpush(J, PEEK);
+
+			NEXT();
+			unescape(J, sp);
+			while (isidentifierpart(PEEK)) {
+				textpush(J, PEEK);
+				NEXT();
+				unescape(J, sp);
+			}
+
+			textend(J);
+
+			return findkeyword(J, J->buf.text);
 		}
 
 		if (PEEK >= 0x20 && PEEK <= 0x7E)