Commit 2bbf3bbe authored by lrn@chromium.org's avatar lrn@chromium.org

Make native syntax an early error in the preparser.

Previously the preparser always accepted natives syntax and let the
real parser throw the syntax error. In ES5, it should be an early error,
so the preparser must catch the error.
The perparser library does not expose parsing for natives syntax, it's
only used internally.

Review URL: http://codereview.chromium.org/8306024

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9660 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5152d2e0
...@@ -480,20 +480,22 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, ...@@ -480,20 +480,22 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
// that would be compiled lazily anyway, so we skip the preparse step // that would be compiled lazily anyway, so we skip the preparse step
// in that case too. // in that case too.
ScriptDataImpl* pre_data = input_pre_data; ScriptDataImpl* pre_data = input_pre_data;
bool harmony_scoping = natives != NATIVES_CODE && FLAG_harmony_scoping; int flags = kNoParsingFlags;
if ((natives == NATIVES_CODE) || FLAG_allow_natives_syntax) {
flags |= kAllowNativesSyntax;
}
if (natives != NATIVES_CODE && FLAG_harmony_scoping) {
flags |= kHarmonyScoping;
}
if (pre_data == NULL if (pre_data == NULL
&& source_length >= FLAG_min_preparse_length) { && source_length >= FLAG_min_preparse_length) {
if (source->IsExternalTwoByteString()) { if (source->IsExternalTwoByteString()) {
ExternalTwoByteStringUC16CharacterStream stream( ExternalTwoByteStringUC16CharacterStream stream(
Handle<ExternalTwoByteString>::cast(source), 0, source->length()); Handle<ExternalTwoByteString>::cast(source), 0, source->length());
pre_data = ParserApi::PartialPreParse(&stream, pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
extension,
harmony_scoping);
} else { } else {
GenericStringUC16CharacterStream stream(source, 0, source->length()); GenericStringUC16CharacterStream stream(source, 0, source->length());
pre_data = ParserApi::PartialPreParse(&stream, pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
extension,
harmony_scoping);
} }
} }
......
...@@ -5217,17 +5217,16 @@ int ScriptDataImpl::ReadNumber(byte** source) { ...@@ -5217,17 +5217,16 @@ int ScriptDataImpl::ReadNumber(byte** source) {
// Create a Scanner for the preparser to use as input, and preparse the source. // Create a Scanner for the preparser to use as input, and preparse the source.
static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
bool allow_lazy, int flags,
ParserRecorder* recorder, ParserRecorder* recorder) {
bool harmony_scoping) {
Isolate* isolate = Isolate::Current(); Isolate* isolate = Isolate::Current();
JavaScriptScanner scanner(isolate->unicode_cache()); JavaScriptScanner scanner(isolate->unicode_cache());
scanner.SetHarmonyScoping(harmony_scoping); scanner.SetHarmonyScoping((flags & kHarmonyScoping) != 0);
scanner.Initialize(source); scanner.Initialize(source);
intptr_t stack_limit = isolate->stack_guard()->real_climit(); intptr_t stack_limit = isolate->stack_guard()->real_climit();
if (!preparser::PreParser::PreParseProgram(&scanner, if (!preparser::PreParser::PreParseProgram(&scanner,
recorder, recorder,
allow_lazy, flags,
stack_limit)) { stack_limit)) {
isolate->StackOverflow(); isolate->StackOverflow();
return NULL; return NULL;
...@@ -5244,25 +5243,28 @@ static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, ...@@ -5244,25 +5243,28 @@ static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
// even if the preparser data is only used once. // even if the preparser data is only used once.
ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source, ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
v8::Extension* extension, v8::Extension* extension,
bool harmony_scoping) { int flags) {
bool allow_lazy = FLAG_lazy && (extension == NULL); bool allow_lazy = FLAG_lazy && (extension == NULL);
if (!allow_lazy) { if (!allow_lazy) {
// Partial preparsing is only about lazily compiled functions. // Partial preparsing is only about lazily compiled functions.
// If we don't allow lazy compilation, the log data will be empty. // If we don't allow lazy compilation, the log data will be empty.
return NULL; return NULL;
} }
flags |= kAllowLazy;
PartialParserRecorder recorder; PartialParserRecorder recorder;
return DoPreParse(source, allow_lazy, &recorder, harmony_scoping); return DoPreParse(source, flags, &recorder);
} }
ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source, ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
v8::Extension* extension, v8::Extension* extension,
bool harmony_scoping) { int flags) {
Handle<Script> no_script; Handle<Script> no_script;
bool allow_lazy = FLAG_lazy && (extension == NULL); if (FLAG_lazy && (extension == NULL)) {
flags |= kAllowLazy;
}
CompleteParserRecorder recorder; CompleteParserRecorder recorder;
return DoPreParse(source, allow_lazy, &recorder, harmony_scoping); return DoPreParse(source, flags, &recorder);
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "preparse-data-format.h" #include "preparse-data-format.h"
#include "preparse-data.h" #include "preparse-data.h"
#include "scopes.h" #include "scopes.h"
#include "preparser.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -165,13 +166,13 @@ class ParserApi { ...@@ -165,13 +166,13 @@ class ParserApi {
// Generic preparser generating full preparse data. // Generic preparser generating full preparse data.
static ScriptDataImpl* PreParse(UC16CharacterStream* source, static ScriptDataImpl* PreParse(UC16CharacterStream* source,
v8::Extension* extension, v8::Extension* extension,
bool harmony_scoping); int flags);
// Preparser that only does preprocessing that makes sense if only used // Preparser that only does preprocessing that makes sense if only used
// immediately after. // immediately after.
static ScriptDataImpl* PartialPreParse(UC16CharacterStream* source, static ScriptDataImpl* PartialPreParse(UC16CharacterStream* source,
v8::Extension* extension, v8::Extension* extension,
bool harmony_scoping); int flags);
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -188,7 +188,7 @@ PreParserData Preparse(UnicodeInputStream* input, size_t max_stack) { ...@@ -188,7 +188,7 @@ PreParserData Preparse(UnicodeInputStream* input, size_t max_stack) {
preparser::PreParser::PreParseResult result = preparser::PreParser::PreParseResult result =
preparser::PreParser::PreParseProgram(&scanner, preparser::PreParser::PreParseProgram(&scanner,
&recorder, &recorder,
true, internal::kAllowLazy,
stack_limit); stack_limit);
if (result == preparser::PreParser::kPreParseStackOverflow) { if (result == preparser::PreParser::kPreParseStackOverflow) {
return PreParserData::StackOverflow(); return PreParserData::StackOverflow();
......
...@@ -1361,8 +1361,11 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { ...@@ -1361,8 +1361,11 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
// CallRuntime :: // CallRuntime ::
// '%' Identifier Arguments // '%' Identifier Arguments
Expect(i::Token::MOD, CHECK_OK); Expect(i::Token::MOD, CHECK_OK);
if (!allow_natives_syntax_) {
*ok = false;
return Expression::Default();
}
ParseIdentifier(CHECK_OK); ParseIdentifier(CHECK_OK);
ParseArguments(ok); ParseArguments(ok);
......
...@@ -118,9 +118,12 @@ class PreParser { ...@@ -118,9 +118,12 @@ class PreParser {
// during parsing. // during parsing.
static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner,
i::ParserRecorder* log, i::ParserRecorder* log,
bool allow_lazy, int flags,
uintptr_t stack_limit) { uintptr_t stack_limit) {
return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); bool allow_lazy = (flags & i::kAllowLazy) != 0;
bool allow_natives_syntax = (flags & i::kAllowNativesSyntax) != 0;
return PreParser(scanner, log, stack_limit,
allow_lazy, allow_natives_syntax).PreParse();
} }
private: private:
...@@ -443,7 +446,8 @@ class PreParser { ...@@ -443,7 +446,8 @@ class PreParser {
PreParser(i::JavaScriptScanner* scanner, PreParser(i::JavaScriptScanner* scanner,
i::ParserRecorder* log, i::ParserRecorder* log,
uintptr_t stack_limit, uintptr_t stack_limit,
bool allow_lazy) bool allow_lazy,
bool allow_natives_syntax)
: scanner_(scanner), : scanner_(scanner),
log_(log), log_(log),
scope_(NULL), scope_(NULL),
...@@ -451,7 +455,8 @@ class PreParser { ...@@ -451,7 +455,8 @@ class PreParser {
strict_mode_violation_location_(i::Scanner::Location::invalid()), strict_mode_violation_location_(i::Scanner::Location::invalid()),
strict_mode_violation_type_(NULL), strict_mode_violation_type_(NULL),
stack_overflow_(false), stack_overflow_(false),
allow_lazy_(true), allow_lazy_(allow_lazy),
allow_natives_syntax_(allow_natives_syntax),
parenthesized_function_(false), parenthesized_function_(false),
harmony_scoping_(scanner->HarmonyScoping()) { } harmony_scoping_(scanner->HarmonyScoping()) { }
...@@ -614,6 +619,7 @@ class PreParser { ...@@ -614,6 +619,7 @@ class PreParser {
const char* strict_mode_violation_type_; const char* strict_mode_violation_type_;
bool stack_overflow_; bool stack_overflow_;
bool allow_lazy_; bool allow_lazy_;
bool allow_natives_syntax_;
bool parenthesized_function_; bool parenthesized_function_;
bool harmony_scoping_; bool harmony_scoping_;
}; };
......
...@@ -41,6 +41,17 @@ ...@@ -41,6 +41,17 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// General collection of bit-flags that can be passed to scanners and
// parsers to signify their (initial) mode of operation.
enum ParsingFlags {
kNoParsingFlags = 0,
kAllowLazy = 1,
kAllowNativesSyntax = 2,
kHarmonyScoping = 4
};
// Returns the value (0 .. 15) of a hexadecimal character c. // Returns the value (0 .. 15) of a hexadecimal character c.
// If c is not a legal hexadecimal character, returns a value < 0. // If c is not a legal hexadecimal character, returns a value < 0.
inline int HexValue(uc32 c) { inline int HexValue(uc32 c) {
......
...@@ -260,10 +260,11 @@ TEST(StandAlonePreParser) { ...@@ -260,10 +260,11 @@ TEST(StandAlonePreParser) {
i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache());
scanner.Initialize(&stream); scanner.Initialize(&stream);
int flags = i::kAllowLazy | i::kAllowNativesSyntax;
v8::preparser::PreParser::PreParseResult result = v8::preparser::PreParser::PreParseResult result =
v8::preparser::PreParser::PreParseProgram(&scanner, v8::preparser::PreParser::PreParseProgram(&scanner,
&log, &log,
true, flags,
stack_limit); stack_limit);
CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
i::ScriptDataImpl data(log.ExtractData()); i::ScriptDataImpl data(log.ExtractData());
...@@ -272,6 +273,43 @@ TEST(StandAlonePreParser) { ...@@ -272,6 +273,43 @@ TEST(StandAlonePreParser) {
} }
TEST(StandAlonePreParserNoNatives) {
v8::V8::Initialize();
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
const char* programs[] = {
"%ArgleBargle(glop);",
"var x = %_IsSmi(42);",
NULL
};
uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
for (int i = 0; programs[i]; i++) {
const char* program = programs[i];
i::Utf8ToUC16CharacterStream stream(
reinterpret_cast<const i::byte*>(program),
static_cast<unsigned>(strlen(program)));
i::CompleteParserRecorder log;
i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache());
scanner.Initialize(&stream);
// Flags don't allow natives syntax.
v8::preparser::PreParser::PreParseResult result =
v8::preparser::PreParser::PreParseProgram(&scanner,
&log,
i::kAllowLazy,
stack_limit);
CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
i::ScriptDataImpl data(log.ExtractData());
// Data contains syntax error.
CHECK(data.has_error());
}
}
TEST(RegressChromium62639) { TEST(RegressChromium62639) {
v8::V8::Initialize(); v8::V8::Initialize();
......
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