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,
// that would be compiled lazily anyway, so we skip the preparse step
// in that case too.
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
&& source_length >= FLAG_min_preparse_length) {
if (source->IsExternalTwoByteString()) {
ExternalTwoByteStringUC16CharacterStream stream(
Handle<ExternalTwoByteString>::cast(source), 0, source->length());
pre_data = ParserApi::PartialPreParse(&stream,
extension,
harmony_scoping);
pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
} else {
GenericStringUC16CharacterStream stream(source, 0, source->length());
pre_data = ParserApi::PartialPreParse(&stream,
extension,
harmony_scoping);
pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
}
}
......
......@@ -5217,17 +5217,16 @@ int ScriptDataImpl::ReadNumber(byte** source) {
// Create a Scanner for the preparser to use as input, and preparse the source.
static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
bool allow_lazy,
ParserRecorder* recorder,
bool harmony_scoping) {
int flags,
ParserRecorder* recorder) {
Isolate* isolate = Isolate::Current();
JavaScriptScanner scanner(isolate->unicode_cache());
scanner.SetHarmonyScoping(harmony_scoping);
scanner.SetHarmonyScoping((flags & kHarmonyScoping) != 0);
scanner.Initialize(source);
intptr_t stack_limit = isolate->stack_guard()->real_climit();
if (!preparser::PreParser::PreParseProgram(&scanner,
recorder,
allow_lazy,
flags,
stack_limit)) {
isolate->StackOverflow();
return NULL;
......@@ -5244,25 +5243,28 @@ static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
// even if the preparser data is only used once.
ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
v8::Extension* extension,
bool harmony_scoping) {
int flags) {
bool allow_lazy = FLAG_lazy && (extension == NULL);
if (!allow_lazy) {
// Partial preparsing is only about lazily compiled functions.
// If we don't allow lazy compilation, the log data will be empty.
return NULL;
}
flags |= kAllowLazy;
PartialParserRecorder recorder;
return DoPreParse(source, allow_lazy, &recorder, harmony_scoping);
return DoPreParse(source, flags, &recorder);
}
ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
v8::Extension* extension,
bool harmony_scoping) {
int flags) {
Handle<Script> no_script;
bool allow_lazy = FLAG_lazy && (extension == NULL);
if (FLAG_lazy && (extension == NULL)) {
flags |= kAllowLazy;
}
CompleteParserRecorder recorder;
return DoPreParse(source, allow_lazy, &recorder, harmony_scoping);
return DoPreParse(source, flags, &recorder);
}
......
......@@ -33,6 +33,7 @@
#include "preparse-data-format.h"
#include "preparse-data.h"
#include "scopes.h"
#include "preparser.h"
namespace v8 {
namespace internal {
......@@ -165,13 +166,13 @@ class ParserApi {
// Generic preparser generating full preparse data.
static ScriptDataImpl* PreParse(UC16CharacterStream* source,
v8::Extension* extension,
bool harmony_scoping);
int flags);
// Preparser that only does preprocessing that makes sense if only used
// immediately after.
static ScriptDataImpl* PartialPreParse(UC16CharacterStream* source,
v8::Extension* extension,
bool harmony_scoping);
int flags);
};
// ----------------------------------------------------------------------------
......
......@@ -188,7 +188,7 @@ PreParserData Preparse(UnicodeInputStream* input, size_t max_stack) {
preparser::PreParser::PreParseResult result =
preparser::PreParser::PreParseProgram(&scanner,
&recorder,
true,
internal::kAllowLazy,
stack_limit);
if (result == preparser::PreParser::kPreParseStackOverflow) {
return PreParserData::StackOverflow();
......
......@@ -1361,8 +1361,11 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
// CallRuntime ::
// '%' Identifier Arguments
Expect(i::Token::MOD, CHECK_OK);
if (!allow_natives_syntax_) {
*ok = false;
return Expression::Default();
}
ParseIdentifier(CHECK_OK);
ParseArguments(ok);
......
......@@ -118,9 +118,12 @@ class PreParser {
// during parsing.
static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner,
i::ParserRecorder* log,
bool allow_lazy,
int flags,
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:
......@@ -443,7 +446,8 @@ class PreParser {
PreParser(i::JavaScriptScanner* scanner,
i::ParserRecorder* log,
uintptr_t stack_limit,
bool allow_lazy)
bool allow_lazy,
bool allow_natives_syntax)
: scanner_(scanner),
log_(log),
scope_(NULL),
......@@ -451,7 +455,8 @@ class PreParser {
strict_mode_violation_location_(i::Scanner::Location::invalid()),
strict_mode_violation_type_(NULL),
stack_overflow_(false),
allow_lazy_(true),
allow_lazy_(allow_lazy),
allow_natives_syntax_(allow_natives_syntax),
parenthesized_function_(false),
harmony_scoping_(scanner->HarmonyScoping()) { }
......@@ -614,6 +619,7 @@ class PreParser {
const char* strict_mode_violation_type_;
bool stack_overflow_;
bool allow_lazy_;
bool allow_natives_syntax_;
bool parenthesized_function_;
bool harmony_scoping_;
};
......
......@@ -41,6 +41,17 @@
namespace v8 {
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.
// If c is not a legal hexadecimal character, returns a value < 0.
inline int HexValue(uc32 c) {
......
......@@ -260,10 +260,11 @@ TEST(StandAlonePreParser) {
i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache());
scanner.Initialize(&stream);
int flags = i::kAllowLazy | i::kAllowNativesSyntax;
v8::preparser::PreParser::PreParseResult result =
v8::preparser::PreParser::PreParseProgram(&scanner,
&log,
true,
flags,
stack_limit);
CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
i::ScriptDataImpl data(log.ExtractData());
......@@ -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) {
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