blob: ece0cfeaec142d58991fd6037b51f8f9e27d6a2f [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "ast-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "bootstrapper.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010037#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080039#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "runtime.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "string-stream.h"
43
44namespace v8 {
45namespace internal {
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047// PositionStack is used for on-stack allocation of token positions for
48// new expressions. Please look at ParseNewExpression.
49
50class PositionStack {
51 public:
52 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
53 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
54
55 class Element {
56 public:
57 Element(PositionStack* stack, int value) {
58 previous_ = stack->top();
59 value_ = value;
60 stack->set_top(this);
61 }
62
63 private:
64 Element* previous() { return previous_; }
65 int value() { return value_; }
66 friend class PositionStack;
67 Element* previous_;
68 int value_;
69 };
70
71 bool is_empty() { return top_ == NULL; }
72 int pop() {
73 ASSERT(!is_empty());
74 int result = top_->value();
75 top_ = top_->previous();
76 return result;
77 }
78
79 private:
80 Element* top() { return top_; }
81 void set_top(Element* value) { top_ = value; }
82 Element* top_;
83 bool* ok_;
84};
85
86
Steve Blocka7e24c12009-10-30 11:49:00 +000087RegExpBuilder::RegExpBuilder()
Ben Murdoch8b112d22011-06-08 16:22:53 +010088 : zone_(Isolate::Current()->zone()),
89 pending_empty_(false),
90 characters_(NULL),
91 terms_(),
92 alternatives_()
Steve Blocka7e24c12009-10-30 11:49:00 +000093#ifdef DEBUG
Ben Murdoch8b112d22011-06-08 16:22:53 +010094 , last_added_(ADD_NONE)
Steve Blocka7e24c12009-10-30 11:49:00 +000095#endif
96 {}
97
98
99void RegExpBuilder::FlushCharacters() {
100 pending_empty_ = false;
101 if (characters_ != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100102 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 characters_ = NULL;
104 text_.Add(atom);
105 LAST(ADD_ATOM);
106 }
107}
108
109
110void RegExpBuilder::FlushText() {
111 FlushCharacters();
112 int num_text = text_.length();
113 if (num_text == 0) {
114 return;
115 } else if (num_text == 1) {
116 terms_.Add(text_.last());
117 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100118 RegExpText* text = new(zone()) RegExpText();
Steve Blocka7e24c12009-10-30 11:49:00 +0000119 for (int i = 0; i < num_text; i++)
120 text_.Get(i)->AppendToText(text);
121 terms_.Add(text);
122 }
123 text_.Clear();
124}
125
126
127void RegExpBuilder::AddCharacter(uc16 c) {
128 pending_empty_ = false;
129 if (characters_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000130 characters_ = new(zone()) ZoneList<uc16>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 }
132 characters_->Add(c);
133 LAST(ADD_CHAR);
134}
135
136
137void RegExpBuilder::AddEmpty() {
138 pending_empty_ = true;
139}
140
141
142void RegExpBuilder::AddAtom(RegExpTree* term) {
143 if (term->IsEmpty()) {
144 AddEmpty();
145 return;
146 }
147 if (term->IsTextElement()) {
148 FlushCharacters();
149 text_.Add(term);
150 } else {
151 FlushText();
152 terms_.Add(term);
153 }
154 LAST(ADD_ATOM);
155}
156
157
158void RegExpBuilder::AddAssertion(RegExpTree* assert) {
159 FlushText();
160 terms_.Add(assert);
161 LAST(ADD_ASSERT);
162}
163
164
165void RegExpBuilder::NewAlternative() {
166 FlushTerms();
167}
168
169
170void RegExpBuilder::FlushTerms() {
171 FlushText();
172 int num_terms = terms_.length();
173 RegExpTree* alternative;
174 if (num_terms == 0) {
175 alternative = RegExpEmpty::GetInstance();
176 } else if (num_terms == 1) {
177 alternative = terms_.last();
178 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100179 alternative = new(zone()) RegExpAlternative(terms_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 }
181 alternatives_.Add(alternative);
182 terms_.Clear();
183 LAST(ADD_NONE);
184}
185
186
187RegExpTree* RegExpBuilder::ToRegExp() {
188 FlushTerms();
189 int num_alternatives = alternatives_.length();
190 if (num_alternatives == 0) {
191 return RegExpEmpty::GetInstance();
192 }
193 if (num_alternatives == 1) {
194 return alternatives_.last();
195 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100196 return new(zone()) RegExpDisjunction(alternatives_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000197}
198
199
Leon Clarkee46be812010-01-19 14:06:41 +0000200void RegExpBuilder::AddQuantifierToAtom(int min,
201 int max,
202 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 if (pending_empty_) {
204 pending_empty_ = false;
205 return;
206 }
207 RegExpTree* atom;
208 if (characters_ != NULL) {
209 ASSERT(last_added_ == ADD_CHAR);
210 // Last atom was character.
211 Vector<const uc16> char_vector = characters_->ToConstVector();
212 int num_chars = char_vector.length();
213 if (num_chars > 1) {
214 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100215 text_.Add(new(zone()) RegExpAtom(prefix));
Steve Blocka7e24c12009-10-30 11:49:00 +0000216 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
217 }
218 characters_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100219 atom = new(zone()) RegExpAtom(char_vector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 FlushText();
221 } else if (text_.length() > 0) {
222 ASSERT(last_added_ == ADD_ATOM);
223 atom = text_.RemoveLast();
224 FlushText();
225 } else if (terms_.length() > 0) {
226 ASSERT(last_added_ == ADD_ATOM);
227 atom = terms_.RemoveLast();
228 if (atom->max_match() == 0) {
229 // Guaranteed to only match an empty string.
230 LAST(ADD_TERM);
231 if (min == 0) {
232 return;
233 }
234 terms_.Add(atom);
235 return;
236 }
237 } else {
238 // Only call immediately after adding an atom or character!
239 UNREACHABLE();
240 return;
241 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 LAST(ADD_TERM);
244}
245
246
Steve Block9fac8402011-05-12 15:51:54 +0100247Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800248 // Length of symbol cache is the number of identified symbols.
249 // If we are larger than that, or negative, it's not a cached symbol.
250 // This might also happen if there is no preparser symbol data, even
251 // if there is some preparser data.
252 if (static_cast<unsigned>(symbol_id)
253 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100254 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100255 return isolate()->factory()->LookupAsciiSymbol(
256 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100257 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100258 return isolate()->factory()->LookupTwoByteSymbol(
259 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100260 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800261 }
Steve Block9fac8402011-05-12 15:51:54 +0100262 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800263}
264
265
Steve Block9fac8402011-05-12 15:51:54 +0100266Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800267 // Make sure the cache is large enough to hold the symbol identifier.
268 if (symbol_cache_.length() <= symbol_id) {
269 // Increase length to index + 1.
270 symbol_cache_.AddBlock(Handle<String>::null(),
271 symbol_id + 1 - symbol_cache_.length());
272 }
273 Handle<String> result = symbol_cache_.at(symbol_id);
274 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100275 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100276 result = isolate()->factory()->LookupAsciiSymbol(
277 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100278 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100279 result = isolate()->factory()->LookupTwoByteSymbol(
280 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100281 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800282 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100283 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 }
Steve Block44f0eee2011-05-26 01:26:41 +0100285 isolate()->counters()->total_preparse_symbols_skipped()->Increment();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800286 return result;
287}
Steve Blocka7e24c12009-10-30 11:49:00 +0000288
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800289
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100290FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
291 // The current pre-data entry must be a FunctionEntry with the given
292 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100293 if ((function_index_ + FunctionEntry::kSize <= store_.length())
294 && (static_cast<int>(store_[function_index_]) == start)) {
295 int index = function_index_;
296 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100297 return FunctionEntry(store_.SubVector(index,
298 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000299 }
300 return FunctionEntry();
301}
302
303
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100304int ScriptDataImpl::GetSymbolIdentifier() {
305 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100306}
307
308
Iain Merrick9ac36c92010-09-13 15:29:50 +0100309bool ScriptDataImpl::SanityCheck() {
310 // Check that the header data is valid and doesn't specify
311 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800312 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
313 if (magic() != PreparseDataConstants::kMagicNumber) return false;
314 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100315 if (has_error()) {
316 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800317 if (store_.length() <= PreparseDataConstants::kHeaderSize
318 + PreparseDataConstants::kMessageTextPos) {
319 return false;
320 }
321 if (Read(PreparseDataConstants::kMessageStartPos) >
322 Read(PreparseDataConstants::kMessageEndPos)) {
323 return false;
324 }
325 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
326 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100327 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800328 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
329 return false;
330 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100331 int length = static_cast<int>(Read(pos));
332 if (length < 0) return false;
333 pos += 1 + length;
334 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800335 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
336 return false;
337 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100338 return true;
339 }
340 // Check that the space allocated for function entries is sane.
341 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800342 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100343 if (functions_size < 0) return false;
344 if (functions_size % FunctionEntry::kSize != 0) return false;
345 // Check that the count of symbols is non-negative.
346 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800347 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100348 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100349 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100350 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800351 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100352 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 return true;
354}
355
356
Steve Block59151502010-09-22 15:07:15 +0100357
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100358const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 int length = start[0];
360 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100361 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000362 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100363 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 result[length] = '\0';
365 if (chars != NULL) *chars = length;
366 return result;
367}
368
Steve Blocka7e24c12009-10-30 11:49:00 +0000369Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800370 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
371 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000372 return Scanner::Location(beg_pos, end_pos);
373}
374
375
376const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800377 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100378 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000379}
380
381
382Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800383 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100385 // Position after text found by skipping past length field and
386 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800387 int pos = PreparseDataConstants::kMessageTextPos + 1
388 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 for (int i = 0; i < arg_count; i++) {
390 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100391 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 pos += count + 1;
393 }
394 return Vector<const char*>(array, arg_count);
395}
396
397
398unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800399 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000400}
401
402
403unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800404 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000405}
406
407
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800408Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100409 Scope* result = new(zone()) Scope(parent, type);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 result->Initialize(inside_with);
411 return result;
412}
413
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000414
Steve Blocka7e24c12009-10-30 11:49:00 +0000415// ----------------------------------------------------------------------------
416// Target is a support class to facilitate manipulation of the
417// Parser's target_stack_ (the stack of potential 'break' and
418// 'continue' statement targets). Upon construction, a new target is
419// added; it is removed upon destruction.
420
421class Target BASE_EMBEDDED {
422 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800423 Target(Target** variable, AstNode* node)
424 : variable_(variable), node_(node), previous_(*variable) {
425 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 }
427
428 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800429 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 }
431
432 Target* previous() { return previous_; }
433 AstNode* node() { return node_; }
434
435 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800436 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 AstNode* node_;
438 Target* previous_;
439};
440
441
442class TargetScope BASE_EMBEDDED {
443 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800444 explicit TargetScope(Target** variable)
445 : variable_(variable), previous_(*variable) {
446 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 }
448
449 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800450 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 }
452
453 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800454 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 Target* previous_;
456};
457
458
459// ----------------------------------------------------------------------------
460// LexicalScope is a support class to facilitate manipulation of the
461// Parser's scope stack. The constructor sets the parser's top scope
462// to the incoming scope, and the destructor resets it.
Steve Block44f0eee2011-05-26 01:26:41 +0100463//
Ben Murdoch8b112d22011-06-08 16:22:53 +0100464// Additionally, it stores transient information used during parsing.
Steve Block44f0eee2011-05-26 01:26:41 +0100465// These scopes are not kept around after parsing or referenced by syntax
466// trees so they can be stack-allocated and hence used by the pre-parser.
Steve Blocka7e24c12009-10-30 11:49:00 +0000467
468class LexicalScope BASE_EMBEDDED {
469 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100470 LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
471 ~LexicalScope();
472
473 int NextMaterializedLiteralIndex() {
474 int next_index =
475 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
476 materialized_literal_count_++;
477 return next_index;
478 }
479 int materialized_literal_count() { return materialized_literal_count_; }
480
481 void SetThisPropertyAssignmentInfo(
482 bool only_simple_this_property_assignments,
483 Handle<FixedArray> this_property_assignments) {
484 only_simple_this_property_assignments_ =
485 only_simple_this_property_assignments;
486 this_property_assignments_ = this_property_assignments;
487 }
488 bool only_simple_this_property_assignments() {
489 return only_simple_this_property_assignments_;
490 }
491 Handle<FixedArray> this_property_assignments() {
492 return this_property_assignments_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000493 }
494
Steve Block44f0eee2011-05-26 01:26:41 +0100495 void AddProperty() { expected_property_count_++; }
496 int expected_property_count() { return expected_property_count_; }
497
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100499 // Captures the number of literals that need materialization in the
500 // function. Includes regexp literals, and boilerplate for object
501 // and array literals.
502 int materialized_literal_count_;
503
504 // Properties count estimation.
505 int expected_property_count_;
506
507 // Keeps track of assignments to properties of this. Used for
508 // optimizing constructors.
509 bool only_simple_this_property_assignments_;
510 Handle<FixedArray> this_property_assignments_;
511
Steve Block44f0eee2011-05-26 01:26:41 +0100512 // Bookkeeping
513 Parser* parser_;
514 // Previous values
515 LexicalScope* lexical_scope_parent_;
516 Scope* previous_scope_;
517 int previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100518 unsigned previous_ast_node_id_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000519};
520
Steve Block44f0eee2011-05-26 01:26:41 +0100521
522LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
523 : materialized_literal_count_(0),
524 expected_property_count_(0),
525 only_simple_this_property_assignments_(false),
526 this_property_assignments_(isolate->factory()->empty_fixed_array()),
Steve Block44f0eee2011-05-26 01:26:41 +0100527 parser_(parser),
528 lexical_scope_parent_(parser->lexical_scope_),
529 previous_scope_(parser->top_scope_),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100530 previous_with_nesting_level_(parser->with_nesting_level_),
531 previous_ast_node_id_(isolate->ast_node_id()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100532 parser->top_scope_ = scope;
533 parser->lexical_scope_ = this;
534 parser->with_nesting_level_ = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100535 isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1);
Steve Block44f0eee2011-05-26 01:26:41 +0100536}
537
538
539LexicalScope::~LexicalScope() {
Steve Block44f0eee2011-05-26 01:26:41 +0100540 parser_->top_scope_ = previous_scope_;
541 parser_->lexical_scope_ = lexical_scope_parent_;
542 parser_->with_nesting_level_ = previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100543 parser_->isolate()->set_ast_node_id(previous_ast_node_id_);
Steve Block44f0eee2011-05-26 01:26:41 +0100544}
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547// ----------------------------------------------------------------------------
548// The CHECK_OK macro is a convenient macro to enforce error
549// handling for functions that may fail (by returning !*ok).
550//
551// CAUTION: This macro appends extra statements after a call,
552// thus it must never be used where only a single statement
553// is correct (e.g. an if statement branch w/o braces)!
554
555#define CHECK_OK ok); \
556 if (!*ok) return NULL; \
557 ((void)0
558#define DUMMY ) // to make indentation work
559#undef DUMMY
560
561#define CHECK_FAILED /**/); \
562 if (failed_) return NULL; \
563 ((void)0
564#define DUMMY ) // to make indentation work
565#undef DUMMY
566
567// ----------------------------------------------------------------------------
568// Implementation of Parser
569
570Parser::Parser(Handle<Script> script,
571 bool allow_natives_syntax,
572 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000573 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100574 : isolate_(script->GetIsolate()),
575 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800576 script_(script),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100577 scanner_(isolate_->unicode_cache()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000578 top_scope_(NULL),
579 with_nesting_level_(0),
Steve Block44f0eee2011-05-26 01:26:41 +0100580 lexical_scope_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000581 target_stack_(NULL),
582 allow_natives_syntax_(allow_natives_syntax),
583 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100584 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100585 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100586 stack_overflow_(false),
587 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100588 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000589}
590
591
Steve Blocka7e24c12009-10-30 11:49:00 +0000592FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100593 bool in_global_context,
594 StrictModeFlag strict_mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000595 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000596
Steve Block44f0eee2011-05-26 01:26:41 +0100597 HistogramTimerScope timer(isolate()->counters()->parse());
598 isolate()->counters()->total_parse_size()->Increment(source->length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000599 fni_ = new(zone()) FuncNameInferrer(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000600
601 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100602 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100603 if (source->IsExternalTwoByteString()) {
604 // Notice that the stream is destroyed at the end of the branch block.
605 // The last line of the blocks can't be moved outside, even though they're
606 // identical calls.
607 ExternalTwoByteStringUC16CharacterStream stream(
608 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100609 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100610 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 } else {
612 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100613 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100614 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100615 }
616}
617
618
619FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
620 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100621 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100622 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000623 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100624 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000625
626 // Compute the parsing mode.
627 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
628 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
629
630 Scope::Type type =
631 in_global_context
632 ? Scope::GLOBAL_SCOPE
633 : Scope::EVAL_SCOPE;
Steve Block44f0eee2011-05-26 01:26:41 +0100634 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000635
636 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800637 { Scope* scope = NewScope(top_scope_, type, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +0100638 LexicalScope lexical_scope(this, scope, isolate());
Steve Block1e0659c2011-05-24 12:43:12 +0100639 if (strict_mode == kStrictMode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100640 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100641 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000642 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100644 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800645 ParseSourceElements(body, Token::EOS, &ok);
Steve Block44f0eee2011-05-26 01:26:41 +0100646 if (ok && top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100647 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
648 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 if (ok) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100650 result = new(zone()) FunctionLiteral(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000651 isolate(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 no_name,
653 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800654 body,
Steve Block44f0eee2011-05-26 01:26:41 +0100655 lexical_scope.materialized_literal_count(),
656 lexical_scope.expected_property_count(),
657 lexical_scope.only_simple_this_property_assignments(),
658 lexical_scope.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 0,
660 0,
661 source->length(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000662 FunctionLiteral::ANONYMOUS_EXPRESSION,
663 false); // Does not have duplicate parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100665 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 }
667 }
668
669 // Make sure the target stack is empty.
670 ASSERT(target_stack_ == NULL);
671
672 // If there was a syntax error we have to get rid of the AST
673 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000675 return result;
676}
677
Steve Block44f0eee2011-05-26 01:26:41 +0100678FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000679 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100680 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100681 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100682 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000683
Steve Block44f0eee2011-05-26 01:26:41 +0100684 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100685 // Initialize parser state.
686 source->TryFlatten();
687 if (source->IsExternalTwoByteString()) {
688 ExternalTwoByteStringUC16CharacterStream stream(
689 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100690 shared_info->start_position(),
691 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100692 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
693 return result;
694 } else {
695 GenericStringUC16CharacterStream stream(source,
Steve Block44f0eee2011-05-26 01:26:41 +0100696 shared_info->start_position(),
697 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
699 return result;
700 }
701}
702
703
Steve Block44f0eee2011-05-26 01:26:41 +0100704FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705 UC16CharacterStream* source,
706 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100707 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100708 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100709 ASSERT(target_stack_ == NULL);
710
Steve Block44f0eee2011-05-26 01:26:41 +0100711 Handle<String> name(String::cast(shared_info->name()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000712 fni_ = new(zone()) FuncNameInferrer(isolate());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100713 fni_->PushEnclosingName(name);
714
Steve Blocka7e24c12009-10-30 11:49:00 +0000715 mode_ = PARSE_EAGERLY;
716
717 // Place holder for the result.
718 FunctionLiteral* result = NULL;
719
720 {
721 // Parse the function literal.
Steve Block44f0eee2011-05-26 01:26:41 +0100722 Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
723 if (!info->closure().is_null()) {
724 scope = Scope::DeserializeScopeChain(info, scope);
725 }
726 LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000727
Steve Block44f0eee2011-05-26 01:26:41 +0100728 if (shared_info->strict_mode()) {
729 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100730 }
731
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000732 FunctionLiteral::Type type = shared_info->is_expression()
733 ? (shared_info->is_anonymous()
734 ? FunctionLiteral::ANONYMOUS_EXPRESSION
735 : FunctionLiteral::NAMED_EXPRESSION)
736 : FunctionLiteral::DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000737 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100738 result = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000739 false, // Strict mode name already checked.
740 RelocInfo::kNoPosition,
741 type,
742 &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 // Make sure the results agree.
744 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 }
746
747 // Make sure the target stack is empty.
748 ASSERT(target_stack_ == NULL);
749
750 // If there was a stack overflow we have to get rid of AST and it is
751 // not safe to do before scope has been deleted.
752 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100754 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100755 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100756 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100757 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 }
759 return result;
760}
761
Ben Murdochf87a2032010-10-22 12:50:53 +0100762
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800763Handle<String> Parser::GetSymbol(bool* ok) {
764 int symbol_id = -1;
765 if (pre_data() != NULL) {
766 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000767 }
Steve Block9fac8402011-05-12 15:51:54 +0100768 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000769}
Steve Blocka7e24c12009-10-30 11:49:00 +0000770
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800771
Steve Blocka7e24c12009-10-30 11:49:00 +0000772void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100773 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000774 ReportMessageAt(source_location, type, args);
775}
776
777
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800778void Parser::ReportMessageAt(Scanner::Location source_location,
779 const char* type,
780 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000781 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100782 source_location.beg_pos,
783 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100784 Factory* factory = isolate()->factory();
785 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100787 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100788 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000789 }
Steve Block44f0eee2011-05-26 01:26:41 +0100790 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
791 Handle<Object> result = factory->NewSyntaxError(type, array);
792 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000793}
794
795
Ben Murdochb8e0da22011-05-16 14:20:40 +0100796void Parser::ReportMessageAt(Scanner::Location source_location,
797 const char* type,
798 Vector<Handle<String> > args) {
799 MessageLocation location(script_,
800 source_location.beg_pos,
801 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100802 Factory* factory = isolate()->factory();
803 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100804 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100805 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100806 }
Steve Block44f0eee2011-05-26 01:26:41 +0100807 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
808 Handle<Object> result = factory->NewSyntaxError(type, array);
809 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100810}
811
812
Steve Blocka7e24c12009-10-30 11:49:00 +0000813// Base class containing common code for the different finder classes used by
814// the parser.
815class ParserFinder {
816 protected:
817 ParserFinder() {}
818 static Assignment* AsAssignment(Statement* stat) {
819 if (stat == NULL) return NULL;
820 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
821 if (exp_stat == NULL) return NULL;
822 return exp_stat->expression()->AsAssignment();
823 }
824};
825
826
827// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000828// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000829class InitializationBlockFinder : public ParserFinder {
830 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000831 // We find and mark the initialization blocks in top level
832 // non-looping code only. This is because the optimization prevents
833 // reuse of the map transitions, so it should be used only for code
834 // that will only be run once.
835 InitializationBlockFinder(Scope* top_scope, Target* target)
836 : enabled_(top_scope->DeclarationScope()->is_global_scope() &&
837 !IsLoopTarget(target)),
838 first_in_block_(NULL),
839 last_in_block_(NULL),
840 block_size_(0) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000841
842 ~InitializationBlockFinder() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000843 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000844 if (InBlock()) EndBlock();
845 }
846
847 void Update(Statement* stat) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000848 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 Assignment* assignment = AsAssignment(stat);
850 if (InBlock()) {
851 if (BlockContinues(assignment)) {
852 UpdateBlock(assignment);
853 } else {
854 EndBlock();
855 }
856 }
857 if (!InBlock() && (assignment != NULL) &&
858 (assignment->op() == Token::ASSIGN)) {
859 StartBlock(assignment);
860 }
861 }
862
863 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800864 // The minimum number of contiguous assignment that will
865 // be treated as an initialization block. Benchmarks show that
866 // the overhead exceeds the savings below this limit.
867 static const int kMinInitializationBlock = 3;
868
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000869 static bool IsLoopTarget(Target* target) {
870 while (target != NULL) {
871 if (target->node()->AsIterationStatement() != NULL) return true;
872 target = target->previous();
873 }
874 return false;
875 }
876
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 // Returns true if the expressions appear to denote the same object.
878 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000879 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000880 static bool SameObject(Expression* e1, Expression* e2) {
881 VariableProxy* v1 = e1->AsVariableProxy();
882 VariableProxy* v2 = e2->AsVariableProxy();
883 if (v1 != NULL && v2 != NULL) {
884 return v1->name()->Equals(*v2->name());
885 }
886 Property* p1 = e1->AsProperty();
887 Property* p2 = e2->AsProperty();
888 if ((p1 == NULL) || (p2 == NULL)) return false;
889 Literal* key1 = p1->key()->AsLiteral();
890 Literal* key2 = p2->key()->AsLiteral();
891 if ((key1 == NULL) || (key2 == NULL)) return false;
892 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
893 return false;
894 }
895 String* name1 = String::cast(*key1->handle());
896 String* name2 = String::cast(*key2->handle());
897 if (!name1->Equals(name2)) return false;
898 return SameObject(p1->obj(), p2->obj());
899 }
900
901 // Returns true if the expressions appear to denote different properties
902 // of the same object.
903 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
904 Property* p1 = e1->AsProperty();
905 Property* p2 = e2->AsProperty();
906 if ((p1 == NULL) || (p2 == NULL)) return false;
907 return SameObject(p1->obj(), p2->obj());
908 }
909
910 bool BlockContinues(Assignment* assignment) {
911 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
912 if (assignment->op() != Token::ASSIGN) return false;
913 return PropertyOfSameObject(first_in_block_->target(),
914 assignment->target());
915 }
916
917 void StartBlock(Assignment* assignment) {
918 first_in_block_ = assignment;
919 last_in_block_ = assignment;
920 block_size_ = 1;
921 }
922
923 void UpdateBlock(Assignment* assignment) {
924 last_in_block_ = assignment;
925 ++block_size_;
926 }
927
928 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800929 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000930 first_in_block_->mark_block_start();
931 last_in_block_->mark_block_end();
932 }
933 last_in_block_ = first_in_block_ = NULL;
934 block_size_ = 0;
935 }
936
937 bool InBlock() { return first_in_block_ != NULL; }
938
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000939 const bool enabled_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000940 Assignment* first_in_block_;
941 Assignment* last_in_block_;
942 int block_size_;
943
944 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
945};
946
947
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000948// A ThisNamedPropertyAssignmentFinder finds and marks statements of the form
Steve Blocka7e24c12009-10-30 11:49:00 +0000949// this.x = ...;, where x is a named property. It also determines whether a
950// function contains only assignments of this type.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000951class ThisNamedPropertyAssignmentFinder : public ParserFinder {
Steve Blocka7e24c12009-10-30 11:49:00 +0000952 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000953 explicit ThisNamedPropertyAssignmentFinder(Isolate* isolate)
Steve Block44f0eee2011-05-26 01:26:41 +0100954 : isolate_(isolate),
955 only_simple_this_property_assignments_(true),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000956 names_(0),
957 assigned_arguments_(0),
958 assigned_constants_(0) {
959 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000960
961 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000962 // Bail out if function already has property assignment that are
963 // not simple this property assignments.
964 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000965 return;
966 }
967
968 // Check whether this statement is of the form this.x = ...;
969 Assignment* assignment = AsAssignment(stat);
970 if (IsThisPropertyAssignment(assignment)) {
971 HandleThisPropertyAssignment(scope, assignment);
972 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 only_simple_this_property_assignments_ = false;
974 }
975 }
976
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 // Returns whether only statements of the form this.x = y; where y is either a
978 // constant or a function argument was encountered.
979 bool only_simple_this_property_assignments() {
980 return only_simple_this_property_assignments_;
981 }
982
983 // Returns a fixed array containing three elements for each assignment of the
984 // form this.x = y;
985 Handle<FixedArray> GetThisPropertyAssignments() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000986 if (names_.is_empty()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100987 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +0000988 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000989 ASSERT_EQ(names_.length(), assigned_arguments_.length());
990 ASSERT_EQ(names_.length(), assigned_constants_.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 Handle<FixedArray> assignments =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000992 isolate_->factory()->NewFixedArray(names_.length() * 3);
993 for (int i = 0; i < names_.length(); ++i) {
994 assignments->set(i * 3, *names_[i]);
995 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_[i]));
996 assignments->set(i * 3 + 2, *assigned_constants_[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +0000997 }
998 return assignments;
999 }
1000
1001 private:
1002 bool IsThisPropertyAssignment(Assignment* assignment) {
1003 if (assignment != NULL) {
1004 Property* property = assignment->target()->AsProperty();
1005 return assignment->op() == Token::ASSIGN
1006 && property != NULL
1007 && property->obj()->AsVariableProxy() != NULL
1008 && property->obj()->AsVariableProxy()->is_this();
1009 }
1010 return false;
1011 }
1012
1013 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +01001014 // Check that the property assigned to is a named property, which is not
1015 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 Property* property = assignment->target()->AsProperty();
1017 ASSERT(property != NULL);
1018 Literal* literal = property->key()->AsLiteral();
1019 uint32_t dummy;
1020 if (literal != NULL &&
1021 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001022 !String::cast(*(literal->handle()))->Equals(
1023 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1025 Handle<String> key = Handle<String>::cast(literal->handle());
1026
1027 // Check whether the value assigned is either a constant or matches the
1028 // name of one of the arguments to the function.
1029 if (assignment->value()->AsLiteral() != NULL) {
1030 // Constant assigned.
1031 Literal* literal = assignment->value()->AsLiteral();
1032 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001033 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001034 } else if (assignment->value()->AsVariableProxy() != NULL) {
1035 // Variable assigned.
1036 Handle<String> name =
1037 assignment->value()->AsVariableProxy()->name();
1038 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 for (int i = 0; i < scope->num_parameters(); i++) {
1040 if (*scope->parameter(i)->name() == *name) {
1041 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001042 AssignmentFromParameter(key, i);
1043 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 }
1045 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 }
1047 }
Steve Blockd0582a62009-12-15 09:54:21 +00001048 // It is not a simple "this.x = value;" assignment with a constant
1049 // or parameter value.
1050 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001051 }
1052
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001053
1054
1055
1056 // We will potentially reorder the property assignments, so they must be
1057 // simple enough that the ordering does not matter.
Steve Blocka7e24c12009-10-30 11:49:00 +00001058 void AssignmentFromParameter(Handle<String> name, int index) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001059 EnsureInitialized();
1060 for (int i = 0; i < names_.length(); ++i) {
1061 if (name->Equals(*names_[i])) {
1062 assigned_arguments_[i] = index;
1063 assigned_constants_[i] = isolate_->factory()->undefined_value();
1064 return;
1065 }
1066 }
1067 names_.Add(name);
1068 assigned_arguments_.Add(index);
1069 assigned_constants_.Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001070 }
1071
1072 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001073 EnsureInitialized();
1074 for (int i = 0; i < names_.length(); ++i) {
1075 if (name->Equals(*names_[i])) {
1076 assigned_arguments_[i] = -1;
1077 assigned_constants_[i] = value;
1078 return;
1079 }
1080 }
1081 names_.Add(name);
1082 assigned_arguments_.Add(-1);
1083 assigned_constants_.Add(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001084 }
1085
Steve Blockd0582a62009-12-15 09:54:21 +00001086 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001087 // The this assignment is not a simple one.
1088 only_simple_this_property_assignments_ = false;
1089 }
1090
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001091 void EnsureInitialized() {
1092 if (names_.capacity() == 0) {
1093 ASSERT(assigned_arguments_.capacity() == 0);
1094 ASSERT(assigned_constants_.capacity() == 0);
1095 names_.Initialize(4);
1096 assigned_arguments_.Initialize(4);
1097 assigned_constants_.Initialize(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001098 }
1099 }
1100
Steve Block44f0eee2011-05-26 01:26:41 +01001101 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001102 bool only_simple_this_property_assignments_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001103 ZoneStringList names_;
1104 ZoneList<int> assigned_arguments_;
1105 ZoneObjectList assigned_constants_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001106};
1107
1108
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001109void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001110 int end_token,
1111 bool* ok) {
1112 // SourceElements ::
1113 // (Statement)* <end_token>
1114
1115 // Allocate a target stack to use for this set of source
1116 // elements. This way, all scripts and functions get their own
1117 // target stack thus avoiding illegal breaks and continues across
1118 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001119 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001120
1121 ASSERT(processor != NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001122 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1123 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001124 bool directive_prologue = true; // Parsing directive prologue.
1125
Steve Blocka7e24c12009-10-30 11:49:00 +00001126 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001127 if (directive_prologue && peek() != Token::STRING) {
1128 directive_prologue = false;
1129 }
1130
1131 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001132
1133 Statement* stat;
1134 if (peek() == Token::FUNCTION) {
1135 // FunctionDeclaration is only allowed in the context of SourceElements
1136 // (Ecma 262 5th Edition, clause 14):
1137 // SourceElement:
1138 // Statement
1139 // FunctionDeclaration
1140 // Common language extension is to allow function declaration in place
1141 // of any statement. This language extension is disabled in strict mode.
1142 stat = ParseFunctionDeclaration(CHECK_OK);
1143 } else {
1144 stat = ParseStatement(NULL, CHECK_OK);
1145 }
Steve Block1e0659c2011-05-24 12:43:12 +01001146
1147 if (stat == NULL || stat->IsEmpty()) {
1148 directive_prologue = false; // End of directive prologue.
1149 continue;
1150 }
1151
1152 if (directive_prologue) {
1153 // A shot at a directive.
1154 ExpressionStatement *e_stat;
1155 Literal *literal;
1156 // Still processing directive prologue?
1157 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1158 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1159 literal->handle()->IsString()) {
1160 Handle<String> directive = Handle<String>::cast(literal->handle());
1161
1162 // Check "use strict" directive (ES5 14.1).
Steve Block44f0eee2011-05-26 01:26:41 +01001163 if (!top_scope_->is_strict_mode() &&
1164 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001165 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001166 isolate()->heap()->use_strict()->length() + 2) {
1167 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +01001168 // "use strict" is the only directive for now.
1169 directive_prologue = false;
1170 }
1171 } else {
1172 // End of the directive prologue.
1173 directive_prologue = false;
1174 }
1175 }
1176
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001177 block_finder.Update(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 // Find and mark all assignments to named properties in this (this.x =)
1179 if (top_scope_->is_function_scope()) {
1180 this_property_assignment_finder.Update(top_scope_, stat);
1181 }
1182 processor->Add(stat);
1183 }
1184
1185 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001186 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001187 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001188 this_property_assignment_finder.only_simple_this_property_assignments()
1189 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001190 if (only_simple_this_property_assignments) {
Steve Block44f0eee2011-05-26 01:26:41 +01001191 lexical_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001192 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001193 this_property_assignment_finder.GetThisPropertyAssignments());
1194 }
1195 }
1196 return 0;
1197}
1198
1199
1200Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1201 // Statement ::
1202 // Block
1203 // VariableStatement
1204 // EmptyStatement
1205 // ExpressionStatement
1206 // IfStatement
1207 // IterationStatement
1208 // ContinueStatement
1209 // BreakStatement
1210 // ReturnStatement
1211 // WithStatement
1212 // LabelledStatement
1213 // SwitchStatement
1214 // ThrowStatement
1215 // TryStatement
1216 // DebuggerStatement
1217
1218 // Note: Since labels can only be used by 'break' and 'continue'
1219 // statements, which themselves are only valid within blocks,
1220 // iterations or 'switch' statements (i.e., BreakableStatements),
1221 // labels can be simply ignored in all other cases; except for
1222 // trivial labeled break statements 'label: break label' which is
1223 // parsed into an empty statement.
1224
1225 // Keep the source position of the statement
1226 int statement_pos = scanner().peek_location().beg_pos;
1227 Statement* stmt = NULL;
1228 switch (peek()) {
1229 case Token::LBRACE:
1230 return ParseBlock(labels, ok);
1231
1232 case Token::CONST: // fall through
1233 case Token::VAR:
1234 stmt = ParseVariableStatement(ok);
1235 break;
1236
1237 case Token::SEMICOLON:
1238 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001239 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001240
1241 case Token::IF:
1242 stmt = ParseIfStatement(labels, ok);
1243 break;
1244
1245 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001246 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001247 break;
1248
1249 case Token::WHILE:
1250 stmt = ParseWhileStatement(labels, ok);
1251 break;
1252
1253 case Token::FOR:
1254 stmt = ParseForStatement(labels, ok);
1255 break;
1256
1257 case Token::CONTINUE:
1258 stmt = ParseContinueStatement(ok);
1259 break;
1260
1261 case Token::BREAK:
1262 stmt = ParseBreakStatement(labels, ok);
1263 break;
1264
1265 case Token::RETURN:
1266 stmt = ParseReturnStatement(ok);
1267 break;
1268
1269 case Token::WITH:
1270 stmt = ParseWithStatement(labels, ok);
1271 break;
1272
1273 case Token::SWITCH:
1274 stmt = ParseSwitchStatement(labels, ok);
1275 break;
1276
1277 case Token::THROW:
1278 stmt = ParseThrowStatement(ok);
1279 break;
1280
1281 case Token::TRY: {
1282 // NOTE: It is somewhat complicated to have labels on
1283 // try-statements. When breaking out of a try-finally statement,
1284 // one must take great care not to treat it as a
1285 // fall-through. It is much easier just to wrap the entire
1286 // try-statement in a statement block and put the labels there
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001287 Block* result = new(zone()) Block(isolate(), labels, 1, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001288 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 TryStatement* statement = ParseTryStatement(CHECK_OK);
1290 if (statement) {
1291 statement->set_statement_pos(statement_pos);
1292 }
1293 if (result) result->AddStatement(statement);
1294 return result;
1295 }
1296
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001297 case Token::FUNCTION: {
1298 // In strict mode, FunctionDeclaration is only allowed in the context
1299 // of SourceElements.
Steve Block44f0eee2011-05-26 01:26:41 +01001300 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001301 ReportMessageAt(scanner().peek_location(), "strict_function",
1302 Vector<const char*>::empty());
1303 *ok = false;
1304 return NULL;
1305 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001306 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001307 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001308
Steve Blocka7e24c12009-10-30 11:49:00 +00001309 case Token::DEBUGGER:
1310 stmt = ParseDebuggerStatement(ok);
1311 break;
1312
1313 default:
1314 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1315 }
1316
1317 // Store the source position of the statement
1318 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1319 return stmt;
1320}
1321
1322
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001323VariableProxy* Parser::Declare(Handle<String> name,
1324 Variable::Mode mode,
1325 FunctionLiteral* fun,
1326 bool resolve,
1327 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001328 Variable* var = NULL;
1329 // If we are inside a function, a declaration of a variable
1330 // is a truly local variable, and the scope of the variable
1331 // is always the function scope.
1332
1333 // If a function scope exists, then we can statically declare this
1334 // variable and also set its mode. In any case, a Declaration node
1335 // will be added to the scope so that the declaration can be added
1336 // to the corresponding activation frame at runtime if necessary.
1337 // For instance declarations inside an eval scope need to be added
1338 // to the calling function context.
Ben Murdoch257744e2011-11-30 15:57:28 +00001339 // Similarly, strict mode eval scope does not leak variable declarations to
1340 // the caller's scope so we declare all locals, too.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001341 Scope* declaration_scope = top_scope_->DeclarationScope();
1342 if (declaration_scope->is_function_scope() ||
1343 declaration_scope->is_strict_mode_eval_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 // Declare the variable in the function scope.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001345 var = declaration_scope->LocalLookup(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 if (var == NULL) {
1347 // Declare the name.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001348 var = declaration_scope->DeclareLocal(name, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 } else {
1350 // The name was declared before; check for conflicting
1351 // re-declarations. If the previous declaration was a const or the
1352 // current declaration is a const then we have a conflict. There is
1353 // similar code in runtime.cc in the Declare functions.
1354 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1355 // We only have vars and consts in declarations.
1356 ASSERT(var->mode() == Variable::VAR ||
1357 var->mode() == Variable::CONST);
1358 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1359 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001360 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001362 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001363 type_string, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001364 declaration_scope->SetIllegalRedeclaration(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00001365 }
1366 }
1367 }
1368
1369 // We add a declaration node for every declaration. The compiler
1370 // will only generate code if necessary. In particular, declarations
1371 // for inner local variables that do not represent functions won't
1372 // result in any generated code.
1373 //
1374 // Note that we always add an unresolved proxy even if it's not
1375 // used, simply because we don't know in this method (w/o extra
1376 // parameters) if the proxy is needed or not. The proxy will be
1377 // bound during variable resolution time unless it was pre-bound
1378 // below.
1379 //
1380 // WARNING: This will lead to multiple declaration nodes for the
1381 // same variable if it is declared several times. This is not a
1382 // semantic issue as long as we keep the source order, but it may be
1383 // a performance issue since it may lead to repeated
1384 // Runtime::DeclareContextSlot() calls.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001385 VariableProxy* proxy = declaration_scope->NewUnresolved(name, false);
1386 declaration_scope->AddDeclaration(new(zone()) Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001387
1388 // For global const variables we bind the proxy to a variable.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001389 if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001390 ASSERT(resolve); // should be set by all callers
1391 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001392 var = new(zone()) Variable(declaration_scope,
1393 name,
1394 Variable::CONST,
1395 true,
1396 kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 }
1398
1399 // If requested and we have a local variable, bind the proxy to the variable
1400 // at parse-time. This is used for functions (and consts) declared inside
1401 // statements: the corresponding function (or const) variable must be in the
1402 // function scope and not a statement-local scope, e.g. as provided with a
1403 // 'with' statement:
1404 //
1405 // with (obj) {
1406 // function f() {}
1407 // }
1408 //
1409 // which is translated into:
1410 //
1411 // with (obj) {
1412 // // in this case this is not: 'var f; f = function () {};'
1413 // var f = function () {};
1414 // }
1415 //
1416 // Note that if 'f' is accessed from inside the 'with' statement, it
1417 // will be allocated in the context (because we must be able to look
1418 // it up dynamically) but it will also be accessed statically, i.e.,
1419 // with a context slot index and a context chain length for this
1420 // initialization code. Thus, inside the 'with' statement, we need
1421 // both access to the static and the dynamic context chain; the
1422 // runtime needs to provide both.
1423 if (resolve && var != NULL) proxy->BindTo(var);
1424
1425 return proxy;
1426}
1427
1428
1429// Language extension which is only enabled for source files loaded
1430// through the API's extension mechanism. A native function
1431// declaration is resolved by looking up the function through a
1432// callback provided by the extension.
1433Statement* Parser::ParseNativeDeclaration(bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001434 Expect(Token::FUNCTION, CHECK_OK);
1435 Handle<String> name = ParseIdentifier(CHECK_OK);
1436 Expect(Token::LPAREN, CHECK_OK);
1437 bool done = (peek() == Token::RPAREN);
1438 while (!done) {
1439 ParseIdentifier(CHECK_OK);
1440 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001441 if (!done) {
1442 Expect(Token::COMMA, CHECK_OK);
1443 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001444 }
1445 Expect(Token::RPAREN, CHECK_OK);
1446 Expect(Token::SEMICOLON, CHECK_OK);
1447
Steve Blocka7e24c12009-10-30 11:49:00 +00001448 // Make sure that the function containing the native declaration
1449 // isn't lazily compiled. The extension structures are only
1450 // accessible while parsing the first time not when reparsing
1451 // because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001452 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001453
1454 // Compute the function template for the native function.
1455 v8::Handle<v8::FunctionTemplate> fun_template =
1456 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1457 ASSERT(!fun_template.IsEmpty());
1458
Steve Block6ded16b2010-05-10 14:33:55 +01001459 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001460 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1461 const int literals = fun->NumberOfLiterals();
1462 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001463 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001464 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001465 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001466 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001467 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001468
Steve Block6ded16b2010-05-10 14:33:55 +01001469 // Copy the function data to the shared function info.
1470 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001471 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001472 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001473
1474 // TODO(1240846): It's weird that native function declarations are
1475 // introduced dynamically when we meet their declarations, whereas
1476 // other functions are setup when entering the surrounding scope.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001477 SharedFunctionInfoLiteral* lit =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001478 new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001479 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001480 return new(zone()) ExpressionStatement(new(zone()) Assignment(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001481 isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001482}
1483
1484
1485Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1486 // FunctionDeclaration ::
1487 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1488 Expect(Token::FUNCTION, CHECK_OK);
1489 int function_token_position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001490 bool is_strict_reserved = false;
1491 Handle<String> name = ParseIdentifierOrStrictReservedWord(
1492 &is_strict_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001493 FunctionLiteral* fun = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001494 is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001495 function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001496 FunctionLiteral::DECLARATION,
Steve Blocka7e24c12009-10-30 11:49:00 +00001497 CHECK_OK);
1498 // Even if we're not at the top-level of the global or a function
1499 // scope, we treat is as such and introduce the function with it's
1500 // initial value upon entering the corresponding scope.
1501 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001502 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001503}
1504
1505
1506Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1507 // Block ::
1508 // '{' Statement* '}'
1509
1510 // Note that a Block does not introduce a new execution scope!
1511 // (ECMA-262, 3rd, 12.2)
1512 //
1513 // Construct block expecting 16 statements.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001514 Block* result = new(zone()) Block(isolate(), labels, 16, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001515 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001516 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001517 InitializationBlockFinder block_finder(top_scope_, target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001518 while (peek() != Token::RBRACE) {
1519 Statement* stat = ParseStatement(NULL, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001520 if (stat && !stat->IsEmpty()) {
1521 result->AddStatement(stat);
1522 block_finder.Update(stat);
1523 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001524 }
1525 Expect(Token::RBRACE, CHECK_OK);
1526 return result;
1527}
1528
1529
1530Block* Parser::ParseVariableStatement(bool* ok) {
1531 // VariableStatement ::
1532 // VariableDeclarations ';'
1533
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001534 Handle<String> ignore;
1535 Block* result = ParseVariableDeclarations(true, &ignore, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 ExpectSemicolon(CHECK_OK);
1537 return result;
1538}
1539
Steve Block44f0eee2011-05-26 01:26:41 +01001540
1541bool Parser::IsEvalOrArguments(Handle<String> string) {
1542 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1543 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001544}
Steve Blocka7e24c12009-10-30 11:49:00 +00001545
Steve Block44f0eee2011-05-26 01:26:41 +01001546
Steve Blocka7e24c12009-10-30 11:49:00 +00001547// If the variable declaration declares exactly one non-const
1548// variable, then *var is set to that variable. In all other cases,
1549// *var is untouched; in particular, it is the caller's responsibility
1550// to initialize it properly. This mechanism is used for the parsing
1551// of 'for-in' loops.
1552Block* Parser::ParseVariableDeclarations(bool accept_IN,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001553 Handle<String>* out,
Steve Blocka7e24c12009-10-30 11:49:00 +00001554 bool* ok) {
1555 // VariableDeclarations ::
1556 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1557
1558 Variable::Mode mode = Variable::VAR;
1559 bool is_const = false;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001560 Scope* declaration_scope = top_scope_->DeclarationScope();
Steve Blocka7e24c12009-10-30 11:49:00 +00001561 if (peek() == Token::VAR) {
1562 Consume(Token::VAR);
1563 } else if (peek() == Token::CONST) {
1564 Consume(Token::CONST);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001565 if (declaration_scope->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001566 ReportMessage("strict_const", Vector<const char*>::empty());
1567 *ok = false;
1568 return NULL;
1569 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 mode = Variable::CONST;
1571 is_const = true;
1572 } else {
1573 UNREACHABLE(); // by current callers
1574 }
1575
1576 // The scope of a variable/const declared anywhere inside a function
1577 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1578 // transform a source-level variable/const declaration into a (Function)
1579 // Scope declaration, and rewrite the source-level initialization into an
1580 // assignment statement. We use a block to collect multiple assignments.
1581 //
1582 // We mark the block as initializer block because we don't want the
1583 // rewriter to add a '.result' assignment to such a block (to get compliant
1584 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1585 // reasons when pretty-printing. Also, unless an assignment (initialization)
1586 // is inside an initializer block, it is ignored.
1587 //
1588 // Create new block with one expected declaration.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001589 Block* block = new(zone()) Block(isolate(), NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001590 int nvars = 0; // the number of variables declared
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001591 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001592 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001593 if (fni_ != NULL) fni_->Enter();
1594
Steve Blocka7e24c12009-10-30 11:49:00 +00001595 // Parse variable name.
1596 if (nvars > 0) Consume(Token::COMMA);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001597 name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001598 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001599
Steve Block1e0659c2011-05-24 12:43:12 +01001600 // Strict mode variables may not be named eval or arguments
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001601 if (declaration_scope->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001602 ReportMessage("strict_var_name", Vector<const char*>::empty());
1603 *ok = false;
1604 return NULL;
1605 }
1606
Steve Blocka7e24c12009-10-30 11:49:00 +00001607 // Declare variable.
1608 // Note that we *always* must treat the initial value via a separate init
1609 // assignment for variables and constants because the value must be assigned
1610 // when the variable is encountered in the source. But the variable/constant
1611 // is declared (and set to 'undefined') upon entering the function within
1612 // which the variable or constant is declared. Only function variables have
1613 // an initial value in the declaration (because they are initialized upon
1614 // entering the function).
1615 //
1616 // If we have a const declaration, in an inner scope, the proxy is always
1617 // bound to the declared variable (independent of possibly surrounding with
1618 // statements).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001619 Declare(name, mode, NULL, is_const /* always bound for CONST! */,
1620 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001621 nvars++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001622 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
Steve Block053d10c2011-06-13 19:13:29 +01001623 ReportMessageAt(scanner().location(), "too_many_variables",
1624 Vector<const char*>::empty());
1625 *ok = false;
1626 return NULL;
1627 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001628
1629 // Parse initialization expression if present and/or needed. A
1630 // declaration of the form:
1631 //
1632 // var v = x;
1633 //
1634 // is syntactic sugar for:
1635 //
1636 // var v; v = x;
1637 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001638 // In particular, we need to re-lookup 'v' (in top_scope_, not
1639 // declaration_scope) as it may be a different 'v' than the 'v' in the
1640 // declaration (e.g., if we are inside a 'with' statement or 'catch'
1641 // block).
Steve Blocka7e24c12009-10-30 11:49:00 +00001642 //
1643 // However, note that const declarations are different! A const
1644 // declaration of the form:
1645 //
1646 // const c = x;
1647 //
1648 // is *not* syntactic sugar for:
1649 //
1650 // const c; c = x;
1651 //
1652 // The "variable" c initialized to x is the same as the declared
1653 // one - there is no re-lookup (see the last parameter of the
1654 // Declare() call above).
1655
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001656 Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001657 Expression* value = NULL;
1658 int position = -1;
1659 if (peek() == Token::ASSIGN) {
1660 Expect(Token::ASSIGN, CHECK_OK);
1661 position = scanner().location().beg_pos;
1662 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001663 // Don't infer if it is "a = function(){...}();"-like expression.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001664 if (fni_ != NULL &&
1665 value->AsCall() == NULL &&
1666 value->AsCallNew() == NULL) {
1667 fni_->Infer();
1668 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001669 }
1670
1671 // Make sure that 'const c' actually initializes 'c' to undefined
1672 // even though it seems like a stupid thing to do.
1673 if (value == NULL && is_const) {
1674 value = GetLiteralUndefined();
1675 }
1676
1677 // Global variable declarations must be compiled in a specific
1678 // way. When the script containing the global variable declaration
1679 // is entered, the global variable must be declared, so that if it
1680 // doesn't exist (not even in a prototype of the global object) it
1681 // gets created with an initial undefined value. This is handled
1682 // by the declarations part of the function representing the
1683 // top-level global code; see Runtime::DeclareGlobalVariable. If
1684 // it already exists (in the object or in a prototype), it is
1685 // *not* touched until the variable declaration statement is
1686 // executed.
1687 //
1688 // Executing the variable declaration statement will always
1689 // guarantee to give the global object a "local" variable; a
1690 // variable defined in the global object and not in any
1691 // prototype. This way, global variable declarations can shadow
1692 // properties in the prototype chain, but only after the variable
1693 // declaration statement has been executed. This is important in
1694 // browsers where the global object (window) has lots of
1695 // properties defined in prototype objects.
1696
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001697 if (initialization_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001698 // Compute the arguments for the runtime call.
Ben Murdoch257744e2011-11-30 15:57:28 +00001699 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001700 // We have at least 1 parameter.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001701 arguments->Add(NewLiteral(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001702 CallRuntime* initialize;
1703
1704 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001705 arguments->Add(value);
1706 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001707
1708 // Construct the call to Runtime_InitializeConstGlobal
1709 // and add it to the initialization statement block.
1710 // Note that the function does different things depending on
1711 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001712 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001713 new(zone()) CallRuntime(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001714 isolate(),
1715 isolate()->factory()->InitializeConstGlobal_symbol(),
1716 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1717 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001718 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001719 // Add strict mode.
1720 // We may want to pass singleton to avoid Literal allocations.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001721 StrictModeFlag flag = initialization_scope->is_strict_mode()
1722 ? kStrictMode
1723 : kNonStrictMode;
1724 arguments->Add(NewNumberLiteral(flag));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001725
1726 // Be careful not to assign a value to the global variable if
1727 // we're in a with. The initialization value should not
1728 // necessarily be stored in the global object in that case,
1729 // which is why we need to generate a separate assignment node.
1730 if (value != NULL && !inside_with()) {
1731 arguments->Add(value);
1732 value = NULL; // zap the value to avoid the unnecessary assignment
1733 }
1734
1735 // Construct the call to Runtime_InitializeVarGlobal
1736 // and add it to the initialization statement block.
1737 // Note that the function does different things depending on
1738 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001739 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001740 new(zone()) CallRuntime(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001741 isolate(),
1742 isolate()->factory()->InitializeVarGlobal_symbol(),
1743 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1744 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001745 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001746
Ben Murdoch8b112d22011-06-08 16:22:53 +01001747 block->AddStatement(new(zone()) ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001748 }
1749
1750 // Add an assignment node to the initialization statement block if
1751 // we still have a pending initialization value. We must distinguish
1752 // between variables and constants: Variable initializations are simply
1753 // assignments (with all the consequences if they are inside a 'with'
1754 // statement - they may change a 'with' object property). Constant
1755 // initializations always assign to the declared constant which is
1756 // always at the function scope level. This is only relevant for
1757 // dynamically looked-up variables and constants (the start context
1758 // for constant lookups is always the function context, while it is
1759 // the top context for variables). Sigh...
1760 if (value != NULL) {
1761 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001762 bool in_with = is_const ? false : inside_with();
1763 VariableProxy* proxy =
1764 initialization_scope->NewUnresolved(name, in_with);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001765 Assignment* assignment =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001766 new(zone()) Assignment(isolate(), op, proxy, value, position);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001767 if (block) {
1768 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1769 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001770 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001771
1772 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001773 } while (peek() == Token::COMMA);
1774
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001775 // If there was a single non-const declaration, return it in the output
1776 // parameter for possible use by for/in.
1777 if (nvars == 1 && !is_const) {
1778 *out = name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001779 }
1780
1781 return block;
1782}
1783
1784
1785static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1786 ASSERT(!label.is_null());
1787 if (labels != NULL)
1788 for (int i = labels->length(); i-- > 0; )
1789 if (labels->at(i).is_identical_to(label))
1790 return true;
1791
1792 return false;
1793}
1794
1795
1796Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1797 bool* ok) {
1798 // ExpressionStatement | LabelledStatement ::
1799 // Expression ';'
1800 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001801 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001802 Expression* expr = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001803 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001804 expr->AsVariableProxy() != NULL &&
1805 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001806 // Expression is a single identifier, and not, e.g., a parenthesized
1807 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001808 VariableProxy* var = expr->AsVariableProxy();
1809 Handle<String> label = var->name();
1810 // TODO(1240780): We don't check for redeclaration of labels
1811 // during preparsing since keeping track of the set of active
1812 // labels requires nontrivial changes to the way scopes are
1813 // structured. However, these are probably changes we want to
1814 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001815 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1816 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1817 const char* elms[2] = { "Label", *c_string };
1818 Vector<const char*> args(elms, 2);
1819 ReportMessage("redeclaration", args);
1820 *ok = false;
1821 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001822 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001823 if (labels == NULL) labels = new(zone()) ZoneStringList(4);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001824 labels->Add(label);
1825 // Remove the "ghost" variable that turned out to be a label
1826 // from the top scope. This way, we don't try to resolve it
1827 // during the scope processing.
1828 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001829 Expect(Token::COLON, CHECK_OK);
1830 return ParseStatement(labels, ok);
1831 }
1832
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001833 // If we have an extension, we allow a native function declaration.
1834 // A native function declaration starts with "native function" with
1835 // no line-terminator between the two words.
1836 if (extension_ != NULL &&
1837 peek() == Token::FUNCTION &&
1838 !scanner().HasAnyLineTerminatorBeforeNext() &&
1839 expr != NULL &&
1840 expr->AsVariableProxy() != NULL &&
1841 expr->AsVariableProxy()->name()->Equals(
1842 isolate()->heap()->native_symbol()) &&
1843 !scanner().literal_contains_escapes()) {
1844 return ParseNativeDeclaration(ok);
1845 }
1846
Steve Blocka7e24c12009-10-30 11:49:00 +00001847 // Parsed expression statement.
1848 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001849 return new(zone()) ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001850}
1851
1852
1853IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1854 // IfStatement ::
1855 // 'if' '(' Expression ')' Statement ('else' Statement)?
1856
1857 Expect(Token::IF, CHECK_OK);
1858 Expect(Token::LPAREN, CHECK_OK);
1859 Expression* condition = ParseExpression(true, CHECK_OK);
1860 Expect(Token::RPAREN, CHECK_OK);
1861 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1862 Statement* else_statement = NULL;
1863 if (peek() == Token::ELSE) {
1864 Next();
1865 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001866 } else {
1867 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001868 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001869 return new(zone()) IfStatement(
1870 isolate(), condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001871}
1872
1873
1874Statement* Parser::ParseContinueStatement(bool* ok) {
1875 // ContinueStatement ::
1876 // 'continue' Identifier? ';'
1877
1878 Expect(Token::CONTINUE, CHECK_OK);
1879 Handle<String> label = Handle<String>::null();
1880 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001881 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001882 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1883 label = ParseIdentifier(CHECK_OK);
1884 }
1885 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001886 target = LookupContinueTarget(label, CHECK_OK);
1887 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001888 // Illegal continue statement.
1889 const char* message = "illegal_continue";
1890 Vector<Handle<String> > args;
1891 if (!label.is_null()) {
1892 message = "unknown_label";
1893 args = Vector<Handle<String> >(&label, 1);
1894 }
1895 ReportMessageAt(scanner().location(), message, args);
1896 *ok = false;
1897 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001898 }
1899 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001900 return new(zone()) ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001901}
1902
1903
1904Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1905 // BreakStatement ::
1906 // 'break' Identifier? ';'
1907
1908 Expect(Token::BREAK, CHECK_OK);
1909 Handle<String> label;
1910 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001911 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001912 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1913 label = ParseIdentifier(CHECK_OK);
1914 }
1915 // Parse labeled break statements that target themselves into
1916 // empty statements, e.g. 'l1: l2: l3: break l2;'
1917 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001918 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001919 }
1920 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001921 target = LookupBreakTarget(label, CHECK_OK);
1922 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001923 // Illegal break statement.
1924 const char* message = "illegal_break";
1925 Vector<Handle<String> > args;
1926 if (!label.is_null()) {
1927 message = "unknown_label";
1928 args = Vector<Handle<String> >(&label, 1);
1929 }
1930 ReportMessageAt(scanner().location(), message, args);
1931 *ok = false;
1932 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001933 }
1934 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001935 return new(zone()) BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001936}
1937
1938
1939Statement* Parser::ParseReturnStatement(bool* ok) {
1940 // ReturnStatement ::
1941 // 'return' Expression? ';'
1942
1943 // Consume the return token. It is necessary to do the before
1944 // reporting any errors on it, because of the way errors are
1945 // reported (underlining).
1946 Expect(Token::RETURN, CHECK_OK);
1947
1948 // An ECMAScript program is considered syntactically incorrect if it
1949 // contains a return statement that is not within the body of a
1950 // function. See ECMA-262, section 12.9, page 67.
1951 //
1952 // To be consistent with KJS we report the syntax error at runtime.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001953 Scope* declaration_scope = top_scope_->DeclarationScope();
1954 if (declaration_scope->is_global_scope() ||
1955 declaration_scope->is_eval_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001956 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00001957 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001958 return new(zone()) ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001959 }
1960
1961 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001962 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001963 tok == Token::SEMICOLON ||
1964 tok == Token::RBRACE ||
1965 tok == Token::EOS) {
1966 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001967 return new(zone()) ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001968 }
1969
1970 Expression* expr = ParseExpression(true, CHECK_OK);
1971 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001972 return new(zone()) ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001973}
1974
1975
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001976Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001977 // Parse the statement and collect escaping labels.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001978 TargetCollector collector;
Steve Blocka7e24c12009-10-30 11:49:00 +00001979 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001980 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001981 with_nesting_level_++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001982 top_scope_->DeclarationScope()->RecordWithStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001983 stat = ParseStatement(labels, CHECK_OK);
1984 with_nesting_level_--;
1985 }
1986 // Create resulting block with two statements.
1987 // 1: Evaluate the with expression.
1988 // 2: The try-finally block evaluating the body.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001989 Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001990
1991 if (result != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001992 result->AddStatement(new(zone()) EnterWithContextStatement(obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001993
1994 // Create body block.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001995 Block* body = new(zone()) Block(isolate(), NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001996 body->AddStatement(stat);
1997
1998 // Create exit block.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001999 Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
2000 exit->AddStatement(new(zone()) ExitContextStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00002001
2002 // Return a try-finally statement.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002003 TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00002004 wrapper->set_escaping_targets(collector.targets());
2005 result->AddStatement(wrapper);
2006 }
2007 return result;
2008}
2009
2010
2011Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2012 // WithStatement ::
2013 // 'with' '(' Expression ')' Statement
2014
2015 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002016
Steve Block44f0eee2011-05-26 01:26:41 +01002017 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002018 ReportMessage("strict_mode_with", Vector<const char*>::empty());
2019 *ok = false;
2020 return NULL;
2021 }
2022
Steve Blocka7e24c12009-10-30 11:49:00 +00002023 Expect(Token::LPAREN, CHECK_OK);
2024 Expression* expr = ParseExpression(true, CHECK_OK);
2025 Expect(Token::RPAREN, CHECK_OK);
2026
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002027 return WithHelper(expr, labels, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002028}
2029
2030
2031CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2032 // CaseClause ::
2033 // 'case' Expression ':' Statement*
2034 // 'default' ':' Statement*
2035
2036 Expression* label = NULL; // NULL expression indicates default case
2037 if (peek() == Token::CASE) {
2038 Expect(Token::CASE, CHECK_OK);
2039 label = ParseExpression(true, CHECK_OK);
2040 } else {
2041 Expect(Token::DEFAULT, CHECK_OK);
2042 if (*default_seen_ptr) {
2043 ReportMessage("multiple_defaults_in_switch",
2044 Vector<const char*>::empty());
2045 *ok = false;
2046 return NULL;
2047 }
2048 *default_seen_ptr = true;
2049 }
2050 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002051 int pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00002052 ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00002053 while (peek() != Token::CASE &&
2054 peek() != Token::DEFAULT &&
2055 peek() != Token::RBRACE) {
2056 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002057 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00002058 }
2059
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002060 return new(zone()) CaseClause(isolate(), label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002061}
2062
2063
2064SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2065 bool* ok) {
2066 // SwitchStatement ::
2067 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2068
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002069 SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002070 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002071
2072 Expect(Token::SWITCH, CHECK_OK);
2073 Expect(Token::LPAREN, CHECK_OK);
2074 Expression* tag = ParseExpression(true, CHECK_OK);
2075 Expect(Token::RPAREN, CHECK_OK);
2076
2077 bool default_seen = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00002078 ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002079 Expect(Token::LBRACE, CHECK_OK);
2080 while (peek() != Token::RBRACE) {
2081 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002082 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002083 }
2084 Expect(Token::RBRACE, CHECK_OK);
2085
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002086 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002087 return statement;
2088}
2089
2090
2091Statement* Parser::ParseThrowStatement(bool* ok) {
2092 // ThrowStatement ::
2093 // 'throw' Expression ';'
2094
2095 Expect(Token::THROW, CHECK_OK);
2096 int pos = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002097 if (scanner().HasAnyLineTerminatorBeforeNext()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002098 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2099 *ok = false;
2100 return NULL;
2101 }
2102 Expression* exception = ParseExpression(true, CHECK_OK);
2103 ExpectSemicolon(CHECK_OK);
2104
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002105 return new(zone()) ExpressionStatement(
2106 new(zone()) Throw(isolate(), exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002107}
2108
2109
2110TryStatement* Parser::ParseTryStatement(bool* ok) {
2111 // TryStatement ::
2112 // 'try' Block Catch
2113 // 'try' Block Finally
2114 // 'try' Block Catch Finally
2115 //
2116 // Catch ::
2117 // 'catch' '(' Identifier ')' Block
2118 //
2119 // Finally ::
2120 // 'finally' Block
2121
2122 Expect(Token::TRY, CHECK_OK);
2123
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002124 TargetCollector try_collector;
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 Block* try_block;
2126
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002127 { Target target(&this->target_stack_, &try_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002128 try_block = ParseBlock(NULL, CHECK_OK);
2129 }
2130
Steve Blocka7e24c12009-10-30 11:49:00 +00002131 Token::Value tok = peek();
2132 if (tok != Token::CATCH && tok != Token::FINALLY) {
2133 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2134 *ok = false;
2135 return NULL;
2136 }
2137
2138 // If we can break out from the catch block and there is a finally block,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002139 // then we will need to collect escaping targets from the catch
2140 // block. Since we don't know yet if there will be a finally block, we
2141 // always collect the targets.
2142 TargetCollector catch_collector;
2143 Scope* catch_scope = NULL;
2144 Variable* catch_variable = NULL;
2145 Block* catch_block = NULL;
2146 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002147 if (tok == Token::CATCH) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002148 Consume(Token::CATCH);
2149
2150 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002151 name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002152
Steve Block44f0eee2011-05-26 01:26:41 +01002153 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002154 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2155 *ok = false;
2156 return NULL;
2157 }
2158
Steve Blocka7e24c12009-10-30 11:49:00 +00002159 Expect(Token::RPAREN, CHECK_OK);
2160
2161 if (peek() == Token::LBRACE) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002162 // Rewrite the catch body B to a single statement block
2163 // { try B finally { PopContext }}.
2164 Block* inner_body;
2165 // We need to collect escapes from the body for both the inner
2166 // try/finally used to pop the catch context and any possible outer
2167 // try/finally.
2168 TargetCollector inner_collector;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002169 { Target target(&this->target_stack_, &catch_collector);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002170 { Target target(&this->target_stack_, &inner_collector);
2171 catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with());
2172 if (top_scope_->is_strict_mode()) {
2173 catch_scope->EnableStrictMode();
2174 }
2175 catch_variable = catch_scope->DeclareLocal(name, Variable::VAR);
2176
2177 Scope* saved_scope = top_scope_;
2178 top_scope_ = catch_scope;
2179 inner_body = ParseBlock(NULL, CHECK_OK);
2180 top_scope_ = saved_scope;
2181 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002182 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002183
2184 // Create exit block.
2185 Block* inner_finally = new(zone()) Block(isolate(), NULL, 1, false);
2186 inner_finally->AddStatement(new(zone()) ExitContextStatement());
2187
2188 // Create a try/finally statement.
2189 TryFinallyStatement* inner_try_finally =
2190 new(zone()) TryFinallyStatement(inner_body, inner_finally);
2191 inner_try_finally->set_escaping_targets(inner_collector.targets());
2192
2193 catch_block = new(zone()) Block(isolate(), NULL, 1, false);
2194 catch_block->AddStatement(inner_try_finally);
Steve Blocka7e24c12009-10-30 11:49:00 +00002195 } else {
2196 Expect(Token::LBRACE, CHECK_OK);
2197 }
2198
2199 tok = peek();
2200 }
2201
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002202 Block* finally_block = NULL;
2203 if (tok == Token::FINALLY || catch_block == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002204 Consume(Token::FINALLY);
Steve Blocka7e24c12009-10-30 11:49:00 +00002205 finally_block = ParseBlock(NULL, CHECK_OK);
2206 }
2207
2208 // Simplify the AST nodes by converting:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002209 // 'try B0 catch B1 finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002210 // to:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002211 // 'try { try B0 catch B1 } finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002212
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002213 if (catch_block != NULL && finally_block != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002214 // If we have both, create an inner try/catch.
2215 ASSERT(catch_scope != NULL && catch_variable != NULL);
Steve Block3ce2e202009-11-05 08:53:23 +00002216 TryCatchStatement* statement =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002217 new(zone()) TryCatchStatement(try_block,
2218 catch_scope,
2219 catch_variable,
2220 catch_block);
2221 statement->set_escaping_targets(try_collector.targets());
2222 try_block = new(zone()) Block(isolate(), NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002223 try_block->AddStatement(statement);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002224 catch_block = NULL; // Clear to indicate it's been handled.
Steve Blocka7e24c12009-10-30 11:49:00 +00002225 }
2226
2227 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002228 if (catch_block != NULL) {
2229 ASSERT(finally_block == NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002230 ASSERT(catch_scope != NULL && catch_variable != NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002231 result =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002232 new(zone()) TryCatchStatement(try_block,
2233 catch_scope,
2234 catch_variable,
2235 catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002236 } else {
2237 ASSERT(finally_block != NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002238 result = new(zone()) TryFinallyStatement(try_block, finally_block);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002239 // Combine the jump targets of the try block and the possible catch block.
2240 try_collector.targets()->AddAll(*catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002241 }
2242
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002243 result->set_escaping_targets(try_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002244 return result;
2245}
2246
2247
Steve Block3ce2e202009-11-05 08:53:23 +00002248DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2249 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002250 // DoStatement ::
2251 // 'do' Statement 'while' '(' Expression ')' ';'
2252
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002253 DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002254 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002255
2256 Expect(Token::DO, CHECK_OK);
2257 Statement* body = ParseStatement(NULL, CHECK_OK);
2258 Expect(Token::WHILE, CHECK_OK);
2259 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002260
2261 if (loop != NULL) {
2262 int position = scanner().location().beg_pos;
2263 loop->set_condition_position(position);
2264 }
2265
Steve Blocka7e24c12009-10-30 11:49:00 +00002266 Expression* cond = ParseExpression(true, CHECK_OK);
2267 Expect(Token::RPAREN, CHECK_OK);
2268
2269 // Allow do-statements to be terminated with and without
2270 // semi-colons. This allows code such as 'do;while(0)return' to
2271 // parse, which would not be the case if we had used the
2272 // ExpectSemicolon() functionality here.
2273 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2274
Steve Block3ce2e202009-11-05 08:53:23 +00002275 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002276 return loop;
2277}
2278
2279
Steve Block3ce2e202009-11-05 08:53:23 +00002280WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002281 // WhileStatement ::
2282 // 'while' '(' Expression ')' Statement
2283
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002284 WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002285 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002286
2287 Expect(Token::WHILE, CHECK_OK);
2288 Expect(Token::LPAREN, CHECK_OK);
2289 Expression* cond = ParseExpression(true, CHECK_OK);
2290 Expect(Token::RPAREN, CHECK_OK);
2291 Statement* body = ParseStatement(NULL, CHECK_OK);
2292
Steve Block3ce2e202009-11-05 08:53:23 +00002293 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002294 return loop;
2295}
2296
2297
2298Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2299 // ForStatement ::
2300 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2301
2302 Statement* init = NULL;
2303
2304 Expect(Token::FOR, CHECK_OK);
2305 Expect(Token::LPAREN, CHECK_OK);
2306 if (peek() != Token::SEMICOLON) {
2307 if (peek() == Token::VAR || peek() == Token::CONST) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002308 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002309 Block* variable_statement =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002310 ParseVariableDeclarations(false, &name, CHECK_OK);
2311
2312 if (peek() == Token::IN && !name.is_null()) {
2313 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with());
2314 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002315 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002316
2317 Expect(Token::IN, CHECK_OK);
2318 Expression* enumerable = ParseExpression(true, CHECK_OK);
2319 Expect(Token::RPAREN, CHECK_OK);
2320
2321 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002322 loop->Initialize(each, enumerable, body);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002323 Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002324 result->AddStatement(variable_statement);
2325 result->AddStatement(loop);
2326 // Parsed for-in loop w/ variable/const declaration.
2327 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002328 } else {
2329 init = variable_statement;
2330 }
2331
2332 } else {
2333 Expression* expression = ParseExpression(false, CHECK_OK);
2334 if (peek() == Token::IN) {
2335 // Signal a reference error if the expression is an invalid
2336 // left-hand side expression. We could report this as a syntax
2337 // error here but for compatibility with JSC we choose to report
2338 // the error at runtime.
2339 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002340 Handle<String> type =
2341 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002342 expression = NewThrowReferenceError(type);
2343 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002344 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002345 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002346
2347 Expect(Token::IN, CHECK_OK);
2348 Expression* enumerable = ParseExpression(true, CHECK_OK);
2349 Expect(Token::RPAREN, CHECK_OK);
2350
2351 Statement* body = ParseStatement(NULL, CHECK_OK);
2352 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002353 // Parsed for-in loop.
2354 return loop;
2355
2356 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002357 init = new(zone()) ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002358 }
2359 }
2360 }
2361
2362 // Standard 'for' loop
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002363 ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002364 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002365
2366 // Parsed initializer at this point.
2367 Expect(Token::SEMICOLON, CHECK_OK);
2368
2369 Expression* cond = NULL;
2370 if (peek() != Token::SEMICOLON) {
2371 cond = ParseExpression(true, CHECK_OK);
2372 }
2373 Expect(Token::SEMICOLON, CHECK_OK);
2374
2375 Statement* next = NULL;
2376 if (peek() != Token::RPAREN) {
2377 Expression* exp = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002378 next = new(zone()) ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002379 }
2380 Expect(Token::RPAREN, CHECK_OK);
2381
2382 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002383 if (loop) loop->Initialize(init, cond, next, body);
2384 return loop;
2385}
2386
2387
2388// Precedence = 1
2389Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2390 // Expression ::
2391 // AssignmentExpression
2392 // Expression ',' AssignmentExpression
2393
2394 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2395 while (peek() == Token::COMMA) {
2396 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002397 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002398 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002399 result = new(zone()) BinaryOperation(
2400 isolate(), Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002401 }
2402 return result;
2403}
2404
2405
2406// Precedence = 2
2407Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2408 // AssignmentExpression ::
2409 // ConditionalExpression
2410 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2411
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002412 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002413 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2414
2415 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002416 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002417 // Parsed conditional expression only (no assignment).
2418 return expression;
2419 }
2420
2421 // Signal a reference error if the expression is an invalid left-hand
2422 // side expression. We could report this as a syntax error here but
2423 // for compatibility with JSC we choose to report the error at
2424 // runtime.
2425 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002426 Handle<String> type =
2427 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002428 expression = NewThrowReferenceError(type);
2429 }
2430
Steve Block44f0eee2011-05-26 01:26:41 +01002431 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002432 // Assignment to eval or arguments is disallowed in strict mode.
2433 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2434 }
2435
Steve Blocka7e24c12009-10-30 11:49:00 +00002436 Token::Value op = Next(); // Get assignment operator.
2437 int pos = scanner().location().beg_pos;
2438 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2439
2440 // TODO(1231235): We try to estimate the set of properties set by
2441 // constructors. We define a new property whenever there is an
2442 // assignment to a property of 'this'. We should probably only add
2443 // properties if we haven't seen them before. Otherwise we'll
2444 // probably overestimate the number of properties.
2445 Property* property = expression ? expression->AsProperty() : NULL;
2446 if (op == Token::ASSIGN &&
2447 property != NULL &&
2448 property->obj()->AsVariableProxy() != NULL &&
2449 property->obj()->AsVariableProxy()->is_this()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002450 lexical_scope_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002451 }
2452
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002453 // If we assign a function literal to a property we pretenure the
2454 // literal so it can be added as a constant function property.
2455 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2456 right->AsFunctionLiteral()->set_pretenure(true);
2457 }
2458
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002459 if (fni_ != NULL) {
2460 // Check if the right hand side is a call to avoid inferring a
2461 // name if we're dealing with "a = function(){...}();"-like
2462 // expression.
2463 if ((op == Token::INIT_VAR
2464 || op == Token::INIT_CONST
2465 || op == Token::ASSIGN)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002466 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002467 fni_->Infer();
2468 }
2469 fni_->Leave();
2470 }
2471
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002472 return new(zone()) Assignment(isolate(), op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002473}
2474
2475
2476// Precedence = 3
2477Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2478 // ConditionalExpression ::
2479 // LogicalOrExpression
2480 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2481
2482 // We start using the binary expression parser for prec >= 4 only!
2483 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2484 if (peek() != Token::CONDITIONAL) return expression;
2485 Consume(Token::CONDITIONAL);
2486 // In parsing the first assignment expression in conditional
2487 // expressions we always accept the 'in' keyword; see ECMA-262,
2488 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002489 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002490 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2491 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002492 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002493 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002494 return new(zone()) Conditional(
2495 isolate(), expression, left, right, left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002496}
2497
2498
2499static int Precedence(Token::Value tok, bool accept_IN) {
2500 if (tok == Token::IN && !accept_IN)
2501 return 0; // 0 precedence will terminate binary expression parsing
2502
2503 return Token::Precedence(tok);
2504}
2505
2506
2507// Precedence >= 4
2508Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2509 ASSERT(prec >= 4);
2510 Expression* x = ParseUnaryExpression(CHECK_OK);
2511 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2512 // prec1 >= 4
2513 while (Precedence(peek(), accept_IN) == prec1) {
2514 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002515 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002516 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2517
2518 // Compute some expressions involving only number literals.
2519 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2520 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2521 double x_val = x->AsLiteral()->handle()->Number();
2522 double y_val = y->AsLiteral()->handle()->Number();
2523
2524 switch (op) {
2525 case Token::ADD:
2526 x = NewNumberLiteral(x_val + y_val);
2527 continue;
2528 case Token::SUB:
2529 x = NewNumberLiteral(x_val - y_val);
2530 continue;
2531 case Token::MUL:
2532 x = NewNumberLiteral(x_val * y_val);
2533 continue;
2534 case Token::DIV:
2535 x = NewNumberLiteral(x_val / y_val);
2536 continue;
2537 case Token::BIT_OR:
2538 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2539 continue;
2540 case Token::BIT_AND:
2541 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2542 continue;
2543 case Token::BIT_XOR:
2544 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2545 continue;
2546 case Token::SHL: {
2547 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2548 x = NewNumberLiteral(value);
2549 continue;
2550 }
2551 case Token::SHR: {
2552 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2553 uint32_t value = DoubleToUint32(x_val) >> shift;
2554 x = NewNumberLiteral(value);
2555 continue;
2556 }
2557 case Token::SAR: {
2558 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2559 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2560 x = NewNumberLiteral(value);
2561 continue;
2562 }
2563 default:
2564 break;
2565 }
2566 }
2567
Steve Blocka7e24c12009-10-30 11:49:00 +00002568 // For now we distinguish between comparisons and other binary
2569 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002570 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002571 if (Token::IsCompareOp(op)) {
2572 // We have a comparison.
2573 Token::Value cmp = op;
2574 switch (op) {
2575 case Token::NE: cmp = Token::EQ; break;
2576 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2577 default: break;
2578 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002579 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002580 if (cmp != op) {
2581 // The comparison was negated - add a NOT.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002582 x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002583 }
2584
2585 } else {
2586 // We have a "normal" binary operation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002587 x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002588 }
2589 }
2590 }
2591 return x;
2592}
2593
2594
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002595Expression* Parser::NewCompareNode(Token::Value op,
2596 Expression* x,
2597 Expression* y,
2598 int position) {
2599 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002600 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002601 bool is_strict = (op == Token::EQ_STRICT);
2602 Literal* x_literal = x->AsLiteral();
2603 if (x_literal != NULL && x_literal->IsNull()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002604 return new(zone()) CompareToNull(isolate(), is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002605 }
2606
2607 Literal* y_literal = y->AsLiteral();
2608 if (y_literal != NULL && y_literal->IsNull()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002609 return new(zone()) CompareToNull(isolate(), is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002610 }
2611 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002612 return new(zone()) CompareOperation(isolate(), op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002613}
2614
2615
Steve Blocka7e24c12009-10-30 11:49:00 +00002616Expression* Parser::ParseUnaryExpression(bool* ok) {
2617 // UnaryExpression ::
2618 // PostfixExpression
2619 // 'delete' UnaryExpression
2620 // 'void' UnaryExpression
2621 // 'typeof' UnaryExpression
2622 // '++' UnaryExpression
2623 // '--' UnaryExpression
2624 // '+' UnaryExpression
2625 // '-' UnaryExpression
2626 // '~' UnaryExpression
2627 // '!' UnaryExpression
2628
2629 Token::Value op = peek();
2630 if (Token::IsUnaryOp(op)) {
2631 op = Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00002632 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002633 Expression* expression = ParseUnaryExpression(CHECK_OK);
2634
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002635 if (expression != NULL && (expression->AsLiteral() != NULL)) {
2636 Handle<Object> literal = expression->AsLiteral()->handle();
2637 if (op == Token::NOT) {
2638 // Convert the literal to a boolean condition and negate it.
2639 bool condition = literal->ToBoolean()->IsTrue();
2640 Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
2641 return NewLiteral(result);
2642 } else if (literal->IsNumber()) {
2643 // Compute some expressions involving only number literals.
2644 double value = literal->Number();
2645 switch (op) {
2646 case Token::ADD:
2647 return expression;
2648 case Token::SUB:
2649 return NewNumberLiteral(-value);
2650 case Token::BIT_NOT:
2651 return NewNumberLiteral(~DoubleToInt32(value));
2652 default:
2653 break;
2654 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002655 }
2656 }
2657
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002658 // "delete identifier" is a syntax error in strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01002659 if (op == Token::DELETE && top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002660 VariableProxy* operand = expression->AsVariableProxy();
2661 if (operand != NULL && !operand->is_this()) {
2662 ReportMessage("strict_delete", Vector<const char*>::empty());
2663 *ok = false;
2664 return NULL;
2665 }
2666 }
2667
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002668 return new(zone()) UnaryOperation(isolate(), op, expression, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002669
2670 } else if (Token::IsCountOp(op)) {
2671 op = Next();
2672 Expression* expression = ParseUnaryExpression(CHECK_OK);
2673 // Signal a reference error if the expression is an invalid
2674 // left-hand side expression. We could report this as a syntax
2675 // error here but for compatibility with JSC we choose to report the
2676 // error at runtime.
2677 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002678 Handle<String> type =
2679 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002680 expression = NewThrowReferenceError(type);
2681 }
Steve Block1e0659c2011-05-24 12:43:12 +01002682
Steve Block44f0eee2011-05-26 01:26:41 +01002683 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002684 // Prefix expression operand in strict mode may not be eval or arguments.
2685 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2686 }
2687
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002688 int position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002689 return new(zone()) CountOperation(isolate(),
2690 op,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002691 true /* prefix */,
2692 expression,
2693 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002694
2695 } else {
2696 return ParsePostfixExpression(ok);
2697 }
2698}
2699
2700
2701Expression* Parser::ParsePostfixExpression(bool* ok) {
2702 // PostfixExpression ::
2703 // LeftHandSideExpression ('++' | '--')?
2704
2705 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002706 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +01002707 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002708 // Signal a reference error if the expression is an invalid
2709 // left-hand side expression. We could report this as a syntax
2710 // error here but for compatibility with JSC we choose to report the
2711 // error at runtime.
2712 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002713 Handle<String> type =
2714 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002715 expression = NewThrowReferenceError(type);
2716 }
Steve Block1e0659c2011-05-24 12:43:12 +01002717
Steve Block44f0eee2011-05-26 01:26:41 +01002718 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002719 // Postfix expression operand in strict mode may not be eval or arguments.
2720 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2721 }
2722
Steve Blocka7e24c12009-10-30 11:49:00 +00002723 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002724 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002725 expression =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002726 new(zone()) CountOperation(isolate(),
2727 next,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002728 false /* postfix */,
2729 expression,
2730 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002731 }
2732 return expression;
2733}
2734
2735
2736Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2737 // LeftHandSideExpression ::
2738 // (NewExpression | MemberExpression) ...
2739
2740 Expression* result;
2741 if (peek() == Token::NEW) {
2742 result = ParseNewExpression(CHECK_OK);
2743 } else {
2744 result = ParseMemberExpression(CHECK_OK);
2745 }
2746
2747 while (true) {
2748 switch (peek()) {
2749 case Token::LBRACK: {
2750 Consume(Token::LBRACK);
2751 int pos = scanner().location().beg_pos;
2752 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002753 result = new(zone()) Property(isolate(), result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002754 Expect(Token::RBRACK, CHECK_OK);
2755 break;
2756 }
2757
2758 case Token::LPAREN: {
2759 int pos = scanner().location().beg_pos;
2760 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2761
2762 // Keep track of eval() calls since they disable all local variable
2763 // optimizations.
2764 // The calls that need special treatment are the
2765 // direct (i.e. not aliased) eval calls. These calls are all of the
2766 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002767 // declared in the current scope chain.
2768 // These calls are marked as potentially direct eval calls. Whether
2769 // they are actually direct calls to eval is determined at run time.
2770 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2771 // in the local scope chain. It only matters that it's called "eval",
2772 // is called without a receiver and it refers to the original eval
2773 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002774 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01002775 if (callee != NULL &&
2776 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002777 Handle<String> name = callee->name();
2778 Variable* var = top_scope_->Lookup(name);
2779 if (var == NULL) {
2780 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002781 }
2782 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002783 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002784 break;
2785 }
2786
2787 case Token::PERIOD: {
2788 Consume(Token::PERIOD);
2789 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002790 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002791 result = new(zone()) Property(isolate(),
2792 result,
2793 NewLiteral(name),
2794 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002795 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002796 break;
2797 }
2798
2799 default:
2800 return result;
2801 }
2802 }
2803}
2804
2805
Steve Blocka7e24c12009-10-30 11:49:00 +00002806Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2807 // NewExpression ::
2808 // ('new')+ MemberExpression
2809
2810 // The grammar for new expressions is pretty warped. The keyword
2811 // 'new' can either be a part of the new expression (where it isn't
2812 // followed by an argument list) or a part of the member expression,
2813 // where it must be followed by an argument list. To accommodate
2814 // this, we parse the 'new' keywords greedily and keep track of how
2815 // many we have parsed. This information is then passed on to the
2816 // member expression parser, which is only allowed to match argument
2817 // lists as long as it has 'new' prefixes left
2818 Expect(Token::NEW, CHECK_OK);
2819 PositionStack::Element pos(stack, scanner().location().beg_pos);
2820
2821 Expression* result;
2822 if (peek() == Token::NEW) {
2823 result = ParseNewPrefix(stack, CHECK_OK);
2824 } else {
2825 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2826 }
2827
2828 if (!stack->is_empty()) {
2829 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002830 result = new(zone()) CallNew(isolate(),
2831 result,
Ben Murdoch257744e2011-11-30 15:57:28 +00002832 new(zone()) ZoneList<Expression*>(0),
2833 last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002834 }
2835 return result;
2836}
2837
2838
2839Expression* Parser::ParseNewExpression(bool* ok) {
2840 PositionStack stack(ok);
2841 return ParseNewPrefix(&stack, ok);
2842}
2843
2844
2845Expression* Parser::ParseMemberExpression(bool* ok) {
2846 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2847}
2848
2849
2850Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2851 bool* ok) {
2852 // MemberExpression ::
2853 // (PrimaryExpression | FunctionLiteral)
2854 // ('[' Expression ']' | '.' Identifier | Arguments)*
2855
2856 // Parse the initial primary or function expression.
2857 Expression* result = NULL;
2858 if (peek() == Token::FUNCTION) {
2859 Expect(Token::FUNCTION, CHECK_OK);
2860 int function_token_position = scanner().location().beg_pos;
2861 Handle<String> name;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002862 bool is_strict_reserved_name = false;
Steve Block1e0659c2011-05-24 12:43:12 +01002863 if (peek_any_identifier()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002864 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2865 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002866 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002867 FunctionLiteral::Type type = name.is_null()
2868 ? FunctionLiteral::ANONYMOUS_EXPRESSION
2869 : FunctionLiteral::NAMED_EXPRESSION;
2870 result = ParseFunctionLiteral(name,
2871 is_strict_reserved_name,
2872 function_token_position,
2873 type,
2874 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002875 } else {
2876 result = ParsePrimaryExpression(CHECK_OK);
2877 }
2878
2879 while (true) {
2880 switch (peek()) {
2881 case Token::LBRACK: {
2882 Consume(Token::LBRACK);
2883 int pos = scanner().location().beg_pos;
2884 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002885 result = new(zone()) Property(isolate(), result, index, pos);
2886 if (fni_ != NULL) {
2887 if (index->IsPropertyName()) {
2888 fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
2889 } else {
2890 fni_->PushLiteralName(
2891 isolate()->factory()->anonymous_function_symbol());
2892 }
2893 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002894 Expect(Token::RBRACK, CHECK_OK);
2895 break;
2896 }
2897 case Token::PERIOD: {
2898 Consume(Token::PERIOD);
2899 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002900 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002901 result = new(zone()) Property(isolate(),
2902 result,
2903 NewLiteral(name),
2904 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002905 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002906 break;
2907 }
2908 case Token::LPAREN: {
2909 if ((stack == NULL) || stack->is_empty()) return result;
2910 // Consume one of the new prefixes (already parsed).
2911 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2912 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002913 result = new(zone()) CallNew(isolate(), result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002914 break;
2915 }
2916 default:
2917 return result;
2918 }
2919 }
2920}
2921
2922
2923DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2924 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2925 // contexts this is used as a statement which invokes the debugger as i a
2926 // break point is present.
2927 // DebuggerStatement ::
2928 // 'debugger' ';'
2929
2930 Expect(Token::DEBUGGER, CHECK_OK);
2931 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002932 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002933}
2934
2935
2936void Parser::ReportUnexpectedToken(Token::Value token) {
2937 // We don't report stack overflows here, to avoid increasing the
2938 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002939 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002940 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002941 // Four of the tokens are treated specially
2942 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002943 case Token::EOS:
2944 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2945 case Token::NUMBER:
2946 return ReportMessage("unexpected_token_number",
2947 Vector<const char*>::empty());
2948 case Token::STRING:
2949 return ReportMessage("unexpected_token_string",
2950 Vector<const char*>::empty());
2951 case Token::IDENTIFIER:
2952 return ReportMessage("unexpected_token_identifier",
2953 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002954 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002955 return ReportMessage("unexpected_reserved",
2956 Vector<const char*>::empty());
2957 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Block44f0eee2011-05-26 01:26:41 +01002958 return ReportMessage(top_scope_->is_strict_mode() ?
Steve Block1e0659c2011-05-24 12:43:12 +01002959 "unexpected_strict_reserved" :
2960 "unexpected_token_identifier",
2961 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002962 default:
2963 const char* name = Token::String(token);
2964 ASSERT(name != NULL);
2965 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002966 }
2967}
2968
2969
Leon Clarkeac952652010-07-15 11:15:24 +01002970void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2971 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2972 const char* element[1] = { *name_string };
2973 ReportMessage("invalid_preparser_data",
2974 Vector<const char*>(element, 1));
2975 *ok = false;
2976}
2977
2978
Steve Blocka7e24c12009-10-30 11:49:00 +00002979Expression* Parser::ParsePrimaryExpression(bool* ok) {
2980 // PrimaryExpression ::
2981 // 'this'
2982 // 'null'
2983 // 'true'
2984 // 'false'
2985 // Identifier
2986 // Number
2987 // String
2988 // ArrayLiteral
2989 // ObjectLiteral
2990 // RegExpLiteral
2991 // '(' Expression ')'
2992
2993 Expression* result = NULL;
2994 switch (peek()) {
2995 case Token::THIS: {
2996 Consume(Token::THIS);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002997 result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00002998 break;
2999 }
3000
3001 case Token::NULL_LITERAL:
3002 Consume(Token::NULL_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003003 result = new(zone()) Literal(
3004 isolate(), isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003005 break;
3006
3007 case Token::TRUE_LITERAL:
3008 Consume(Token::TRUE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003009 result = new(zone()) Literal(
3010 isolate(), isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003011 break;
3012
3013 case Token::FALSE_LITERAL:
3014 Consume(Token::FALSE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003015 result = new(zone()) Literal(
3016 isolate(), isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003017 break;
3018
Steve Block1e0659c2011-05-24 12:43:12 +01003019 case Token::IDENTIFIER:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003020 case Token::FUTURE_STRICT_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003021 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003022 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003023 result = top_scope_->NewUnresolved(name,
3024 inside_with(),
3025 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003026 break;
3027 }
3028
3029 case Token::NUMBER: {
3030 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003031 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003032 double value = StringToDouble(isolate()->unicode_cache(),
3033 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003034 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003035 result = NewNumberLiteral(value);
3036 break;
3037 }
3038
3039 case Token::STRING: {
3040 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003041 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003042 result = NewLiteral(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003043 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00003044 break;
3045 }
3046
3047 case Token::ASSIGN_DIV:
3048 result = ParseRegExpLiteral(true, CHECK_OK);
3049 break;
3050
3051 case Token::DIV:
3052 result = ParseRegExpLiteral(false, CHECK_OK);
3053 break;
3054
3055 case Token::LBRACK:
3056 result = ParseArrayLiteral(CHECK_OK);
3057 break;
3058
3059 case Token::LBRACE:
3060 result = ParseObjectLiteral(CHECK_OK);
3061 break;
3062
3063 case Token::LPAREN:
3064 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003065 // Heuristically try to detect immediately called functions before
3066 // seeing the call parentheses.
3067 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00003068 result = ParseExpression(true, CHECK_OK);
3069 Expect(Token::RPAREN, CHECK_OK);
3070 break;
3071
3072 case Token::MOD:
3073 if (allow_natives_syntax_ || extension_ != NULL) {
3074 result = ParseV8Intrinsic(CHECK_OK);
3075 break;
3076 }
3077 // If we're not allowing special syntax we fall-through to the
3078 // default case.
3079
3080 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01003081 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00003082 ReportUnexpectedToken(tok);
3083 *ok = false;
3084 return NULL;
3085 }
3086 }
3087
3088 return result;
3089}
3090
3091
Leon Clarke4515c472010-02-03 11:58:03 +00003092void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
3093 Handle<FixedArray> literals,
3094 bool* is_simple,
3095 int* depth) {
3096 // Fill in the literals.
3097 // Accumulate output values in local variables.
3098 bool is_simple_acc = true;
3099 int depth_acc = 1;
3100 for (int i = 0; i < values->length(); i++) {
3101 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3102 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3103 depth_acc = m_literal->depth() + 1;
3104 }
3105 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3106 if (boilerplate_value->IsUndefined()) {
3107 literals->set_the_hole(i);
3108 is_simple_acc = false;
3109 } else {
3110 literals->set(i, *boilerplate_value);
3111 }
3112 }
3113
3114 *is_simple = is_simple_acc;
3115 *depth = depth_acc;
3116}
3117
3118
Steve Blocka7e24c12009-10-30 11:49:00 +00003119Expression* Parser::ParseArrayLiteral(bool* ok) {
3120 // ArrayLiteral ::
3121 // '[' Expression? (',' Expression?)* ']'
3122
Ben Murdoch257744e2011-11-30 15:57:28 +00003123 ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003124 Expect(Token::LBRACK, CHECK_OK);
3125 while (peek() != Token::RBRACK) {
3126 Expression* elem;
3127 if (peek() == Token::COMMA) {
3128 elem = GetLiteralTheHole();
3129 } else {
3130 elem = ParseAssignmentExpression(true, CHECK_OK);
3131 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003132 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003133 if (peek() != Token::RBRACK) {
3134 Expect(Token::COMMA, CHECK_OK);
3135 }
3136 }
3137 Expect(Token::RBRACK, CHECK_OK);
3138
3139 // Update the scope information before the pre-parsing bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003140 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003141
Steve Blocka7e24c12009-10-30 11:49:00 +00003142 // Allocate a fixed array with all the literals.
3143 Handle<FixedArray> literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003144 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003145
3146 // Fill in the literals.
3147 bool is_simple = true;
3148 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003149 for (int i = 0, n = values->length(); i < n; i++) {
3150 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003151 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3152 depth = m_literal->depth() + 1;
3153 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003154 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003155 if (boilerplate_value->IsUndefined()) {
3156 literals->set_the_hole(i);
3157 is_simple = false;
3158 } else {
3159 literals->set(i, *boilerplate_value);
3160 }
3161 }
3162
Iain Merrick75681382010-08-19 15:07:18 +01003163 // Simple and shallow arrays can be lazily copied, we transform the
3164 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003165 if (is_simple && depth == 1 && values->length() > 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01003166 literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003167 }
3168
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003169 return new(zone()) ArrayLiteral(
3170 isolate(), literals, values, literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003171}
3172
3173
3174bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3175 return property != NULL &&
3176 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3177}
3178
3179
3180bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003181 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003182 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3183 return lit != NULL && lit->is_simple();
3184}
3185
Iain Merrick75681382010-08-19 15:07:18 +01003186
3187bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3188 Expression* value) {
3189 // If value is a literal the property value is already set in the
3190 // boilerplate object.
3191 if (value->AsLiteral() != NULL) return false;
3192 // If value is a materialized literal the property value is already set
3193 // in the boilerplate object if it is simple.
3194 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3195 return true;
3196}
3197
3198
Steve Blocka7e24c12009-10-30 11:49:00 +00003199Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3200 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003201 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003202 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3203 if (object_literal != NULL) {
3204 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003205 if (object_literal->fast_elements()) {
3206 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3207 } else {
3208 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3209 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003210 result->set(kElementsSlot, *object_literal->constant_properties());
3211 } else {
3212 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3213 ASSERT(array_literal != NULL && array_literal->is_simple());
3214 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003215 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003216 }
3217 return result;
3218}
3219
3220
3221CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3222 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3223 return static_cast<Type>(type_value->value());
3224}
3225
3226
3227Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3228 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3229}
3230
3231
3232Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3233 if (expression->AsLiteral() != NULL) {
3234 return expression->AsLiteral()->handle();
3235 }
3236 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3237 return CompileTimeValue::GetValue(expression);
3238 }
Steve Block44f0eee2011-05-26 01:26:41 +01003239 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003240}
3241
Steve Block1e0659c2011-05-24 12:43:12 +01003242// Defined in ast.cc
3243bool IsEqualString(void* first, void* second);
3244bool IsEqualNumber(void* first, void* second);
3245
3246
3247// Validation per 11.1.5 Object Initialiser
3248class ObjectLiteralPropertyChecker {
3249 public:
3250 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3251 props(&IsEqualString),
3252 elems(&IsEqualNumber),
3253 parser_(parser),
3254 strict_(strict) {
3255 }
3256
3257 void CheckProperty(
3258 ObjectLiteral::Property* property,
3259 Scanner::Location loc,
3260 bool* ok);
3261
3262 private:
3263 enum PropertyKind {
3264 kGetAccessor = 0x01,
3265 kSetAccessor = 0x02,
3266 kAccessor = kGetAccessor | kSetAccessor,
3267 kData = 0x04
3268 };
3269
3270 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3271 switch (property->kind()) {
3272 case ObjectLiteral::Property::GETTER:
3273 return kGetAccessor;
3274 case ObjectLiteral::Property::SETTER:
3275 return kSetAccessor;
3276 default:
3277 return kData;
3278 }
3279 }
3280
3281 HashMap props;
3282 HashMap elems;
3283 Parser* parser_;
3284 bool strict_;
3285};
3286
3287
3288void ObjectLiteralPropertyChecker::CheckProperty(
3289 ObjectLiteral::Property* property,
3290 Scanner::Location loc,
3291 bool* ok) {
3292
3293 ASSERT(property != NULL);
3294
3295 Literal *lit = property->key();
3296 Handle<Object> handle = lit->handle();
3297
3298 uint32_t hash;
3299 HashMap* map;
3300 void* key;
3301
3302 if (handle->IsSymbol()) {
3303 Handle<String> name(String::cast(*handle));
3304 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003305 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003306 key = key_handle.location();
3307 map = &elems;
3308 } else {
3309 key = handle.location();
3310 hash = name->Hash();
3311 map = &props;
3312 }
3313 } else if (handle->ToArrayIndex(&hash)) {
3314 key = handle.location();
3315 map = &elems;
3316 } else {
3317 ASSERT(handle->IsNumber());
3318 double num = handle->Number();
3319 char arr[100];
3320 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3321 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003322 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003323 key = name.location();
3324 hash = name->Hash();
3325 map = &props;
3326 }
3327
3328 // Lookup property previously defined, if any.
3329 HashMap::Entry* entry = map->Lookup(key, hash, true);
3330 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3331 intptr_t curr = GetPropertyKind(property);
3332
3333 // Duplicate data properties are illegal in strict mode.
3334 if (strict_ && (curr & prev & kData) != 0) {
3335 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3336 Vector<const char*>::empty());
3337 *ok = false;
3338 return;
3339 }
3340 // Data property conflicting with an accessor.
3341 if (((curr & kData) && (prev & kAccessor)) ||
3342 ((prev & kData) && (curr & kAccessor))) {
3343 parser_->ReportMessageAt(loc, "accessor_data_property",
3344 Vector<const char*>::empty());
3345 *ok = false;
3346 return;
3347 }
3348 // Two accessors of the same type conflicting
3349 if ((curr & prev & kAccessor) != 0) {
3350 parser_->ReportMessageAt(loc, "accessor_get_set",
3351 Vector<const char*>::empty());
3352 *ok = false;
3353 return;
3354 }
3355
3356 // Update map
3357 entry->value = reinterpret_cast<void*> (prev | curr);
3358 *ok = true;
3359}
3360
Steve Blocka7e24c12009-10-30 11:49:00 +00003361
Leon Clarke4515c472010-02-03 11:58:03 +00003362void Parser::BuildObjectLiteralConstantProperties(
3363 ZoneList<ObjectLiteral::Property*>* properties,
3364 Handle<FixedArray> constant_properties,
3365 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003366 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003367 int* depth) {
3368 int position = 0;
3369 // Accumulate the value in local variables and store it at the end.
3370 bool is_simple_acc = true;
3371 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003372 uint32_t max_element_index = 0;
3373 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003374 for (int i = 0; i < properties->length(); i++) {
3375 ObjectLiteral::Property* property = properties->at(i);
3376 if (!IsBoilerplateProperty(property)) {
3377 is_simple_acc = false;
3378 continue;
3379 }
3380 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3381 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3382 depth_acc = m_literal->depth() + 1;
3383 }
3384
3385 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3386 // value for COMPUTED properties, the real value is filled in at
3387 // runtime. The enumeration order is maintained.
3388 Handle<Object> key = property->key()->handle();
3389 Handle<Object> value = GetBoilerplateValue(property->value());
3390 is_simple_acc = is_simple_acc && !value->IsUndefined();
3391
Steve Block6ded16b2010-05-10 14:33:55 +01003392 // Keep track of the number of elements in the object literal and
3393 // the largest element index. If the largest element index is
3394 // much larger than the number of elements, creating an object
3395 // literal with fast elements will be a waste of space.
3396 uint32_t element_index = 0;
3397 if (key->IsString()
3398 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3399 && element_index > max_element_index) {
3400 max_element_index = element_index;
3401 elements++;
3402 } else if (key->IsSmi()) {
3403 int key_value = Smi::cast(*key)->value();
3404 if (key_value > 0
3405 && static_cast<uint32_t>(key_value) > max_element_index) {
3406 max_element_index = key_value;
3407 }
3408 elements++;
3409 }
3410
Leon Clarke4515c472010-02-03 11:58:03 +00003411 // Add name, value pair to the fixed array.
3412 constant_properties->set(position++, *key);
3413 constant_properties->set(position++, *value);
3414 }
Steve Block6ded16b2010-05-10 14:33:55 +01003415 *fast_elements =
3416 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003417 *is_simple = is_simple_acc;
3418 *depth = depth_acc;
3419}
3420
3421
Ben Murdochbb769b22010-08-11 14:56:33 +01003422ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3423 bool* ok) {
3424 // Special handling of getter and setter syntax:
3425 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3426 // We have already read the "get" or "set" keyword.
3427 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003428 bool is_keyword = Token::IsKeyword(next);
3429 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003430 next == Token::FUTURE_RESERVED_WORD ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003431 next == Token::FUTURE_STRICT_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003432 next == Token::STRING || is_keyword) {
3433 Handle<String> name;
3434 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003435 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003436 } else {
3437 name = GetSymbol(CHECK_OK);
3438 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003439 FunctionLiteral* value =
3440 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003441 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003442 RelocInfo::kNoPosition,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003443 FunctionLiteral::ANONYMOUS_EXPRESSION,
Ben Murdochbb769b22010-08-11 14:56:33 +01003444 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003445 // Allow any number of parameters for compatiabilty with JSC.
3446 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003447 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003448 new(zone()) ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003449 return property;
3450 } else {
3451 ReportUnexpectedToken(next);
3452 *ok = false;
3453 return NULL;
3454 }
3455}
3456
3457
Steve Blocka7e24c12009-10-30 11:49:00 +00003458Expression* Parser::ParseObjectLiteral(bool* ok) {
3459 // ObjectLiteral ::
3460 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003461 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3462 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003463 // )*[','] '}'
3464
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003465 ZoneList<ObjectLiteral::Property*>* properties =
Ben Murdoch257744e2011-11-30 15:57:28 +00003466 new(zone()) ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003467 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003468 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003469
Steve Block44f0eee2011-05-26 01:26:41 +01003470 ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003471
Steve Blocka7e24c12009-10-30 11:49:00 +00003472 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003473
Steve Blocka7e24c12009-10-30 11:49:00 +00003474 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003475 if (fni_ != NULL) fni_->Enter();
3476
Steve Blocka7e24c12009-10-30 11:49:00 +00003477 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003478 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003479
3480 // Location of the property name token
3481 Scanner::Location loc = scanner().peek_location();
3482
Ben Murdochbb769b22010-08-11 14:56:33 +01003483 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003484 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003485 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003486 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003487 bool is_getter = false;
3488 bool is_setter = false;
3489 Handle<String> id =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003490 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003491 if (fni_ != NULL) fni_->PushLiteralName(id);
3492
Ben Murdochbb769b22010-08-11 14:56:33 +01003493 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003494 // Update loc to point to the identifier
3495 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003496 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003497 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3498 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003499 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003500 }
Steve Block1e0659c2011-05-24 12:43:12 +01003501 // Validate the property.
3502 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003503 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003504 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003505
3506 if (fni_ != NULL) {
3507 fni_->Infer();
3508 fni_->Leave();
3509 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003510 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003511 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003512 // Failed to parse as get/set property, so it's just a property
3513 // called "get" or "set".
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003514 key = NewLiteral(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003515 break;
3516 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003517 case Token::STRING: {
3518 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003519 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003520 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003521 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003522 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003523 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003524 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003525 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003526 key = NewLiteral(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003527 break;
3528 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003529 case Token::NUMBER: {
3530 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003531 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003532 double value = StringToDouble(isolate()->unicode_cache(),
3533 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003534 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003535 key = NewNumberLiteral(value);
3536 break;
3537 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003538 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003539 if (Token::IsKeyword(next)) {
3540 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003541 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003542 key = NewLiteral(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003543 } else {
3544 // Unexpected token.
3545 Token::Value next = Next();
3546 ReportUnexpectedToken(next);
3547 *ok = false;
3548 return NULL;
3549 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003550 }
3551
3552 Expect(Token::COLON, CHECK_OK);
3553 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3554
3555 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003556 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003557
Steve Block44f0eee2011-05-26 01:26:41 +01003558 // Mark object literals that contain function literals and pretenure the
3559 // literal so it can be added as a constant function property.
3560 if (value->AsFunctionLiteral() != NULL) {
3561 has_function = true;
3562 value->AsFunctionLiteral()->set_pretenure(true);
3563 }
3564
Steve Blocka7e24c12009-10-30 11:49:00 +00003565 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3566 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003567 // Validate the property
3568 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003569 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003570
3571 // TODO(1240767): Consider allowing trailing comma.
3572 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003573
3574 if (fni_ != NULL) {
3575 fni_->Infer();
3576 fni_->Leave();
3577 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003578 }
3579 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003580
Steve Blocka7e24c12009-10-30 11:49:00 +00003581 // Computation of literal_index must happen before pre parse bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003582 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003583
Steve Block44f0eee2011-05-26 01:26:41 +01003584 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3585 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003586
Steve Blocka7e24c12009-10-30 11:49:00 +00003587 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003588 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003589 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003590 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003591 constant_properties,
3592 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003593 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003594 &depth);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003595 return new(zone()) ObjectLiteral(isolate(),
3596 constant_properties,
3597 properties,
3598 literal_index,
3599 is_simple,
3600 fast_elements,
3601 depth,
3602 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003603}
3604
3605
3606Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003607 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003608 Next();
3609 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3610 *ok = false;
3611 return NULL;
3612 }
3613
Steve Block44f0eee2011-05-26 01:26:41 +01003614 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003615
Steve Block9fac8402011-05-12 15:51:54 +01003616 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003617 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003618 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003619 Next();
3620
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003621 return new(zone()) RegExpLiteral(
3622 isolate(), js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003623}
3624
3625
3626ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3627 // Arguments ::
3628 // '(' (AssignmentExpression)*[','] ')'
3629
Ben Murdoch257744e2011-11-30 15:57:28 +00003630 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003631 Expect(Token::LPAREN, CHECK_OK);
3632 bool done = (peek() == Token::RPAREN);
3633 while (!done) {
3634 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003635 result->Add(argument);
Steve Block053d10c2011-06-13 19:13:29 +01003636 if (result->length() > kMaxNumFunctionParameters) {
3637 ReportMessageAt(scanner().location(), "too_many_arguments",
3638 Vector<const char*>::empty());
3639 *ok = false;
3640 return NULL;
3641 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003642 done = (peek() == Token::RPAREN);
3643 if (!done) Expect(Token::COMMA, CHECK_OK);
3644 }
3645 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003646 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003647}
3648
3649
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003650FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
3651 bool name_is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003652 int function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003653 FunctionLiteral::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +00003654 bool* ok) {
3655 // Function ::
3656 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003657
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003658 // Anonymous functions were passed either the empty symbol or a null
3659 // handle as the function name. Remember if we were passed a non-empty
3660 // handle to decide whether to invoke function name inference.
3661 bool should_infer_name = function_name.is_null();
3662
3663 // We want a non-null handle as the function name.
3664 if (should_infer_name) {
3665 function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003666 }
3667
3668 int num_parameters = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003669 // Function declarations are hoisted.
3670 Scope* scope = (type == FunctionLiteral::DECLARATION)
3671 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false)
3672 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
Ben Murdoch257744e2011-11-30 15:57:28 +00003673 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003674 int materialized_literal_count;
3675 int expected_property_count;
3676 int start_pos;
3677 int end_pos;
3678 bool only_simple_this_property_assignments;
3679 Handle<FixedArray> this_property_assignments;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003680 bool has_duplicate_parameters = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 // Parse function body.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003682 { LexicalScope lexical_scope(this, scope, isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003683 top_scope_->SetScopeName(function_name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003684
3685 // FormalParameterList ::
3686 // '(' (Identifier)*[','] ')'
3687 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003688 start_pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00003689 Scanner::Location name_loc = Scanner::Location::invalid();
3690 Scanner::Location dupe_loc = Scanner::Location::invalid();
3691 Scanner::Location reserved_loc = Scanner::Location::invalid();
Steve Block1e0659c2011-05-24 12:43:12 +01003692
Steve Blocka7e24c12009-10-30 11:49:00 +00003693 bool done = (peek() == Token::RPAREN);
3694 while (!done) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003695 bool is_strict_reserved = false;
Steve Block1e0659c2011-05-24 12:43:12 +01003696 Handle<String> param_name =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003697 ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
3698 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003699
3700 // Store locations for possible future error reports.
3701 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3702 name_loc = scanner().location();
3703 }
3704 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003705 has_duplicate_parameters = true;
Steve Block1e0659c2011-05-24 12:43:12 +01003706 dupe_loc = scanner().location();
3707 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003708 if (!reserved_loc.IsValid() && is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01003709 reserved_loc = scanner().location();
3710 }
3711
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003712 top_scope_->DeclareParameter(param_name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003713 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003714 if (num_parameters > kMaxNumFunctionParameters) {
3715 ReportMessageAt(scanner().location(), "too_many_parameters",
3716 Vector<const char*>::empty());
3717 *ok = false;
3718 return NULL;
3719 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003720 done = (peek() == Token::RPAREN);
3721 if (!done) Expect(Token::COMMA, CHECK_OK);
3722 }
3723 Expect(Token::RPAREN, CHECK_OK);
3724
3725 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003726
3727 // If we have a named function expression, we add a local variable
3728 // declaration to the body of the function with the name of the
3729 // function and let it refer to the function itself (closure).
3730 // NOTE: We create a proxy and resolve it here so that in the
3731 // future we can change the AST to only refer to VariableProxies
3732 // instead of Variables and Proxis as is the case now.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003733 if (type == FunctionLiteral::NAMED_EXPRESSION) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003734 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3735 VariableProxy* fproxy =
3736 top_scope_->NewUnresolved(function_name, inside_with());
3737 fproxy->BindTo(fvar);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003738 body->Add(new(zone()) ExpressionStatement(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003739 new(zone()) Assignment(isolate(),
3740 Token::INIT_CONST,
3741 fproxy,
3742 new(zone()) ThisFunction(isolate()),
3743 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003744 }
3745
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003746 // Determine if the function will be lazily compiled. The mode can only
3747 // be PARSE_LAZILY if the --lazy flag is true. We will not lazily
3748 // compile if we do not have preparser data for the function.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003749 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3750 top_scope_->outer_scope()->is_global_scope() &&
3751 top_scope_->HasTrivialOuterContext() &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003752 !parenthesized_function_ &&
3753 pre_data() != NULL);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003754 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003755
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003756 if (is_lazily_compiled) {
3757 int function_block_pos = scanner().location().beg_pos;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003758 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003759 if (!entry.is_valid()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003760 // There is no preparser data for the function, we will not lazily
3761 // compile after all.
3762 is_lazily_compiled = false;
3763 } else {
3764 end_pos = entry.end_pos();
3765 if (end_pos <= function_block_pos) {
3766 // End position greater than end of stream is safe, and hard to check.
3767 ReportInvalidPreparseData(function_name, CHECK_OK);
3768 }
3769 isolate()->counters()->total_preparse_skipped()->Increment(
3770 end_pos - function_block_pos);
3771 // Seek to position just before terminal '}'.
3772 scanner().SeekForward(end_pos - 1);
3773 materialized_literal_count = entry.literal_count();
3774 expected_property_count = entry.property_count();
3775 if (entry.strict_mode()) top_scope_->EnableStrictMode();
3776 only_simple_this_property_assignments = false;
3777 this_property_assignments = isolate()->factory()->empty_fixed_array();
3778 Expect(Token::RBRACE, CHECK_OK);
Leon Clarkeac952652010-07-15 11:15:24 +01003779 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003780 }
3781
3782 if (!is_lazily_compiled) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003783 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3784
Steve Block44f0eee2011-05-26 01:26:41 +01003785 materialized_literal_count = lexical_scope.materialized_literal_count();
3786 expected_property_count = lexical_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003787 only_simple_this_property_assignments =
Steve Block44f0eee2011-05-26 01:26:41 +01003788 lexical_scope.only_simple_this_property_assignments();
3789 this_property_assignments = lexical_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003790
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003791 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003792 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003793 }
3794
Steve Block1e0659c2011-05-24 12:43:12 +01003795 // Validate strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01003796 if (top_scope_->is_strict_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003797 if (IsEvalOrArguments(function_name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01003798 int position = function_token_position != RelocInfo::kNoPosition
3799 ? function_token_position
3800 : (start_pos > 0 ? start_pos - 1 : start_pos);
3801 Scanner::Location location = Scanner::Location(position, start_pos);
3802 ReportMessageAt(location,
3803 "strict_function_name", Vector<const char*>::empty());
3804 *ok = false;
3805 return NULL;
3806 }
3807 if (name_loc.IsValid()) {
3808 ReportMessageAt(name_loc, "strict_param_name",
3809 Vector<const char*>::empty());
3810 *ok = false;
3811 return NULL;
3812 }
3813 if (dupe_loc.IsValid()) {
3814 ReportMessageAt(dupe_loc, "strict_param_dupe",
3815 Vector<const char*>::empty());
3816 *ok = false;
3817 return NULL;
3818 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003819 if (name_is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01003820 int position = function_token_position != RelocInfo::kNoPosition
3821 ? function_token_position
3822 : (start_pos > 0 ? start_pos - 1 : start_pos);
3823 Scanner::Location location = Scanner::Location(position, start_pos);
3824 ReportMessageAt(location, "strict_reserved_word",
3825 Vector<const char*>::empty());
3826 *ok = false;
3827 return NULL;
3828 }
3829 if (reserved_loc.IsValid()) {
3830 ReportMessageAt(reserved_loc, "strict_reserved_word",
3831 Vector<const char*>::empty());
3832 *ok = false;
3833 return NULL;
3834 }
3835 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3836 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003837 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003838
3839 FunctionLiteral* function_literal =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003840 new(zone()) FunctionLiteral(isolate(),
3841 function_name,
Ben Murdoch8b112d22011-06-08 16:22:53 +01003842 scope,
3843 body,
3844 materialized_literal_count,
3845 expected_property_count,
3846 only_simple_this_property_assignments,
3847 this_property_assignments,
3848 num_parameters,
3849 start_pos,
3850 end_pos,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003851 type,
3852 has_duplicate_parameters);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003853 function_literal->set_function_token_position(function_token_position);
3854
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003855 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003856 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00003857}
3858
3859
3860Expression* Parser::ParseV8Intrinsic(bool* ok) {
3861 // CallRuntime ::
3862 // '%' Identifier Arguments
3863
3864 Expect(Token::MOD, CHECK_OK);
3865 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003866 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003867
3868 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003869 // The extension structures are only accessible while parsing the
3870 // very first time not when reparsing because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003871 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00003872 }
3873
Steve Block44f0eee2011-05-26 01:26:41 +01003874 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003875
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003876 // Check for built-in IS_VAR macro.
3877 if (function != NULL &&
3878 function->intrinsic_type == Runtime::RUNTIME &&
3879 function->function_id == Runtime::kIS_VAR) {
3880 // %IS_VAR(x) evaluates to x if x is a variable,
3881 // leads to a parse error otherwise. Could be implemented as an
3882 // inline function %_IS_VAR(x) to eliminate this special case.
3883 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3884 return args->at(0);
3885 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003886 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003887 *ok = false;
3888 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003889 }
3890 }
3891
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003892 // Check that the expected number of arguments are being passed.
3893 if (function != NULL &&
3894 function->nargs != -1 &&
3895 function->nargs != args->length()) {
3896 ReportMessage("illegal_access", Vector<const char*>::empty());
3897 *ok = false;
3898 return NULL;
3899 }
3900
3901 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003902 return new(zone()) CallRuntime(isolate(), name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003903}
3904
3905
Steve Block1e0659c2011-05-24 12:43:12 +01003906bool Parser::peek_any_identifier() {
3907 Token::Value next = peek();
3908 return next == Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003909 next == Token::FUTURE_RESERVED_WORD ||
3910 next == Token::FUTURE_STRICT_RESERVED_WORD;
Steve Block1e0659c2011-05-24 12:43:12 +01003911}
3912
3913
Steve Blocka7e24c12009-10-30 11:49:00 +00003914void Parser::Consume(Token::Value token) {
3915 Token::Value next = Next();
3916 USE(next);
3917 USE(token);
3918 ASSERT(next == token);
3919}
3920
3921
3922void Parser::Expect(Token::Value token, bool* ok) {
3923 Token::Value next = Next();
3924 if (next == token) return;
3925 ReportUnexpectedToken(next);
3926 *ok = false;
3927}
3928
3929
Leon Clarke4515c472010-02-03 11:58:03 +00003930bool Parser::Check(Token::Value token) {
3931 Token::Value next = peek();
3932 if (next == token) {
3933 Consume(next);
3934 return true;
3935 }
3936 return false;
3937}
3938
3939
Steve Blocka7e24c12009-10-30 11:49:00 +00003940void Parser::ExpectSemicolon(bool* ok) {
3941 // Check for automatic semicolon insertion according to
3942 // the rules given in ECMA-262, section 7.9, page 21.
3943 Token::Value tok = peek();
3944 if (tok == Token::SEMICOLON) {
3945 Next();
3946 return;
3947 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003948 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003949 tok == Token::RBRACE ||
3950 tok == Token::EOS) {
3951 return;
3952 }
3953 Expect(Token::SEMICOLON, ok);
3954}
3955
3956
3957Literal* Parser::GetLiteralUndefined() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003958 return NewLiteral(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003959}
3960
3961
3962Literal* Parser::GetLiteralTheHole() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003963 return NewLiteral(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003964}
3965
3966
3967Literal* Parser::GetLiteralNumber(double value) {
3968 return NewNumberLiteral(value);
3969}
3970
3971
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003972// Parses and identifier that is valid for the current scope, in particular it
3973// fails on strict mode future reserved keywords in a strict scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00003974Handle<String> Parser::ParseIdentifier(bool* ok) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003975 if (top_scope_->is_strict_mode()) {
3976 Expect(Token::IDENTIFIER, ok);
3977 } else if (!Check(Token::IDENTIFIER)) {
3978 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
3979 }
3980 if (!*ok) return Handle<String>();
3981 return GetSymbol(ok);
Steve Block1e0659c2011-05-24 12:43:12 +01003982}
3983
3984
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003985// Parses and identifier or a strict mode future reserved word, and indicate
3986// whether it is strict mode future reserved.
3987Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
3988 bool* is_strict_reserved, bool* ok) {
3989 *is_strict_reserved = false;
3990 if (!Check(Token::IDENTIFIER)) {
3991 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
3992 *is_strict_reserved = true;
Steve Block1e0659c2011-05-24 12:43:12 +01003993 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003994 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003995 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003996}
3997
Ben Murdochbb769b22010-08-11 14:56:33 +01003998
3999Handle<String> Parser::ParseIdentifierName(bool* ok) {
4000 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01004001 if (next != Token::IDENTIFIER &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004002 next != Token::FUTURE_RESERVED_WORD &&
4003 next != Token::FUTURE_STRICT_RESERVED_WORD &&
4004 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01004005 ReportUnexpectedToken(next);
4006 *ok = false;
4007 return Handle<String>();
4008 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01004009 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01004010}
4011
4012
Steve Block1e0659c2011-05-24 12:43:12 +01004013// Checks LHS expression for assignment and prefix/postfix increment/decrement
4014// in strict mode.
4015void Parser::CheckStrictModeLValue(Expression* expression,
4016 const char* error,
4017 bool* ok) {
Steve Block44f0eee2011-05-26 01:26:41 +01004018 ASSERT(top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01004019 VariableProxy* lhs = expression != NULL
4020 ? expression->AsVariableProxy()
4021 : NULL;
4022
4023 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
4024 ReportMessage(error, Vector<const char*>::empty());
4025 *ok = false;
4026 }
4027}
4028
4029
Ben Murdoch257744e2011-11-30 15:57:28 +00004030// Checks whether an octal literal was last seen between beg_pos and end_pos.
4031// If so, reports an error. Only called for strict mode.
Steve Block1e0659c2011-05-24 12:43:12 +01004032void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004033 Scanner::Location octal = scanner().octal_position();
4034 if (octal.IsValid() &&
4035 beg_pos <= octal.beg_pos &&
4036 octal.end_pos <= end_pos) {
4037 ReportMessageAt(octal, "strict_octal_literal",
Steve Block1e0659c2011-05-24 12:43:12 +01004038 Vector<const char*>::empty());
4039 scanner().clear_octal_position();
4040 *ok = false;
4041 }
4042}
4043
4044
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004045// This function reads an identifier name and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01004046// is 'get' or 'set'.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004047Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
4048 bool* is_set,
4049 bool* ok) {
4050 Handle<String> result = ParseIdentifierName(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004051 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01004052 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
4053 const char* token = scanner().literal_ascii_string().start();
4054 *is_get = strncmp(token, "get", 3) == 0;
4055 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00004056 }
Steve Block1e0659c2011-05-24 12:43:12 +01004057 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00004058}
4059
4060
4061// ----------------------------------------------------------------------------
4062// Parser support
4063
4064
4065bool Parser::TargetStackContainsLabel(Handle<String> label) {
4066 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4067 BreakableStatement* stat = t->node()->AsBreakableStatement();
4068 if (stat != NULL && ContainsLabel(stat->labels(), label))
4069 return true;
4070 }
4071 return false;
4072}
4073
4074
4075BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
4076 bool anonymous = label.is_null();
4077 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4078 BreakableStatement* stat = t->node()->AsBreakableStatement();
4079 if (stat == NULL) continue;
4080 if ((anonymous && stat->is_target_for_anonymous()) ||
4081 (!anonymous && ContainsLabel(stat->labels(), label))) {
4082 RegisterTargetUse(stat->break_target(), t->previous());
4083 return stat;
4084 }
4085 }
4086 return NULL;
4087}
4088
4089
4090IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
4091 bool* ok) {
4092 bool anonymous = label.is_null();
4093 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4094 IterationStatement* stat = t->node()->AsIterationStatement();
4095 if (stat == NULL) continue;
4096
4097 ASSERT(stat->is_target_for_anonymous());
4098 if (anonymous || ContainsLabel(stat->labels(), label)) {
4099 RegisterTargetUse(stat->continue_target(), t->previous());
4100 return stat;
4101 }
4102 }
4103 return NULL;
4104}
4105
4106
Ben Murdoch8b112d22011-06-08 16:22:53 +01004107void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004108 // Register that a break target found at the given stop in the
4109 // target stack has been used from the top of the target stack. Add
4110 // the break target to any TargetCollectors passed on the stack.
4111 for (Target* t = target_stack_; t != stop; t = t->previous()) {
4112 TargetCollector* collector = t->node()->AsTargetCollector();
4113 if (collector != NULL) collector->AddTarget(target);
4114 }
4115}
4116
4117
4118Literal* Parser::NewNumberLiteral(double number) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004119 return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00004120}
4121
4122
4123Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01004124 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00004125 type, HandleVector<Object>(NULL, 0));
4126}
4127
4128
4129Expression* Parser::NewThrowSyntaxError(Handle<String> type,
4130 Handle<Object> first) {
4131 int argc = first.is_null() ? 0 : 1;
4132 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01004133 return NewThrowError(
4134 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004135}
4136
4137
4138Expression* Parser::NewThrowTypeError(Handle<String> type,
4139 Handle<Object> first,
4140 Handle<Object> second) {
4141 ASSERT(!first.is_null() && !second.is_null());
4142 Handle<Object> elements[] = { first, second };
4143 Vector< Handle<Object> > arguments =
4144 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01004145 return NewThrowError(
4146 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004147}
4148
4149
4150Expression* Parser::NewThrowError(Handle<String> constructor,
4151 Handle<String> type,
4152 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004153 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01004154 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4155 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004156 for (int i = 0; i < argc; i++) {
4157 Handle<Object> element = arguments[i];
4158 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01004159 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00004160 }
4161 }
Steve Block44f0eee2011-05-26 01:26:41 +01004162 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
4163 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01004164
Ben Murdoch257744e2011-11-30 15:57:28 +00004165 ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004166 args->Add(NewLiteral(type));
4167 args->Add(NewLiteral(array));
4168 CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
4169 constructor,
4170 NULL,
4171 args);
4172 return new(zone()) Throw(isolate(),
4173 call_constructor,
4174 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004175}
4176
Leon Clarke4515c472010-02-03 11:58:03 +00004177// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004178// Regular expressions
4179
4180
4181RegExpParser::RegExpParser(FlatStringReader* in,
4182 Handle<String>* error,
4183 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004184 : isolate_(Isolate::Current()),
4185 error_(error),
4186 captures_(NULL),
4187 in_(in),
4188 current_(kEndMarker),
4189 next_pos_(0),
4190 capture_count_(0),
4191 has_more_(true),
4192 multiline_(multiline),
4193 simple_(false),
4194 contains_anchor_(false),
4195 is_scanned_for_captures_(false),
4196 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004197 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004198}
4199
4200
4201uc32 RegExpParser::Next() {
4202 if (has_next()) {
4203 return in()->Get(next_pos_);
4204 } else {
4205 return kEndMarker;
4206 }
4207}
4208
4209
4210void RegExpParser::Advance() {
4211 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004212 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004213 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004214 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4215 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004216 ReportError(CStrVector("Regular expression too large"));
4217 } else {
4218 current_ = in()->Get(next_pos_);
4219 next_pos_++;
4220 }
4221 } else {
4222 current_ = kEndMarker;
4223 has_more_ = false;
4224 }
4225}
4226
4227
4228void RegExpParser::Reset(int pos) {
4229 next_pos_ = pos;
4230 Advance();
4231}
4232
4233
4234void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004235 next_pos_ += dist - 1;
4236 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004237}
4238
4239
4240bool RegExpParser::simple() {
4241 return simple_;
4242}
4243
4244RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4245 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004246 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004247 // Zip to the end to make sure the no more input is read.
4248 current_ = kEndMarker;
4249 next_pos_ = in()->length();
4250 return NULL;
4251}
4252
4253
4254// Pattern ::
4255// Disjunction
4256RegExpTree* RegExpParser::ParsePattern() {
4257 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4258 ASSERT(!has_more());
4259 // If the result of parsing is a literal string atom, and it has the
4260 // same length as the input, then the atom is identical to the input.
4261 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4262 simple_ = true;
4263 }
4264 return result;
4265}
4266
4267
4268// Disjunction ::
4269// Alternative
4270// Alternative | Disjunction
4271// Alternative ::
4272// [empty]
4273// Term Alternative
4274// Term ::
4275// Assertion
4276// Atom
4277// Atom Quantifier
4278RegExpTree* RegExpParser::ParseDisjunction() {
4279 // Used to store current state while parsing subexpressions.
4280 RegExpParserState initial_state(NULL, INITIAL, 0);
4281 RegExpParserState* stored_state = &initial_state;
4282 // Cache the builder in a local variable for quick access.
4283 RegExpBuilder* builder = initial_state.builder();
4284 while (true) {
4285 switch (current()) {
4286 case kEndMarker:
4287 if (stored_state->IsSubexpression()) {
4288 // Inside a parenthesized group when hitting end of input.
4289 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4290 }
4291 ASSERT_EQ(INITIAL, stored_state->group_type());
4292 // Parsing completed successfully.
4293 return builder->ToRegExp();
4294 case ')': {
4295 if (!stored_state->IsSubexpression()) {
4296 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4297 }
4298 ASSERT_NE(INITIAL, stored_state->group_type());
4299
4300 Advance();
4301 // End disjunction parsing and convert builder content to new single
4302 // regexp atom.
4303 RegExpTree* body = builder->ToRegExp();
4304
4305 int end_capture_index = captures_started();
4306
4307 int capture_index = stored_state->capture_index();
4308 SubexpressionType type = stored_state->group_type();
4309
4310 // Restore previous state.
4311 stored_state = stored_state->previous_state();
4312 builder = stored_state->builder();
4313
4314 // Build result of subexpression.
4315 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004316 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004317 captures_->at(capture_index - 1) = capture;
4318 body = capture;
4319 } else if (type != GROUPING) {
4320 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4321 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004322 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004323 is_positive,
4324 end_capture_index - capture_index,
4325 capture_index);
4326 }
4327 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004328 // For compatability with JSC and ES3, we allow quantifiers after
4329 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004330 break;
4331 }
4332 case '|': {
4333 Advance();
4334 builder->NewAlternative();
4335 continue;
4336 }
4337 case '*':
4338 case '+':
4339 case '?':
4340 return ReportError(CStrVector("Nothing to repeat"));
4341 case '^': {
4342 Advance();
4343 if (multiline_) {
4344 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004345 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004346 } else {
4347 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004348 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004349 set_contains_anchor();
4350 }
4351 continue;
4352 }
4353 case '$': {
4354 Advance();
4355 RegExpAssertion::Type type =
4356 multiline_ ? RegExpAssertion::END_OF_LINE :
4357 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004358 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004359 continue;
4360 }
4361 case '.': {
4362 Advance();
4363 // everything except \x0a, \x0d, \u2028 and \u2029
Ben Murdoch257744e2011-11-30 15:57:28 +00004364 ZoneList<CharacterRange>* ranges =
4365 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004366 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004367 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004368 builder->AddAtom(atom);
4369 break;
4370 }
4371 case '(': {
4372 SubexpressionType type = CAPTURE;
4373 Advance();
4374 if (current() == '?') {
4375 switch (Next()) {
4376 case ':':
4377 type = GROUPING;
4378 break;
4379 case '=':
4380 type = POSITIVE_LOOKAHEAD;
4381 break;
4382 case '!':
4383 type = NEGATIVE_LOOKAHEAD;
4384 break;
4385 default:
4386 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4387 break;
4388 }
4389 Advance(2);
4390 } else {
4391 if (captures_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004392 captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004393 }
4394 if (captures_started() >= kMaxCaptures) {
4395 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4396 }
4397 captures_->Add(NULL);
4398 }
4399 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004400 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004401 type,
4402 captures_started());
4403 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004404 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004405 }
4406 case '[': {
4407 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4408 builder->AddAtom(atom);
4409 break;
4410 }
4411 // Atom ::
4412 // \ AtomEscape
4413 case '\\':
4414 switch (Next()) {
4415 case kEndMarker:
4416 return ReportError(CStrVector("\\ at end of pattern"));
4417 case 'b':
4418 Advance(2);
4419 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004420 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004421 continue;
4422 case 'B':
4423 Advance(2);
4424 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004425 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004426 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004427 // AtomEscape ::
4428 // CharacterClassEscape
4429 //
4430 // CharacterClassEscape :: one of
4431 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004432 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4433 uc32 c = Next();
4434 Advance(2);
Ben Murdoch257744e2011-11-30 15:57:28 +00004435 ZoneList<CharacterRange>* ranges =
4436 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004437 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004438 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004439 builder->AddAtom(atom);
4440 break;
4441 }
4442 case '1': case '2': case '3': case '4': case '5': case '6':
4443 case '7': case '8': case '9': {
4444 int index = 0;
4445 if (ParseBackReferenceIndex(&index)) {
4446 RegExpCapture* capture = NULL;
4447 if (captures_ != NULL && index <= captures_->length()) {
4448 capture = captures_->at(index - 1);
4449 }
4450 if (capture == NULL) {
4451 builder->AddEmpty();
4452 break;
4453 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004454 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004455 builder->AddAtom(atom);
4456 break;
4457 }
4458 uc32 first_digit = Next();
4459 if (first_digit == '8' || first_digit == '9') {
4460 // Treat as identity escape
4461 builder->AddCharacter(first_digit);
4462 Advance(2);
4463 break;
4464 }
4465 }
4466 // FALLTHROUGH
4467 case '0': {
4468 Advance();
4469 uc32 octal = ParseOctalLiteral();
4470 builder->AddCharacter(octal);
4471 break;
4472 }
4473 // ControlEscape :: one of
4474 // f n r t v
4475 case 'f':
4476 Advance(2);
4477 builder->AddCharacter('\f');
4478 break;
4479 case 'n':
4480 Advance(2);
4481 builder->AddCharacter('\n');
4482 break;
4483 case 'r':
4484 Advance(2);
4485 builder->AddCharacter('\r');
4486 break;
4487 case 't':
4488 Advance(2);
4489 builder->AddCharacter('\t');
4490 break;
4491 case 'v':
4492 Advance(2);
4493 builder->AddCharacter('\v');
4494 break;
4495 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004496 Advance();
4497 uc32 controlLetter = Next();
4498 // Special case if it is an ASCII letter.
4499 // Convert lower case letters to uppercase.
4500 uc32 letter = controlLetter & ~('a' ^ 'A');
4501 if (letter < 'A' || 'Z' < letter) {
4502 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4503 // This is outside the specification. We match JSC in
4504 // reading the backslash as a literal character instead
4505 // of as starting an escape.
4506 builder->AddCharacter('\\');
4507 } else {
4508 Advance(2);
4509 builder->AddCharacter(controlLetter & 0x1f);
4510 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004511 break;
4512 }
4513 case 'x': {
4514 Advance(2);
4515 uc32 value;
4516 if (ParseHexEscape(2, &value)) {
4517 builder->AddCharacter(value);
4518 } else {
4519 builder->AddCharacter('x');
4520 }
4521 break;
4522 }
4523 case 'u': {
4524 Advance(2);
4525 uc32 value;
4526 if (ParseHexEscape(4, &value)) {
4527 builder->AddCharacter(value);
4528 } else {
4529 builder->AddCharacter('u');
4530 }
4531 break;
4532 }
4533 default:
4534 // Identity escape.
4535 builder->AddCharacter(Next());
4536 Advance(2);
4537 break;
4538 }
4539 break;
4540 case '{': {
4541 int dummy;
4542 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4543 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4544 }
4545 // fallthrough
4546 }
4547 default:
4548 builder->AddCharacter(current());
4549 Advance();
4550 break;
4551 } // end switch(current())
4552
4553 int min;
4554 int max;
4555 switch (current()) {
4556 // QuantifierPrefix ::
4557 // *
4558 // +
4559 // ?
4560 // {
4561 case '*':
4562 min = 0;
4563 max = RegExpTree::kInfinity;
4564 Advance();
4565 break;
4566 case '+':
4567 min = 1;
4568 max = RegExpTree::kInfinity;
4569 Advance();
4570 break;
4571 case '?':
4572 min = 0;
4573 max = 1;
4574 Advance();
4575 break;
4576 case '{':
4577 if (ParseIntervalQuantifier(&min, &max)) {
4578 if (max < min) {
4579 ReportError(CStrVector("numbers out of order in {} quantifier.")
4580 CHECK_FAILED);
4581 }
4582 break;
4583 } else {
4584 continue;
4585 }
4586 default:
4587 continue;
4588 }
Leon Clarkee46be812010-01-19 14:06:41 +00004589 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004590 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004591 type = RegExpQuantifier::NON_GREEDY;
4592 Advance();
4593 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4594 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4595 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004596 Advance();
4597 }
Leon Clarkee46be812010-01-19 14:06:41 +00004598 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004599 }
4600}
4601
Steve Blocka7e24c12009-10-30 11:49:00 +00004602
4603#ifdef DEBUG
4604// Currently only used in an ASSERT.
4605static bool IsSpecialClassEscape(uc32 c) {
4606 switch (c) {
4607 case 'd': case 'D':
4608 case 's': case 'S':
4609 case 'w': case 'W':
4610 return true;
4611 default:
4612 return false;
4613 }
4614}
4615#endif
4616
4617
4618// In order to know whether an escape is a backreference or not we have to scan
4619// the entire regexp and find the number of capturing parentheses. However we
4620// don't want to scan the regexp twice unless it is necessary. This mini-parser
4621// is called when needed. It can see the difference between capturing and
4622// noncapturing parentheses and can skip character classes and backslash-escaped
4623// characters.
4624void RegExpParser::ScanForCaptures() {
4625 // Start with captures started previous to current position
4626 int capture_count = captures_started();
4627 // Add count of captures after this position.
4628 int n;
4629 while ((n = current()) != kEndMarker) {
4630 Advance();
4631 switch (n) {
4632 case '\\':
4633 Advance();
4634 break;
4635 case '[': {
4636 int c;
4637 while ((c = current()) != kEndMarker) {
4638 Advance();
4639 if (c == '\\') {
4640 Advance();
4641 } else {
4642 if (c == ']') break;
4643 }
4644 }
4645 break;
4646 }
4647 case '(':
4648 if (current() != '?') capture_count++;
4649 break;
4650 }
4651 }
4652 capture_count_ = capture_count;
4653 is_scanned_for_captures_ = true;
4654}
4655
4656
4657bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4658 ASSERT_EQ('\\', current());
4659 ASSERT('1' <= Next() && Next() <= '9');
4660 // Try to parse a decimal literal that is no greater than the total number
4661 // of left capturing parentheses in the input.
4662 int start = position();
4663 int value = Next() - '0';
4664 Advance(2);
4665 while (true) {
4666 uc32 c = current();
4667 if (IsDecimalDigit(c)) {
4668 value = 10 * value + (c - '0');
4669 if (value > kMaxCaptures) {
4670 Reset(start);
4671 return false;
4672 }
4673 Advance();
4674 } else {
4675 break;
4676 }
4677 }
4678 if (value > captures_started()) {
4679 if (!is_scanned_for_captures_) {
4680 int saved_position = position();
4681 ScanForCaptures();
4682 Reset(saved_position);
4683 }
4684 if (value > capture_count_) {
4685 Reset(start);
4686 return false;
4687 }
4688 }
4689 *index_out = value;
4690 return true;
4691}
4692
4693
4694// QuantifierPrefix ::
4695// { DecimalDigits }
4696// { DecimalDigits , }
4697// { DecimalDigits , DecimalDigits }
4698//
4699// Returns true if parsing succeeds, and set the min_out and max_out
4700// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4701bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4702 ASSERT_EQ(current(), '{');
4703 int start = position();
4704 Advance();
4705 int min = 0;
4706 if (!IsDecimalDigit(current())) {
4707 Reset(start);
4708 return false;
4709 }
4710 while (IsDecimalDigit(current())) {
4711 int next = current() - '0';
4712 if (min > (RegExpTree::kInfinity - next) / 10) {
4713 // Overflow. Skip past remaining decimal digits and return -1.
4714 do {
4715 Advance();
4716 } while (IsDecimalDigit(current()));
4717 min = RegExpTree::kInfinity;
4718 break;
4719 }
4720 min = 10 * min + next;
4721 Advance();
4722 }
4723 int max = 0;
4724 if (current() == '}') {
4725 max = min;
4726 Advance();
4727 } else if (current() == ',') {
4728 Advance();
4729 if (current() == '}') {
4730 max = RegExpTree::kInfinity;
4731 Advance();
4732 } else {
4733 while (IsDecimalDigit(current())) {
4734 int next = current() - '0';
4735 if (max > (RegExpTree::kInfinity - next) / 10) {
4736 do {
4737 Advance();
4738 } while (IsDecimalDigit(current()));
4739 max = RegExpTree::kInfinity;
4740 break;
4741 }
4742 max = 10 * max + next;
4743 Advance();
4744 }
4745 if (current() != '}') {
4746 Reset(start);
4747 return false;
4748 }
4749 Advance();
4750 }
4751 } else {
4752 Reset(start);
4753 return false;
4754 }
4755 *min_out = min;
4756 *max_out = max;
4757 return true;
4758}
4759
4760
Steve Blocka7e24c12009-10-30 11:49:00 +00004761uc32 RegExpParser::ParseOctalLiteral() {
4762 ASSERT('0' <= current() && current() <= '7');
4763 // For compatibility with some other browsers (not all), we parse
4764 // up to three octal digits with a value below 256.
4765 uc32 value = current() - '0';
4766 Advance();
4767 if ('0' <= current() && current() <= '7') {
4768 value = value * 8 + current() - '0';
4769 Advance();
4770 if (value < 32 && '0' <= current() && current() <= '7') {
4771 value = value * 8 + current() - '0';
4772 Advance();
4773 }
4774 }
4775 return value;
4776}
4777
4778
4779bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4780 int start = position();
4781 uc32 val = 0;
4782 bool done = false;
4783 for (int i = 0; !done; i++) {
4784 uc32 c = current();
4785 int d = HexValue(c);
4786 if (d < 0) {
4787 Reset(start);
4788 return false;
4789 }
4790 val = val * 16 + d;
4791 Advance();
4792 if (i == length - 1) {
4793 done = true;
4794 }
4795 }
4796 *value = val;
4797 return true;
4798}
4799
4800
4801uc32 RegExpParser::ParseClassCharacterEscape() {
4802 ASSERT(current() == '\\');
4803 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4804 Advance();
4805 switch (current()) {
4806 case 'b':
4807 Advance();
4808 return '\b';
4809 // ControlEscape :: one of
4810 // f n r t v
4811 case 'f':
4812 Advance();
4813 return '\f';
4814 case 'n':
4815 Advance();
4816 return '\n';
4817 case 'r':
4818 Advance();
4819 return '\r';
4820 case 't':
4821 Advance();
4822 return '\t';
4823 case 'v':
4824 Advance();
4825 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004826 case 'c': {
4827 uc32 controlLetter = Next();
4828 uc32 letter = controlLetter & ~('A' ^ 'a');
4829 // For compatibility with JSC, inside a character class
4830 // we also accept digits and underscore as control characters.
4831 if ((controlLetter >= '0' && controlLetter <= '9') ||
4832 controlLetter == '_' ||
4833 (letter >= 'A' && letter <= 'Z')) {
4834 Advance(2);
4835 // Control letters mapped to ASCII control characters in the range
4836 // 0x00-0x1f.
4837 return controlLetter & 0x1f;
4838 }
4839 // We match JSC in reading the backslash as a literal
4840 // character instead of as starting an escape.
4841 return '\\';
4842 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004843 case '0': case '1': case '2': case '3': case '4': case '5':
4844 case '6': case '7':
4845 // For compatibility, we interpret a decimal escape that isn't
4846 // a back reference (and therefore either \0 or not valid according
4847 // to the specification) as a 1..3 digit octal character code.
4848 return ParseOctalLiteral();
4849 case 'x': {
4850 Advance();
4851 uc32 value;
4852 if (ParseHexEscape(2, &value)) {
4853 return value;
4854 }
4855 // If \x is not followed by a two-digit hexadecimal, treat it
4856 // as an identity escape.
4857 return 'x';
4858 }
4859 case 'u': {
4860 Advance();
4861 uc32 value;
4862 if (ParseHexEscape(4, &value)) {
4863 return value;
4864 }
4865 // If \u is not followed by a four-digit hexadecimal, treat it
4866 // as an identity escape.
4867 return 'u';
4868 }
4869 default: {
4870 // Extended identity escape. We accept any character that hasn't
4871 // been matched by a more specific case, not just the subset required
4872 // by the ECMAScript specification.
4873 uc32 result = current();
4874 Advance();
4875 return result;
4876 }
4877 }
4878 return 0;
4879}
4880
4881
4882CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4883 ASSERT_EQ(0, *char_class);
4884 uc32 first = current();
4885 if (first == '\\') {
4886 switch (Next()) {
4887 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4888 *char_class = Next();
4889 Advance(2);
4890 return CharacterRange::Singleton(0); // Return dummy value.
4891 }
4892 case kEndMarker:
4893 return ReportError(CStrVector("\\ at end of pattern"));
4894 default:
4895 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4896 return CharacterRange::Singleton(c);
4897 }
4898 } else {
4899 Advance();
4900 return CharacterRange::Singleton(first);
4901 }
4902}
4903
4904
Ben Murdochb0fe1622011-05-05 13:52:32 +01004905static const uc16 kNoCharClass = 0;
4906
4907// Adds range or pre-defined character class to character ranges.
4908// If char_class is not kInvalidClass, it's interpreted as a class
4909// escape (i.e., 's' means whitespace, from '\s').
4910static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4911 uc16 char_class,
4912 CharacterRange range) {
4913 if (char_class != kNoCharClass) {
4914 CharacterRange::AddClassEscape(char_class, ranges);
4915 } else {
4916 ranges->Add(range);
4917 }
4918}
4919
4920
Steve Blocka7e24c12009-10-30 11:49:00 +00004921RegExpTree* RegExpParser::ParseCharacterClass() {
4922 static const char* kUnterminated = "Unterminated character class";
4923 static const char* kRangeOutOfOrder = "Range out of order in character class";
4924
4925 ASSERT_EQ(current(), '[');
4926 Advance();
4927 bool is_negated = false;
4928 if (current() == '^') {
4929 is_negated = true;
4930 Advance();
4931 }
Ben Murdoch257744e2011-11-30 15:57:28 +00004932 ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004933 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004934 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004935 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004936 if (current() == '-') {
4937 Advance();
4938 if (current() == kEndMarker) {
4939 // If we reach the end we break out of the loop and let the
4940 // following code report an error.
4941 break;
4942 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004943 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004944 ranges->Add(CharacterRange::Singleton('-'));
4945 break;
4946 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004947 uc16 char_class_2 = kNoCharClass;
4948 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4949 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4950 // Either end is an escaped character class. Treat the '-' verbatim.
4951 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004952 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004953 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004954 continue;
4955 }
4956 if (first.from() > next.to()) {
4957 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4958 }
4959 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4960 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004961 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004962 }
4963 }
4964 if (!has_more()) {
4965 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4966 }
4967 Advance();
4968 if (ranges->length() == 0) {
4969 ranges->Add(CharacterRange::Everything());
4970 is_negated = !is_negated;
4971 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004972 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00004973}
4974
4975
4976// ----------------------------------------------------------------------------
4977// The Parser interface.
4978
Steve Blocka7e24c12009-10-30 11:49:00 +00004979ParserMessage::~ParserMessage() {
4980 for (int i = 0; i < args().length(); i++)
4981 DeleteArray(args()[i]);
4982 DeleteArray(args().start());
4983}
4984
4985
4986ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004987 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004988}
4989
4990
4991int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004992 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004993}
4994
4995
Leon Clarkef7060e22010-06-03 12:02:55 +01004996const char* ScriptDataImpl::Data() {
4997 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00004998}
4999
5000
Leon Clarkee46be812010-01-19 14:06:41 +00005001bool ScriptDataImpl::HasError() {
5002 return has_error();
5003}
5004
5005
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005006void ScriptDataImpl::Initialize() {
5007 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005008 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5009 function_index_ = PreparseDataConstants::kHeaderSize;
5010 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5011 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005012 if (store_.length() > symbol_data_offset) {
5013 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5014 } else {
5015 // Partial preparse causes no symbol information.
5016 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5017 }
5018 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5019 }
5020}
5021
5022
5023int ScriptDataImpl::ReadNumber(byte** source) {
5024 // Reads a number from symbol_data_ in base 128. The most significant
5025 // bit marks that there are more digits.
5026 // If the first byte is 0x80 (kNumberTerminator), it would normally
5027 // represent a leading zero. Since that is useless, and therefore won't
5028 // appear as the first digit of any actual value, it is used to
5029 // mark the end of the input stream.
5030 byte* data = *source;
5031 if (data >= symbol_data_end_) return -1;
5032 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005033 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005034 // End of stream marker.
5035 return -1;
5036 }
5037 int result = input & 0x7f;
5038 data++;
5039 while ((input & 0x80u) != 0) {
5040 if (data >= symbol_data_end_) return -1;
5041 input = *data;
5042 result = (result << 7) | (input & 0x7f);
5043 data++;
5044 }
5045 *source = data;
5046 return result;
5047}
5048
5049
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005050// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005051static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005052 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01005053 ParserRecorder* recorder) {
Steve Block44f0eee2011-05-26 01:26:41 +01005054 Isolate* isolate = Isolate::Current();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005055 JavaScriptScanner scanner(isolate->unicode_cache());
Steve Block9fac8402011-05-12 15:51:54 +01005056 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005057 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005058 if (!preparser::PreParser::PreParseProgram(&scanner,
5059 recorder,
5060 allow_lazy,
5061 stack_limit)) {
Steve Block44f0eee2011-05-26 01:26:41 +01005062 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005063 return NULL;
5064 }
5065
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005066 // Extract the accumulated data from the recorder as a single
5067 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005068 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005069 return new ScriptDataImpl(store);
5070}
5071
5072
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005073// Preparse, but only collect data that is immediately useful,
5074// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005075ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005076 v8::Extension* extension) {
5077 bool allow_lazy = FLAG_lazy && (extension == NULL);
5078 if (!allow_lazy) {
5079 // Partial preparsing is only about lazily compiled functions.
5080 // If we don't allow lazy compilation, the log data will be empty.
5081 return NULL;
5082 }
5083 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005084 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005085}
5086
5087
Ben Murdochb0fe1622011-05-05 13:52:32 +01005088ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005089 v8::Extension* extension) {
5090 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005091 bool allow_lazy = FLAG_lazy && (extension == NULL);
5092 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005093 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005094}
5095
5096
5097bool RegExpParser::ParseRegExp(FlatStringReader* input,
5098 bool multiline,
5099 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005100 ASSERT(result != NULL);
5101 RegExpParser parser(input, &result->error, multiline);
5102 RegExpTree* tree = parser.ParsePattern();
5103 if (parser.failed()) {
5104 ASSERT(tree == NULL);
5105 ASSERT(!result->error.is_null());
5106 } else {
5107 ASSERT(tree != NULL);
5108 ASSERT(result->error.is_null());
5109 result->tree = tree;
5110 int capture_count = parser.captures_started();
5111 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5112 result->contains_anchor = parser.contains_anchor();
5113 result->capture_count = capture_count;
5114 }
5115 return !parser.failed();
5116}
5117
5118
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005119bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005120 ASSERT(info->function() == NULL);
5121 FunctionLiteral* result = NULL;
5122 Handle<Script> script = info->script();
5123 if (info->is_lazy()) {
Ben Murdoch203a29f2011-10-20 14:36:23 +01005124 bool allow_natives_syntax =
5125 FLAG_allow_natives_syntax ||
5126 info->is_native();
5127 Parser parser(script, allow_natives_syntax, NULL, NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01005128 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005129 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005130 // Whether we allow %identifier(..) syntax.
Ben Murdochf87a2032010-10-22 12:50:53 +01005131 bool allow_natives_syntax =
Ben Murdoch203a29f2011-10-20 14:36:23 +01005132 info->is_native() || FLAG_allow_natives_syntax;
Ben Murdochf87a2032010-10-22 12:50:53 +01005133 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005134 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005135 if (pre_data != NULL && pre_data->has_error()) {
5136 Scanner::Location loc = pre_data->MessageLocation();
5137 const char* message = pre_data->BuildMessage();
5138 Vector<const char*> args = pre_data->BuildArgs();
5139 parser.ReportMessageAt(loc, message, args);
5140 DeleteArray(message);
5141 for (int i = 0; i < args.length(); i++) {
5142 DeleteArray(args[i]);
5143 }
5144 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005145 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005146 } else {
5147 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01005148 result = parser.ParseProgram(source,
5149 info->is_global(),
5150 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005151 }
Leon Clarke4515c472010-02-03 11:58:03 +00005152 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005153
5154 info->SetFunction(result);
5155 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005156}
5157
Steve Blocka7e24c12009-10-30 11:49:00 +00005158} } // namespace v8::internal