shithub: libmujs

Download patch

ref: cb273846e4702b096feb761d26c3cff82f2f22df
parent: e01fe424ab94395713d94f46eee57f1af0a279b4
author: Tor Andersson <tor@ccxvii.net>
date: Fri Dec 27 12:56:41 EST 2013

Throw errors on future words immediately.

Use the latest ECMA 262-5 list of future words.

--- a/js-lex.c
+++ b/js-lex.c
@@ -2,108 +2,66 @@
 
 #define nelem(a) (sizeof (a) / sizeof (a)[0])
 
-struct {
-	const char *string;
-	js_Token token;
-} keywords[] = {
-	{"abstract", JS_ABSTRACT},
-	{"boolean", JS_BOOLEAN},
-	{"break", JS_BREAK},
-	{"byte", JS_BYTE},
-	{"case", JS_CASE},
-	{"catch", JS_CATCH},
-	{"char", JS_CHAR},
-	{"class", JS_CLASS},
-	{"const", JS_CONST},
-	{"continue", JS_CONTINUE},
-	{"debugger", JS_DEBUGGER},
-	{"default", JS_DEFAULT},
-	{"delete", JS_DELETE},
-	{"do", JS_DO},
-	{"double", JS_DOUBLE},
-	{"else", JS_ELSE},
-	{"enum", JS_ENUM},
-	{"export", JS_EXPORT},
-	{"extends", JS_EXTENDS},
-	{"false", JS_FALSE},
-	{"final", JS_FINAL},
-	{"finally", JS_FINALLY},
-	{"float", JS_FLOAT},
-	{"for", JS_FOR},
-	{"function", JS_FUNCTION},
-	{"goto", JS_GOTO},
-	{"if", JS_IF},
-	{"implements", JS_IMPLEMENTS},
-	{"import", JS_IMPORT},
-	{"in", JS_IN},
-	{"instanceof", JS_INSTANCEOF},
-	{"int", JS_INT},
-	{"interface", JS_INTERFACE},
-	{"long", JS_LONG},
-	{"native", JS_NATIVE},
-	{"new", JS_NEW},
-	{"null", JS_NULL},
-	{"package", JS_PACKAGE},
-	{"private", JS_PRIVATE},
-	{"protected", JS_PROTECTED},
-	{"public", JS_PUBLIC},
-	{"return", JS_RETURN},
-	{"short", JS_SHORT},
-	{"static", JS_STATIC},
-	{"super", JS_SUPER},
-	{"switch", JS_SWITCH},
-	{"synchronized", JS_SYNCHRONIZED},
-	{"this", JS_THIS},
-	{"throw", JS_THROW},
-	{"throws", JS_THROWS},
-	{"transient", JS_TRANSIENT},
-	{"true", JS_TRUE},
-	{"try", JS_TRY},
-	{"typeof", JS_TYPEOF},
-	{"var", JS_VAR},
-	{"void", JS_VOID},
-	{"volatile", JS_VOLATILE},
-	{"while", JS_WHILE},
-	{"with", JS_WITH},
+static const char *keywords[] = {
+	"break", "case", "catch", "continue", "debugger", "default", "delete",
+	"do", "else", "false", "finally", "for", "function", "if", "in",
+	"instanceof", "new", "null", "return", "switch", "this", "throw",
+	"true", "try", "typeof", "var", "void", "while", "with",
 };
 
-static inline js_Token findkeyword(const char *s)
-{
-	int m, l, r;
-	int c;
+static const char *futurewords[] = {
+	"class", "const", "enum", "export", "extends", "import", "super",
+};
 
-	l = 0;
-	r = nelem(keywords) - 1;
+static const char *strictfuturewords[] = {
+	"implements", "interface", "let", "package", "private", "protected",
+	"public", "static", "yield",
+};
 
+static inline int findword(const char *s, const char **list, int num)
+{
+	int l = 0;
+	int r = num - 1;
 	while (l <= r) {
-		m = (l + r) >> 1;
-		c = strcmp(s, keywords[m].string);
+		int m = (l + r) >> 1;
+		int c = strcmp(s, list[m]);
 		if (c < 0)
 			r = m - 1;
 		else if (c > 0)
 			l = m + 1;
 		else
-			return keywords[m].token;
+			return m;
 	}
+	return -1;
+}
 
+static inline js_Token findkeyword(js_State *J, const char *s)
+{
+	int i = findword(s, keywords, nelem(keywords));
+	if (i >= 0)
+		return JS_BREAK + i;
+
+	if (findword(s, futurewords, nelem(futurewords)) >= 0)
+		return js_syntaxerror(J, "'%s' is a future reserved word", s);
+	if (J->strict && findword(s, strictfuturewords, nelem(strictfuturewords)) >= 0)
+		return js_syntaxerror(J, "'%s' is a strict mode future reserved word", s);
+
 	return JS_IDENTIFIER;
 }
 
 const char *tokenstrings[] = {
-	"ERROR", "EOF", "(identifier)", "null", "true", "false", "(number)",
-	"(string)", "(regexp)", "\\n", "{", "}", "(", ")", "[", "]", ".", ";",
-	",", "<", ">", "<=", ">=", "==", "!=", "===", "!==", "+", "-", "*",
-	"%", "++", "--", "<<", ">>", ">>>", "&", "|", "^", "!", "~", "&&",
-	"||", "?", ":", "=", "+=", "-=", "*=", "%=", "<<=", ">>=", ">>>=",
-	"&=", "|=", "^=", "/", "/=", "break", "case", "catch", "continue",
-	"default", "delete", "do", "else", "finally", "for", "function", "if",
-	"in", "instanceof", "new", "return", "switch", "this", "throw", "try",
-	"typeof", "var", "void", "while", "with", "abstract", "boolean",
-	"byte", "char", "class", "const", "debugger", "double", "enum",
-	"export", "extends", "final", "float", "goto", "implements", "import",
-	"int", "interface", "long", "native", "package", "private",
-	"protected", "public", "short", "static", "super", "synchronized",
-	"throws", "transient", "volatile",
+	"(error)", "(eof)", "(identifier)", "null", "true", "false",
+	"(number)", "(string)", "(regexp)", "(newline)",
+	"{", "}", "(", ")", "[", "]", ".", ";", ",",
+	"<", ">", "<=", ">=", "==", "!=", "===", "!==",
+	"+", "-", "*", "%", "++", "--", "<<", ">>", ">>>", "&", "|",
+	"^", "!", "~", "&&", "||", "?", ":",
+	"=", "+=", "-=", "*=", "%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=",
+	"/", "/=",
+	"break", "case", "catch", "continue", "debugger", "default", "delete",
+	"do", "else", "finally", "for", "function", "if", "in", "instanceof",
+	"new", "return", "switch", "this", "throw", "try", "typeof", "var",
+	"void", "while", "with",
 };
 
 const char *js_tokentostring(js_Token t)
@@ -450,7 +408,7 @@
 
 			textend(J);
 
-			return findkeyword(J->yytext);
+			return findkeyword(J, J->yytext);
 		}
 
 		if (c == '.') {
--- a/js.h
+++ b/js.h
@@ -93,6 +93,7 @@
 	JS_CASE,
 	JS_CATCH,
 	JS_CONTINUE,
+	JS_DEBUGGER,
 	JS_DEFAULT,
 	JS_DELETE,
 	JS_DO,
@@ -114,40 +115,6 @@
 	JS_VOID,
 	JS_WHILE,
 	JS_WITH,
-
-	/* future reserved words */
-	JS_ABSTRACT,
-	JS_BOOLEAN,
-	JS_BYTE,
-	JS_CHAR,
-	JS_CLASS,
-	JS_CONST,
-	JS_DEBUGGER,
-	JS_DOUBLE,
-	JS_ENUM,
-	JS_EXPORT,
-	JS_EXTENDS,
-	JS_FINAL,
-	JS_FLOAT,
-	JS_GOTO,
-	JS_IMPLEMENTS,
-	JS_IMPORT,
-	JS_INT,
-	JS_INTERFACE,
-	JS_LONG,
-	JS_NATIVE,
-	JS_PACKAGE,
-	JS_PRIVATE,
-	JS_PROTECTED,
-	JS_PUBLIC,
-	JS_SHORT,
-	JS_STATIC,
-	JS_SUPER,
-	JS_SYNCHRONIZED,
-	JS_THROWS,
-	JS_TRANSIENT,
-	JS_VOLATILE,
-
 };
 
 struct js_State
@@ -158,6 +125,7 @@
 	struct { int g, i, m; } yyflags;
 	int yyline;
 	js_Token lasttoken;
+	int strict;
 };
 
 void js_initlex(js_State *J);