Commit 93e9016d authored by barraclough@apple.com's avatar barraclough@apple.com

https://bugs.webkit.org/show_bug.cgi?id=53014

ES5 strict mode keyword restrictions aren't implemented

Reviewed by Oliver Hunt.

The following are future restricted words is strict mode code:
    implements, interface, let, package, private, protected, public, static, yield

Source/JavaScriptCore: 

* parser/JSParser.h:
    - Add RESERVED_IF_STRICT token.
* parser/Keywords.table:
    - Add new future restricted words.
* parser/Lexer.cpp:
(JSC::Lexer::parseIdentifier):
    - Check for RESERVED_IF_STRICT; in nonstrict code this is converted to IDENT.
(JSC::Lexer::lex):
    - Pass strictMode flag to parseIdentifier.
* parser/Lexer.h:
    - parseIdentifier needs a strictMode flag.
* runtime/CommonIdentifiers.h:
    - Add identifiers for new reserved words.

LayoutTests: 

* fast/js/keywords-and-reserved_words-expected.txt: Added.
* fast/js/keywords-and-reserved_words.html: Added.
* fast/js/script-tests/keywords-and-reserved_words.js: Added.
(isKeyword):
(isStrictKeyword):
(classifyIdentifier):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@89109 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9557ccb5
2011-06-16 Gavin Barraclough <barraclough@apple.com>
Reviewed by Oliver Hunt.
https://bugs.webkit.org/show_bug.cgi?id=53014
ES5 strict mode keyword restrictions aren't implemented
The following are future restricted words is strict mode code:
implements, interface, let, package, private, protected, public, static, yield
* fast/js/keywords-and-reserved_words-expected.txt: Added.
* fast/js/keywords-and-reserved_words.html: Added.
* fast/js/script-tests/keywords-and-reserved_words.js: Added.
(isKeyword):
(isStrictKeyword):
(classifyIdentifier):
2011-06-16 Yuta Kitamura <yutak@chromium.org>
Unreviewed, rolling out r89107.
......
This test verifies that keywords and reserved words match those specified in ES5 section 7.6.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS classifyIdentifier("x") is "identifier"
PASS classifyIdentifier("id") is "identifier"
PASS classifyIdentifier("identifier") is "identifier"
PASS classifyIdentifier("keyword") is "identifier"
PASS classifyIdentifier("strict") is "identifier"
PASS classifyIdentifier("use") is "identifier"
PASS classifyIdentifier("abstract") is "identifier"
PASS classifyIdentifier("boolean") is "identifier"
PASS classifyIdentifier("byte") is "identifier"
PASS classifyIdentifier("char") is "identifier"
PASS classifyIdentifier("double") is "identifier"
PASS classifyIdentifier("final") is "identifier"
PASS classifyIdentifier("float") is "identifier"
PASS classifyIdentifier("goto") is "identifier"
PASS classifyIdentifier("int") is "identifier"
PASS classifyIdentifier("long") is "identifier"
PASS classifyIdentifier("native") is "identifier"
PASS classifyIdentifier("short") is "identifier"
PASS classifyIdentifier("synchronized") is "identifier"
PASS classifyIdentifier("throws") is "identifier"
PASS classifyIdentifier("transient") is "identifier"
PASS classifyIdentifier("volatile") is "identifier"
PASS classifyIdentifier("break") is "keyword"
PASS classifyIdentifier("case") is "keyword"
PASS classifyIdentifier("catch") is "keyword"
PASS classifyIdentifier("continue") is "keyword"
PASS classifyIdentifier("debugger") is "keyword"
PASS classifyIdentifier("default") is "keyword"
PASS classifyIdentifier("delete") is "keyword"
PASS classifyIdentifier("do") is "keyword"
PASS classifyIdentifier("else") is "keyword"
PASS classifyIdentifier("finally") is "keyword"
PASS classifyIdentifier("for") is "keyword"
PASS classifyIdentifier("function") is "keyword"
PASS classifyIdentifier("if") is "keyword"
PASS classifyIdentifier("in") is "keyword"
PASS classifyIdentifier("instanceof") is "keyword"
PASS classifyIdentifier("new") is "keyword"
PASS classifyIdentifier("return") is "keyword"
PASS classifyIdentifier("switch") is "keyword"
PASS classifyIdentifier("this") is "keyword"
PASS classifyIdentifier("throw") is "keyword"
PASS classifyIdentifier("try") is "keyword"
PASS classifyIdentifier("typeof") is "keyword"
PASS classifyIdentifier("var") is "keyword"
PASS classifyIdentifier("void") is "keyword"
PASS classifyIdentifier("while") is "keyword"
PASS classifyIdentifier("with") is "keyword"
PASS classifyIdentifier("class") is "keyword"
PASS classifyIdentifier("const") is "keyword"
PASS classifyIdentifier("enum") is "keyword"
PASS classifyIdentifier("export") is "keyword"
PASS classifyIdentifier("extends") is "keyword"
PASS classifyIdentifier("import") is "keyword"
PASS classifyIdentifier("super") is "keyword"
PASS classifyIdentifier("implements") is "strict"
PASS classifyIdentifier("interface") is "strict"
PASS classifyIdentifier("let") is "strict"
PASS classifyIdentifier("package") is "strict"
PASS classifyIdentifier("private") is "strict"
PASS classifyIdentifier("protected") is "strict"
PASS classifyIdentifier("public") is "strict"
PASS classifyIdentifier("static") is "strict"
PASS classifyIdentifier("yield") is "strict"
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="resources/js-test-style.css">
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="script-tests/keywords-and-reserved_words.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
description(
"This test verifies that keywords and reserved words match those specified in ES5 section 7.6."
);
function isKeyword(x)
{
try {
eval("var "+x+";");
} catch(e) {
return true;
}
return false;
}
function isStrictKeyword(x)
{
try {
eval("'use strict'; var "+x+";");
} catch(e) {
return true;
}
return false;
}
function classifyIdentifier(x)
{
if (isKeyword(x)) {
// All non-strict keywords are also keywords in strict code.
if (!isStrictKeyword(x))
return "ERROR";
return "keyword";
}
// Check for strict mode future reserved words.
if (isStrictKeyword(x))
return "strict";
return "identifier";
}
// Not keywords - these are all just identifiers.
shouldBe('classifyIdentifier("x")', '"identifier"');
shouldBe('classifyIdentifier("id")', '"identifier"');
shouldBe('classifyIdentifier("identifier")', '"identifier"');
shouldBe('classifyIdentifier("keyword")', '"identifier"');
shouldBe('classifyIdentifier("strict")', '"identifier"');
shouldBe('classifyIdentifier("use")', '"identifier"');
// These are identifiers that we used to treat as keywords!
shouldBe('classifyIdentifier("abstract")', '"identifier"');
shouldBe('classifyIdentifier("boolean")', '"identifier"');
shouldBe('classifyIdentifier("byte")', '"identifier"');
shouldBe('classifyIdentifier("char")', '"identifier"');
shouldBe('classifyIdentifier("double")', '"identifier"');
shouldBe('classifyIdentifier("final")', '"identifier"');
shouldBe('classifyIdentifier("float")', '"identifier"');
shouldBe('classifyIdentifier("goto")', '"identifier"');
shouldBe('classifyIdentifier("int")', '"identifier"');
shouldBe('classifyIdentifier("long")', '"identifier"');
shouldBe('classifyIdentifier("native")', '"identifier"');
shouldBe('classifyIdentifier("short")', '"identifier"');
shouldBe('classifyIdentifier("synchronized")', '"identifier"');
shouldBe('classifyIdentifier("throws")', '"identifier"');
shouldBe('classifyIdentifier("transient")', '"identifier"');
shouldBe('classifyIdentifier("volatile")', '"identifier"');
// Keywords.
shouldBe('classifyIdentifier("break")', '"keyword"');
shouldBe('classifyIdentifier("case")', '"keyword"');
shouldBe('classifyIdentifier("catch")', '"keyword"');
shouldBe('classifyIdentifier("continue")', '"keyword"');
shouldBe('classifyIdentifier("debugger")', '"keyword"');
shouldBe('classifyIdentifier("default")', '"keyword"');
shouldBe('classifyIdentifier("delete")', '"keyword"');
shouldBe('classifyIdentifier("do")', '"keyword"');
shouldBe('classifyIdentifier("else")', '"keyword"');
shouldBe('classifyIdentifier("finally")', '"keyword"');
shouldBe('classifyIdentifier("for")', '"keyword"');
shouldBe('classifyIdentifier("function")', '"keyword"');
shouldBe('classifyIdentifier("if")', '"keyword"');
shouldBe('classifyIdentifier("in")', '"keyword"');
shouldBe('classifyIdentifier("instanceof")', '"keyword"');
shouldBe('classifyIdentifier("new")', '"keyword"');
shouldBe('classifyIdentifier("return")', '"keyword"');
shouldBe('classifyIdentifier("switch")', '"keyword"');
shouldBe('classifyIdentifier("this")', '"keyword"');
shouldBe('classifyIdentifier("throw")', '"keyword"');
shouldBe('classifyIdentifier("try")', '"keyword"');
shouldBe('classifyIdentifier("typeof")', '"keyword"');
shouldBe('classifyIdentifier("var")', '"keyword"');
shouldBe('classifyIdentifier("void")', '"keyword"');
shouldBe('classifyIdentifier("while")', '"keyword"');
shouldBe('classifyIdentifier("with")', '"keyword"');
// Technically these are "Future Reserved Words"!
shouldBe('classifyIdentifier("class")', '"keyword"');
shouldBe('classifyIdentifier("const")', '"keyword"');
shouldBe('classifyIdentifier("enum")', '"keyword"');
shouldBe('classifyIdentifier("export")', '"keyword"');
shouldBe('classifyIdentifier("extends")', '"keyword"');
shouldBe('classifyIdentifier("import")', '"keyword"');
shouldBe('classifyIdentifier("super")', '"keyword"');
// Future Reserved Words, in strict mode only.
shouldBe('classifyIdentifier("implements")', '"strict"');
shouldBe('classifyIdentifier("interface")', '"strict"');
shouldBe('classifyIdentifier("let")', '"strict"');
shouldBe('classifyIdentifier("package")', '"strict"');
shouldBe('classifyIdentifier("private")', '"strict"');
shouldBe('classifyIdentifier("protected")', '"strict"');
shouldBe('classifyIdentifier("public")', '"strict"');
shouldBe('classifyIdentifier("static")', '"strict"');
shouldBe('classifyIdentifier("yield")', '"strict"');
var successfullyParsed = true;
2011-06-16 Gavin Barraclough <barraclough@apple.com>
Reviewed by Oliver Hunt.
https://bugs.webkit.org/show_bug.cgi?id=53014
ES5 strict mode keyword restrictions aren't implemented
The following are future restricted words is strict mode code:
implements, interface, let, package, private, protected, public, static, yield
* parser/JSParser.h:
- Add RESERVED_IF_STRICT token.
* parser/Keywords.table:
- Add new future restricted words.
* parser/Lexer.cpp:
(JSC::Lexer::parseIdentifier):
- Check for RESERVED_IF_STRICT; in nonstrict code this is converted to IDENT.
(JSC::Lexer::lex):
- Pass strictMode flag to parseIdentifier.
* parser/Lexer.h:
- parseIdentifier needs a strictMode flag.
* runtime/CommonIdentifiers.h:
- Add identifiers for new reserved words.
2011-06-16 Gavin Barraclough <barraclough@apple.com>
Reviewed by Oliver Hunt.
......
......@@ -66,6 +66,7 @@ enum JSTokenType {
SWITCH,
WITH,
RESERVED,
RESERVED_IF_STRICT,
THROW,
TRY,
CATCH,
......
# main keywords
@begin mainTable 41
@begin mainTable 47
# types
null NULLTOKEN
......@@ -43,30 +43,16 @@ extends RESERVED
import RESERVED
super RESERVED
# these words are reserved for future use in the ECMA spec, but not in WinIE
# (see http://bugs.webkit.org/show_bug.cgi?id=6179)
# abstract RESERVED
# boolean RESERVED
# byte RESERVED
# char RESERVED
# double RESERVED
# final RESERVED
# float RESERVED
# goto RESERVED
# implements RESERVED
# int RESERVED
# interface RESERVED
# long RESERVED
# native RESERVED
# package RESERVED
# private RESERVED
# protected RESERVED
# public RESERVED
# short RESERVED
# static RESERVED
# synchronized RESERVED
# throws RESERVED
# transient RESERVED
# volatile RESERVED
# reserved for future use in strict code
implements RESERVED_IF_STRICT
interface RESERVED_IF_STRICT
let RESERVED_IF_STRICT
package RESERVED_IF_STRICT
private RESERVED_IF_STRICT
protected RESERVED_IF_STRICT
public RESERVED_IF_STRICT
static RESERVED_IF_STRICT
yield RESERVED_IF_STRICT
@end
......@@ -405,12 +405,12 @@ inline void Lexer::record16(int c)
record16(UChar(static_cast<unsigned short>(c)));
}
template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* tokenData, unsigned lexType)
template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* tokenData, unsigned lexType, bool strictMode)
{
const ptrdiff_t remaining = m_codeEnd - m_code;
if ((remaining >= maxTokenLength) && !(lexType & IgnoreReservedWords)) {
JSTokenType keyword = parseKeyword<shouldCreateIdentifier>(tokenData);
if (keyword != IDENT) {
if (keyword != IDENT && (keyword != RESERVED_IF_STRICT || strictMode)) {
ASSERT((!shouldCreateIdentifier) || tokenData->ident);
return keyword;
}
......@@ -469,7 +469,10 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIde
if (remaining < maxTokenLength) {
const HashEntry* entry = m_keywordTable.entry(m_globalData, *ident);
ASSERT((remaining < maxTokenLength) || !entry);
return entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT;
if (!entry)
return IDENT;
JSTokenType token = static_cast<JSTokenType>(entry->lexerValue());
return (token != RESERVED_IF_STRICT) || strictMode ? token : IDENT;
}
return IDENT;
}
......@@ -1082,9 +1085,9 @@ inNumberAfterDecimalPoint:
// Fall through into CharacterBackSlash.
case CharacterBackSlash:
if (lexType & DontBuildKeywords)
token = parseIdentifier<false>(tokenData, lexType);
token = parseIdentifier<false>(tokenData, lexType, strictMode);
else
token = parseIdentifier<true>(tokenData, lexType);
token = parseIdentifier<true>(tokenData, lexType, strictMode);
break;
case CharacterLineTerminator:
ASSERT(isLineTerminator(m_current));
......
......@@ -118,7 +118,7 @@ namespace JSC {
enum ShiftType { DoBoundsCheck, DoNotBoundsCheck };
template <int shiftAmount, ShiftType shouldBoundsCheck> void internalShift();
template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType parseKeyword(JSTokenData*);
template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned);
template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned, bool strictMode);
template <bool shouldBuildStrings> ALWAYS_INLINE bool parseString(JSTokenData*, bool strictMode);
ALWAYS_INLINE void parseHex(double& returnValue);
ALWAYS_INLINE bool parseOctal(double& returnValue);
......
......@@ -111,7 +111,16 @@
macro(export) \
macro(extends) \
macro(import) \
macro(super)
macro(super) \
macro(implements) \
macro(interface) \
macro(let) \
macro(package) \
macro(private) \
macro(protected) \
macro(public) \
macro(static) \
macro(yield)
namespace JSC {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment