Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: src/preparser.h

Issue 7037024: Added preparser strict-mode tests. (Closed)
Patch Set: Address review comment. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/preparse-data.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 // captured the syntax error), and false if a stack-overflow happened 60 // captured the syntax error), and false if a stack-overflow happened
61 // during parsing. 61 // during parsing.
62 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, 62 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner,
63 i::ParserRecorder* log, 63 i::ParserRecorder* log,
64 bool allow_lazy, 64 bool allow_lazy,
65 uintptr_t stack_limit) { 65 uintptr_t stack_limit) {
66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); 66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse();
67 } 67 }
68 68
69 private: 69 private:
70 // These types form an algebra over syntactic categories that is just
71 // rich enough to let us recognize and propagate the constructs that
72 // are either being counted in the preparser data, or is important
73 // to throw the correct syntax error exceptions.
74
70 enum ScopeType { 75 enum ScopeType {
71 kTopLevelScope, 76 kTopLevelScope,
72 kFunctionScope 77 kFunctionScope
73 }; 78 };
74 79
75 // Types that allow us to recognize simple this-property assignments. 80 class Expression;
76 // A simple this-property assignment is a statement on the form 81
77 // "this.propertyName = {primitive constant or function parameter name);" 82 class Identifier {
78 // where propertyName isn't "__proto__". 83 public:
79 // The result is only relevant if the function body contains only 84 static Identifier Default() {
80 // simple this-property assignments. 85 return Identifier(kUnknownIdentifier);
81 86 }
82 enum StatementType { 87 static Identifier Eval() {
83 kUnknownStatement, 88 return Identifier(kEvalIdentifier);
84 kStringLiteralExpressionStatement, 89 }
85 kUseStrictExpressionStatement 90 static Identifier Arguments() {
86 }; 91 return Identifier(kArgumentsIdentifier);
87 92 }
88 enum ExpressionType { 93 static Identifier FutureReserved() {
89 kUnknownExpression, 94 return Identifier(kFutureReservedIdentifier);
90 kIdentifierExpression, // Used to detect labels. 95 }
91 kThisExpression, 96 bool IsEval() { return type_ == kEvalIdentifier; }
92 kThisPropertyExpression, 97 bool IsArguments() { return type_ == kArgumentsIdentifier; }
93 kStringLiteralExpression, 98 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
94 kUseStrictString 99 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
95 }; 100 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
96 101 private:
97 enum IdentifierType { 102 enum Type {
98 kUnknownIdentifier 103 kUnknownIdentifier,
99 }; 104 kFutureReservedIdentifier,
100 105 kEvalIdentifier,
101 enum SourceElementTypes { 106 kArgumentsIdentifier
102 kUnknownSourceElements, 107 };
103 kDirectivePrologue, 108 explicit Identifier(Type type) : type_(type) { }
104 kUseStrictDirective 109 Type type_;
105 }; 110
106 111 friend class Expression;
107 typedef int SourceElements; 112 };
108 typedef int Expression; 113
109 typedef int Statement; 114 // Bits 0 and 1 are used to identify the type of expression:
110 typedef int Identifier; 115 // If bit 0 is set, it's an identifier.
116 // if bit 1 is set, it's a string literal.
117 // If neither is set, it's no particular type, and both set isn't
118 // use yet.
119 // Bit 2 is used to mark the expression as being parenthesized,
120 // so "(foo)" isn't recognized as a pure identifier (and possible label).
121 class Expression {
122 public:
123 static Expression Default() {
124 return Expression(kUnknownExpression);
125 }
126
127 static Expression Identifier(Identifier id) {
128 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift));
129 }
130
131 static Expression StringLiteral() {
132 return Expression(kUnknownStringLiteral);
133 }
134
135 static Expression UseStrictStringLiteral() {
136 return Expression(kUseStrictString);
137 }
138
139 static Expression This() {
140 return Expression(kThisExpression);
141 }
142
143 static Expression ThisProperty() {
144 return Expression(kThisPropertyExpression);
145 }
146
147 static Expression StrictFunction() {
148 return Expression(kStrictFunctionExpression);
149 }
150
151 bool IsIdentifier() {
152 return (code_ & kIdentifierFlag) != 0;
153 }
154
155 // Only works corretly if it is actually an identifier expression.
156 PreParser::Identifier AsIdentifier() {
157 return PreParser::Identifier(
158 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
159 }
160
161 bool IsParenthesized() {
162 // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized.
163 return (code_ & 7) > 4;
164 }
165
166 bool IsRawIdentifier() {
167 return !IsParenthesized() && IsIdentifier();
168 }
169
170 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
171
172 bool IsRawStringLiteral() {
173 return !IsParenthesized() && IsStringLiteral();
174 }
175
176 bool IsUseStrictLiteral() {
177 return (code_ & kStringLiteralMask) == kUseStrictString;
178 }
179
180 bool IsThis() {
181 return code_ == kThisExpression;
182 }
183
184 bool IsThisProperty() {
185 return code_ == kThisPropertyExpression;
186 }
187
188 bool IsStrictFunction() {
189 return code_ == kStrictFunctionExpression;
190 }
191
192 Expression Parenthesize() {
193 int type = code_ & 3;
194 if (type != 0) {
195 // Identifiers and string literals can be parenthesized.
196 // They no longer work as labels or directive prologues,
197 // but are still recognized in other contexts.
198 return Expression(code_ | kParentesizedExpressionFlag);
199 }
200 // For other types of expressions, it's not important to remember
201 // the parentheses.
202 return *this;
203 }
204
205 private:
206 // First two/three bits are used as flags.
207 // Bit 0 and 1 represent identifiers or strings literals, and are
208 // mutually exclusive, but can both be absent.
209 // If bit 0 or 1 are set, bit 2 marks that the expression has
210 // been wrapped in parentheses (a string literal can no longer
211 // be a directive prologue, and an identifier can no longer be
212 // a label.
213 enum {
214 kUnknownExpression = 0,
215 // Identifiers
216 kIdentifierFlag = 1, // Used to detect labels.
217 kIdentifierShift = 3,
218
219 kStringLiteralFlag = 2, // Used to detect directive prologue.
220 kUnknownStringLiteral = kStringLiteralFlag,
221 kUseStrictString = kStringLiteralFlag | 8,
222 kStringLiteralMask = kUseStrictString,
223
224 kParentesizedExpressionFlag = 4, // Only if identifier or string literal.
225
226 // Below here applies if neither identifier nor string literal.
227 kThisExpression = 4,
228 kThisPropertyExpression = 8,
229 kStrictFunctionExpression = 12
230 };
231
232 explicit Expression(int expression_code) : code_(expression_code) { }
233
234 int code_;
235 };
236
237 class Statement {
238 public:
239 static Statement Default() {
240 return Statement(kUnknownStatement);
241 }
242
243 // Creates expression statement from expression.
244 // Preserves being an unparenthesized string literal, possibly
245 // "use strict".
246 static Statement ExpressionStatement(Expression expression) {
247 if (!expression.IsParenthesized()) {
248 if (expression.IsUseStrictLiteral()) {
249 return Statement(kUseStrictExpressionStatement);
250 }
251 if (expression.IsStringLiteral()) {
252 return Statement(kStringLiteralExpressionStatement);
253 }
254 }
255 return Default();
256 }
257
258 bool IsStringLiteral() {
259 return code_ != kUnknownStatement;
260 }
261
262 bool IsUseStrictLiteral() {
263 return code_ == kUseStrictExpressionStatement;
264 }
265
266 private:
267 enum Type {
268 kUnknownStatement,
269 kStringLiteralExpressionStatement,
270 kUseStrictExpressionStatement
271 };
272
273 explicit Statement(Type code) : code_(code) {}
274 Type code_;
275 };
276
277 enum SourceElements {
278 kUnknownSourceElements
279 };
280
111 typedef int Arguments; 281 typedef int Arguments;
112 282
113 class Scope { 283 class Scope {
114 public: 284 public:
115 Scope(Scope** variable, ScopeType type) 285 Scope(Scope** variable, ScopeType type)
116 : variable_(variable), 286 : variable_(variable),
117 prev_(*variable), 287 prev_(*variable),
118 type_(type), 288 type_(type),
119 materialized_literal_count_(0), 289 materialized_literal_count_(0),
120 expected_properties_(0), 290 expected_properties_(0),
(...skipping 25 matching lines...) Expand all
146 316
147 // Private constructor only used in PreParseProgram. 317 // Private constructor only used in PreParseProgram.
148 PreParser(i::JavaScriptScanner* scanner, 318 PreParser(i::JavaScriptScanner* scanner,
149 i::ParserRecorder* log, 319 i::ParserRecorder* log,
150 uintptr_t stack_limit, 320 uintptr_t stack_limit,
151 bool allow_lazy) 321 bool allow_lazy)
152 : scanner_(scanner), 322 : scanner_(scanner),
153 log_(log), 323 log_(log),
154 scope_(NULL), 324 scope_(NULL),
155 stack_limit_(stack_limit), 325 stack_limit_(stack_limit),
326 strict_mode_violation_location_(i::Scanner::Location::invalid()),
327 strict_mode_violation_type_(NULL),
156 stack_overflow_(false), 328 stack_overflow_(false),
157 allow_lazy_(true), 329 allow_lazy_(true),
158 parenthesized_function_(false) { } 330 parenthesized_function_(false) { }
159 331
160 // Preparse the program. Only called in PreParseProgram after creating 332 // Preparse the program. Only called in PreParseProgram after creating
161 // the instance. 333 // the instance.
162 PreParseResult PreParse() { 334 PreParseResult PreParse() {
163 Scope top_scope(&scope_, kTopLevelScope); 335 Scope top_scope(&scope_, kTopLevelScope);
164 bool ok = true; 336 bool ok = true;
165 int start_position = scanner_->peek_location().beg_pos; 337 int start_position = scanner_->peek_location().beg_pos;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } 429 }
258 return scanner_->Next(); 430 return scanner_->Next();
259 } 431 }
260 432
261 bool peek_any_identifier(); 433 bool peek_any_identifier();
262 434
263 void set_strict_mode() { 435 void set_strict_mode() {
264 scope_->set_strict(); 436 scope_->set_strict();
265 } 437 }
266 438
267 bool is_strict_mode() { return scope_->is_strict(); } 439 bool strict_mode() { return scope_->is_strict(); }
268 440
269 void Consume(i::Token::Value token) { Next(); } 441 void Consume(i::Token::Value token) { Next(); }
270 442
271 void Expect(i::Token::Value token, bool* ok) { 443 void Expect(i::Token::Value token, bool* ok) {
272 if (Next() != token) { 444 if (Next() != token) {
273 *ok = false; 445 *ok = false;
274 } 446 }
275 } 447 }
276 448
277 bool Check(i::Token::Value token) { 449 bool Check(i::Token::Value token) {
278 i::Token::Value next = peek(); 450 i::Token::Value next = peek();
279 if (next == token) { 451 if (next == token) {
280 Consume(next); 452 Consume(next);
281 return true; 453 return true;
282 } 454 }
283 return false; 455 return false;
284 } 456 }
285 void ExpectSemicolon(bool* ok); 457 void ExpectSemicolon(bool* ok);
286 458
287 static int Precedence(i::Token::Value tok, bool accept_IN); 459 static int Precedence(i::Token::Value tok, bool accept_IN);
288 460
461 void SetStrictModeViolation(i::Scanner::Location,
462 const char* type,
463 bool *ok);
464
465 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);
466
467 void StrictModeIdentifierViolation(i::Scanner::Location,
468 const char* eval_args_type,
469 Identifier identifier,
470 bool* ok);
471
289 i::JavaScriptScanner* scanner_; 472 i::JavaScriptScanner* scanner_;
290 i::ParserRecorder* log_; 473 i::ParserRecorder* log_;
291 Scope* scope_; 474 Scope* scope_;
292 uintptr_t stack_limit_; 475 uintptr_t stack_limit_;
476 i::Scanner::Location strict_mode_violation_location_;
477 const char* strict_mode_violation_type_;
293 bool stack_overflow_; 478 bool stack_overflow_;
294 bool allow_lazy_; 479 bool allow_lazy_;
295 bool parenthesized_function_; 480 bool parenthesized_function_;
296 }; 481 };
297 } } // v8::preparser 482 } } // v8::preparser
298 483
299 #endif // V8_PREPARSER_H 484 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/preparse-data.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698