OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 Handle<FixedArray> this_property_assignments() { | 276 Handle<FixedArray> this_property_assignments() { |
277 return this_property_assignments_; | 277 return this_property_assignments_; |
278 } | 278 } |
279 | 279 |
280 void AddProperty() { expected_property_count_++; } | 280 void AddProperty() { expected_property_count_++; } |
281 int expected_property_count() { return expected_property_count_; } | 281 int expected_property_count() { return expected_property_count_; } |
282 | 282 |
283 void AddLoop() { loop_count_++; } | 283 void AddLoop() { loop_count_++; } |
284 bool ContainsLoops() const { return loop_count_ > 0; } | 284 bool ContainsLoops() const { return loop_count_ > 0; } |
285 | 285 |
286 bool StrictMode() { return strict_mode_; } | |
287 void EnableStrictMode() { | |
288 strict_mode_ = FLAG_strict_mode; | |
289 } | |
290 | |
291 // Checks whether scope already declares parameter with a name "param_name". | |
292 bool CheckParameterDeclared(Scope *scope, Handle<String> param_name); | |
293 | |
286 private: | 294 private: |
287 // Captures the number of literals that need materialization in the | 295 // Captures the number of literals that need materialization in the |
288 // function. Includes regexp literals, and boilerplate for object | 296 // function. Includes regexp literals, and boilerplate for object |
289 // and array literals. | 297 // and array literals. |
290 int materialized_literal_count_; | 298 int materialized_literal_count_; |
291 | 299 |
292 // Properties count estimation. | 300 // Properties count estimation. |
293 int expected_property_count_; | 301 int expected_property_count_; |
294 | 302 |
295 // Keeps track of assignments to properties of this. Used for | 303 // Keeps track of assignments to properties of this. Used for |
296 // optimizing constructors. | 304 // optimizing constructors. |
297 bool only_simple_this_property_assignments_; | 305 bool only_simple_this_property_assignments_; |
298 Handle<FixedArray> this_property_assignments_; | 306 Handle<FixedArray> this_property_assignments_; |
299 | 307 |
300 // Captures the number of loops inside the scope. | 308 // Captures the number of loops inside the scope. |
301 int loop_count_; | 309 int loop_count_; |
302 | 310 |
311 // Parsing strict mode code. | |
312 bool strict_mode_; | |
313 | |
314 // Hash map for finding duplicate parameter names | |
315 HashMap* param_names_; | |
316 | |
303 // Bookkeeping | 317 // Bookkeeping |
304 TemporaryScope** variable_; | 318 TemporaryScope** variable_; |
305 TemporaryScope* parent_; | 319 TemporaryScope* parent_; |
306 }; | 320 }; |
307 | 321 |
308 | 322 |
309 TemporaryScope::TemporaryScope(TemporaryScope** variable) | 323 TemporaryScope::TemporaryScope(TemporaryScope** variable) |
310 : materialized_literal_count_(0), | 324 : materialized_literal_count_(0), |
311 expected_property_count_(0), | 325 expected_property_count_(0), |
312 only_simple_this_property_assignments_(false), | 326 only_simple_this_property_assignments_(false), |
313 this_property_assignments_(Factory::empty_fixed_array()), | 327 this_property_assignments_(Factory::empty_fixed_array()), |
314 loop_count_(0), | 328 loop_count_(0), |
329 param_names_(NULL), | |
315 variable_(variable), | 330 variable_(variable), |
316 parent_(*variable) { | 331 parent_(*variable) { |
332 // Inherit the strict mode from the parent scope. | |
333 strict_mode_ = (parent_ != NULL) ? parent_->strict_mode_ : false; | |
317 *variable = this; | 334 *variable = this; |
318 } | 335 } |
319 | 336 |
320 | 337 |
321 TemporaryScope::~TemporaryScope() { | 338 TemporaryScope::~TemporaryScope() { |
339 if (param_names_) { | |
340 // TODO(mmaly): How to allocate temporary map and free it when not needed? | |
Martin Maly
2011/01/14 00:06:28
I am trying to allocate the hash map only when fun
| |
341 // delete param_names_; | |
342 param_names_ = 0; | |
343 } | |
322 *variable_ = parent_; | 344 *variable_ = parent_; |
323 } | 345 } |
324 | 346 |
347 bool TemporaryScope::CheckParameterDeclared( | |
348 Scope *scope, Handle<String> param_name) { | |
349 | |
350 const int LinearLookupThreshold = 5; | |
351 | |
Martin Maly
2011/01/14 00:06:28
Moved the code from Scope to TemporaryScope since
| |
352 int length = scope->num_parameters(); | |
353 if (length <= LinearLookupThreshold) { | |
354 for (int i = 0; i < length; i ++) { | |
355 if (param_name.is_identical_to(scope->parameter(i)->name())) { | |
356 // Parameter with the given name found! | |
357 return true; | |
358 } | |
359 } | |
360 } else { | |
361 if (param_names_ == NULL) { | |
362 // Populate the variable map. | |
363 param_names_ = new VariableMap(); | |
364 for (int i = 0; i < length; i ++) { | |
365 Handle<String> name = scope->parameter(i)->name(); | |
366 HashMap::Entry* e = param_names_->Lookup( | |
367 name.location(), name->Hash(), true); | |
368 ASSERT(e->value == NULL); | |
369 e->value = name.location(); | |
370 } | |
371 } | |
372 | |
373 HashMap::Entry* p = param_names_->Lookup( | |
374 param_name.location(), param_name->Hash(), true); | |
375 if (p->value == NULL) { | |
376 p->value = param_name.location(); | |
377 } else { | |
378 // Parameter with the given name found! | |
379 return true; | |
380 } | |
381 } | |
382 return false; | |
383 } | |
384 | |
325 | 385 |
326 Handle<String> Parser::LookupSymbol(int symbol_id) { | 386 Handle<String> Parser::LookupSymbol(int symbol_id) { |
327 // Length of symbol cache is the number of identified symbols. | 387 // Length of symbol cache is the number of identified symbols. |
328 // If we are larger than that, or negative, it's not a cached symbol. | 388 // If we are larger than that, or negative, it's not a cached symbol. |
329 // This might also happen if there is no preparser symbol data, even | 389 // This might also happen if there is no preparser symbol data, even |
330 // if there is some preparser data. | 390 // if there is some preparser data. |
331 if (static_cast<unsigned>(symbol_id) | 391 if (static_cast<unsigned>(symbol_id) |
332 >= static_cast<unsigned>(symbol_cache_.length())) { | 392 >= static_cast<unsigned>(symbol_cache_.length())) { |
333 if (scanner().is_literal_ascii()) { | 393 if (scanner().is_literal_ascii()) { |
334 return Factory::LookupAsciiSymbol(scanner().literal_ascii_string()); | 394 return Factory::LookupAsciiSymbol(scanner().literal_ascii_string()); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 *with_nesting_level_variable_ = prev_level_; | 614 *with_nesting_level_variable_ = prev_level_; |
555 } | 615 } |
556 | 616 |
557 private: | 617 private: |
558 Scope** scope_variable_; | 618 Scope** scope_variable_; |
559 int* with_nesting_level_variable_; | 619 int* with_nesting_level_variable_; |
560 Scope* prev_scope_; | 620 Scope* prev_scope_; |
561 int prev_level_; | 621 int prev_level_; |
562 }; | 622 }; |
563 | 623 |
564 | |
565 // ---------------------------------------------------------------------------- | 624 // ---------------------------------------------------------------------------- |
566 // The CHECK_OK macro is a convenient macro to enforce error | 625 // The CHECK_OK macro is a convenient macro to enforce error |
567 // handling for functions that may fail (by returning !*ok). | 626 // handling for functions that may fail (by returning !*ok). |
568 // | 627 // |
569 // CAUTION: This macro appends extra statements after a call, | 628 // CAUTION: This macro appends extra statements after a call, |
570 // thus it must never be used where only a single statement | 629 // thus it must never be used where only a single statement |
571 // is correct (e.g. an if statement branch w/o braces)! | 630 // is correct (e.g. an if statement branch w/o braces)! |
572 | 631 |
573 #define CHECK_OK ok); \ | 632 #define CHECK_OK ok); \ |
574 if (!*ok) return NULL; \ | 633 if (!*ok) return NULL; \ |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 top_scope_, | 720 top_scope_, |
662 body, | 721 body, |
663 temp_scope.materialized_literal_count(), | 722 temp_scope.materialized_literal_count(), |
664 temp_scope.expected_property_count(), | 723 temp_scope.expected_property_count(), |
665 temp_scope.only_simple_this_property_assignments(), | 724 temp_scope.only_simple_this_property_assignments(), |
666 temp_scope.this_property_assignments(), | 725 temp_scope.this_property_assignments(), |
667 0, | 726 0, |
668 0, | 727 0, |
669 source->length(), | 728 source->length(), |
670 false, | 729 false, |
671 temp_scope.ContainsLoops()); | 730 temp_scope.ContainsLoops(), |
731 temp_scope.StrictMode()); | |
672 } else if (stack_overflow_) { | 732 } else if (stack_overflow_) { |
673 Top::StackOverflow(); | 733 Top::StackOverflow(); |
674 } | 734 } |
675 } | 735 } |
676 | 736 |
677 // Make sure the target stack is empty. | 737 // Make sure the target stack is empty. |
678 ASSERT(target_stack_ == NULL); | 738 ASSERT(target_stack_ == NULL); |
679 | 739 |
680 // If there was a syntax error we have to get rid of the AST | 740 // If there was a syntax error we have to get rid of the AST |
681 // and it is not safe to do so before the scope has been deleted. | 741 // and it is not safe to do so before the scope has been deleted. |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1051 | 1111 |
1052 // Allocate a target stack to use for this set of source | 1112 // Allocate a target stack to use for this set of source |
1053 // elements. This way, all scripts and functions get their own | 1113 // elements. This way, all scripts and functions get their own |
1054 // target stack thus avoiding illegal breaks and continues across | 1114 // target stack thus avoiding illegal breaks and continues across |
1055 // functions. | 1115 // functions. |
1056 TargetScope scope(&this->target_stack_); | 1116 TargetScope scope(&this->target_stack_); |
1057 | 1117 |
1058 ASSERT(processor != NULL); | 1118 ASSERT(processor != NULL); |
1059 InitializationBlockFinder block_finder; | 1119 InitializationBlockFinder block_finder; |
1060 ThisNamedPropertyAssigmentFinder this_property_assignment_finder; | 1120 ThisNamedPropertyAssigmentFinder this_property_assignment_finder; |
1121 bool directive_prologue = true; // Parsing directive prologue. | |
1122 | |
1061 while (peek() != end_token) { | 1123 while (peek() != end_token) { |
1062 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1124 Statement* stat; |
1125 | |
1126 if (directive_prologue && peek() == Token::STRING) { | |
1127 // A shot at a directive. | |
1128 Scanner::Location directive_loc = scanner().peek_location(); | |
1129 stat = ParseStatement(NULL, CHECK_OK); | |
1130 if (stat == NULL || stat->IsEmpty()) { | |
1131 directive_prologue = false; // End of directive prologue. | |
1132 continue; | |
1133 } | |
1134 | |
1135 if (directive_prologue) { | |
1136 ExpressionStatement *e_stat; | |
1137 Literal *literal; | |
1138 // Still processing directive prologue? | |
1139 if ((e_stat = stat->AsExpressionStatement()) != NULL && | |
1140 (literal = e_stat->expression()->AsLiteral()) != NULL && | |
1141 literal->handle()->IsString()) { | |
1142 Handle<String> directive = Handle<String>::cast(literal->handle()); | |
1143 | |
1144 // Check "use strict" directive (ES5 14.1). | |
1145 if (!temp_scope_->StrictMode() && | |
1146 directive->Equals(Heap::use_strict()) && | |
1147 directive_loc.end_pos - directive_loc.beg_pos == | |
1148 Heap::use_strict()->length() + 2) { | |
1149 temp_scope_->EnableStrictMode(); | |
1150 } | |
1151 } else { | |
1152 // End of the directive prologue. | |
1153 directive_prologue = false; | |
1154 } | |
1155 } | |
1156 } else { | |
1157 stat = ParseStatement(NULL, CHECK_OK); | |
1158 } | |
1159 | |
1063 if (stat == NULL || stat->IsEmpty()) continue; | 1160 if (stat == NULL || stat->IsEmpty()) continue; |
1064 // We find and mark the initialization blocks on top level code only. | 1161 // We find and mark the initialization blocks on top level code only. |
1065 // This is because the optimization prevents reuse of the map transitions, | 1162 // This is because the optimization prevents reuse of the map transitions, |
1066 // so it should be used only for code that will only be run once. | 1163 // so it should be used only for code that will only be run once. |
1067 if (top_scope_->is_global_scope()) { | 1164 if (top_scope_->is_global_scope()) { |
1068 block_finder.Update(stat); | 1165 block_finder.Update(stat); |
1069 } | 1166 } |
1070 // Find and mark all assignments to named properties in this (this.x =) | 1167 // Find and mark all assignments to named properties in this (this.x =) |
1071 if (top_scope_->is_function_scope()) { | 1168 if (top_scope_->is_function_scope()) { |
1072 this_property_assignment_finder.Update(top_scope_, stat); | 1169 this_property_assignment_finder.Update(top_scope_, stat); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1407 Block* Parser::ParseVariableStatement(bool* ok) { | 1504 Block* Parser::ParseVariableStatement(bool* ok) { |
1408 // VariableStatement :: | 1505 // VariableStatement :: |
1409 // VariableDeclarations ';' | 1506 // VariableDeclarations ';' |
1410 | 1507 |
1411 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature | 1508 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature |
1412 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); | 1509 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); |
1413 ExpectSemicolon(CHECK_OK); | 1510 ExpectSemicolon(CHECK_OK); |
1414 return result; | 1511 return result; |
1415 } | 1512 } |
1416 | 1513 |
1514 static bool IsEvalOrArguments(Handle<String> string) { | |
1515 return string.is_identical_to(Factory::eval_symbol()) || | |
1516 string.is_identical_to(Factory::arguments_symbol()); | |
1517 } | |
1417 | 1518 |
1418 // If the variable declaration declares exactly one non-const | 1519 // If the variable declaration declares exactly one non-const |
1419 // variable, then *var is set to that variable. In all other cases, | 1520 // variable, then *var is set to that variable. In all other cases, |
1420 // *var is untouched; in particular, it is the caller's responsibility | 1521 // *var is untouched; in particular, it is the caller's responsibility |
1421 // to initialize it properly. This mechanism is used for the parsing | 1522 // to initialize it properly. This mechanism is used for the parsing |
1422 // of 'for-in' loops. | 1523 // of 'for-in' loops. |
1423 Block* Parser::ParseVariableDeclarations(bool accept_IN, | 1524 Block* Parser::ParseVariableDeclarations(bool accept_IN, |
1424 Expression** var, | 1525 Expression** var, |
1425 bool* ok) { | 1526 bool* ok) { |
1426 // VariableDeclarations :: | 1527 // VariableDeclarations :: |
(...skipping 28 matching lines...) Expand all Loading... | |
1455 VariableProxy* last_var = NULL; // the last variable declared | 1556 VariableProxy* last_var = NULL; // the last variable declared |
1456 int nvars = 0; // the number of variables declared | 1557 int nvars = 0; // the number of variables declared |
1457 do { | 1558 do { |
1458 if (fni_ != NULL) fni_->Enter(); | 1559 if (fni_ != NULL) fni_->Enter(); |
1459 | 1560 |
1460 // Parse variable name. | 1561 // Parse variable name. |
1461 if (nvars > 0) Consume(Token::COMMA); | 1562 if (nvars > 0) Consume(Token::COMMA); |
1462 Handle<String> name = ParseIdentifier(CHECK_OK); | 1563 Handle<String> name = ParseIdentifier(CHECK_OK); |
1463 if (fni_ != NULL) fni_->PushVariableName(name); | 1564 if (fni_ != NULL) fni_->PushVariableName(name); |
1464 | 1565 |
1566 // Strict mode variables may not be named eval or arguments | |
1567 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { | |
1568 ReportMessage("strict_var_name", Vector<const char*>::empty()); | |
1569 *ok = false; | |
1570 return NULL; | |
1571 } | |
1572 | |
1465 // Declare variable. | 1573 // Declare variable. |
1466 // Note that we *always* must treat the initial value via a separate init | 1574 // Note that we *always* must treat the initial value via a separate init |
1467 // assignment for variables and constants because the value must be assigned | 1575 // assignment for variables and constants because the value must be assigned |
1468 // when the variable is encountered in the source. But the variable/constant | 1576 // when the variable is encountered in the source. But the variable/constant |
1469 // is declared (and set to 'undefined') upon entering the function within | 1577 // is declared (and set to 'undefined') upon entering the function within |
1470 // which the variable or constant is declared. Only function variables have | 1578 // which the variable or constant is declared. Only function variables have |
1471 // an initial value in the declaration (because they are initialized upon | 1579 // an initial value in the declaration (because they are initialized upon |
1472 // entering the function). | 1580 // entering the function). |
1473 // | 1581 // |
1474 // If we have a const declaration, in an inner scope, the proxy is always | 1582 // If we have a const declaration, in an inner scope, the proxy is always |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1807 } | 1915 } |
1808 return result; | 1916 return result; |
1809 } | 1917 } |
1810 | 1918 |
1811 | 1919 |
1812 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { | 1920 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
1813 // WithStatement :: | 1921 // WithStatement :: |
1814 // 'with' '(' Expression ')' Statement | 1922 // 'with' '(' Expression ')' Statement |
1815 | 1923 |
1816 Expect(Token::WITH, CHECK_OK); | 1924 Expect(Token::WITH, CHECK_OK); |
1925 | |
1926 if (temp_scope_->StrictMode()) { | |
1927 ReportMessage("strict_mode_with", Vector<const char*>::empty()); | |
1928 *ok = false; | |
1929 return NULL; | |
1930 } | |
1931 | |
1817 Expect(Token::LPAREN, CHECK_OK); | 1932 Expect(Token::LPAREN, CHECK_OK); |
1818 Expression* expr = ParseExpression(true, CHECK_OK); | 1933 Expression* expr = ParseExpression(true, CHECK_OK); |
1819 Expect(Token::RPAREN, CHECK_OK); | 1934 Expect(Token::RPAREN, CHECK_OK); |
1820 | 1935 |
1821 return WithHelper(expr, labels, false, CHECK_OK); | 1936 return WithHelper(expr, labels, false, CHECK_OK); |
1822 } | 1937 } |
1823 | 1938 |
1824 | 1939 |
1825 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | 1940 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
1826 // CaseClause :: | 1941 // CaseClause :: |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1939 // the jump targets. | 2054 // the jump targets. |
1940 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); | 2055 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); |
1941 TargetCollector catch_collector(catch_target_list); | 2056 TargetCollector catch_collector(catch_target_list); |
1942 bool has_catch = false; | 2057 bool has_catch = false; |
1943 if (tok == Token::CATCH) { | 2058 if (tok == Token::CATCH) { |
1944 has_catch = true; | 2059 has_catch = true; |
1945 Consume(Token::CATCH); | 2060 Consume(Token::CATCH); |
1946 | 2061 |
1947 Expect(Token::LPAREN, CHECK_OK); | 2062 Expect(Token::LPAREN, CHECK_OK); |
1948 Handle<String> name = ParseIdentifier(CHECK_OK); | 2063 Handle<String> name = ParseIdentifier(CHECK_OK); |
2064 | |
2065 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { | |
2066 ReportMessage("strict_catch_variable", Vector<const char*>::empty()); | |
2067 *ok = false; | |
2068 return NULL; | |
2069 } | |
2070 | |
1949 Expect(Token::RPAREN, CHECK_OK); | 2071 Expect(Token::RPAREN, CHECK_OK); |
1950 | 2072 |
1951 if (peek() == Token::LBRACE) { | 2073 if (peek() == Token::LBRACE) { |
1952 // Allocate a temporary for holding the finally state while | 2074 // Allocate a temporary for holding the finally state while |
1953 // executing the finally block. | 2075 // executing the finally block. |
1954 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); | 2076 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); |
1955 Literal* name_literal = new Literal(name); | 2077 Literal* name_literal = new Literal(name); |
1956 VariableProxy* catch_var_use = new VariableProxy(catch_var); | 2078 VariableProxy* catch_var_use = new VariableProxy(catch_var); |
1957 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); | 2079 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); |
1958 { Target target(&this->target_stack_, &catch_collector); | 2080 { Target target(&this->target_stack_, &catch_collector); |
(...skipping 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3185 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); | 3307 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); |
3186 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, | 3308 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, |
3187 scope); | 3309 scope); |
3188 TemporaryScope temp_scope(&this->temp_scope_); | 3310 TemporaryScope temp_scope(&this->temp_scope_); |
3189 top_scope_->SetScopeName(name); | 3311 top_scope_->SetScopeName(name); |
3190 | 3312 |
3191 // FormalParameterList :: | 3313 // FormalParameterList :: |
3192 // '(' (Identifier)*[','] ')' | 3314 // '(' (Identifier)*[','] ')' |
3193 Expect(Token::LPAREN, CHECK_OK); | 3315 Expect(Token::LPAREN, CHECK_OK); |
3194 int start_pos = scanner().location().beg_pos; | 3316 int start_pos = scanner().location().beg_pos; |
3317 Scanner::Location eval_loc(RelocInfo::kNoPosition, RelocInfo::kNoPosition); | |
3318 Scanner::Location dupe_loc(RelocInfo::kNoPosition, RelocInfo::kNoPosition); | |
3319 | |
3195 bool done = (peek() == Token::RPAREN); | 3320 bool done = (peek() == Token::RPAREN); |
3196 while (!done) { | 3321 while (!done) { |
3197 Handle<String> param_name = ParseIdentifier(CHECK_OK); | 3322 Handle<String> param_name = ParseIdentifier(CHECK_OK); |
3198 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name, | 3323 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR); |
3199 Variable::VAR)); | 3324 |
Martin Maly
2011/01/14 00:06:28
This code runs even when not processing strict mod
| |
3325 // Store locations for possible future error reports. | |
3326 if (eval_loc.beg_pos == RelocInfo::kNoPosition && | |
3327 IsEvalOrArguments(param_name)) { | |
3328 // Store location for later | |
3329 eval_loc = scanner().location(); | |
3330 } | |
3331 if (dupe_loc.beg_pos == RelocInfo::kNoPosition && | |
3332 temp_scope.CheckParameterDeclared(scope, param_name)) { | |
3333 // Store location for later | |
3334 dupe_loc = scanner().location(); | |
3335 } | |
3336 | |
3337 top_scope_->AddParameter(parameter); | |
3200 num_parameters++; | 3338 num_parameters++; |
3201 done = (peek() == Token::RPAREN); | 3339 done = (peek() == Token::RPAREN); |
3202 if (!done) Expect(Token::COMMA, CHECK_OK); | 3340 if (!done) Expect(Token::COMMA, CHECK_OK); |
3203 } | 3341 } |
3204 Expect(Token::RPAREN, CHECK_OK); | 3342 Expect(Token::RPAREN, CHECK_OK); |
3205 | 3343 |
3206 Expect(Token::LBRACE, CHECK_OK); | 3344 Expect(Token::LBRACE, CHECK_OK); |
3207 ZoneList<Statement*>* body = new ZoneList<Statement*>(8); | 3345 ZoneList<Statement*>* body = new ZoneList<Statement*>(8); |
3208 | 3346 |
3209 // If we have a named function expression, we add a local variable | 3347 // If we have a named function expression, we add a local variable |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3258 materialized_literal_count = temp_scope.materialized_literal_count(); | 3396 materialized_literal_count = temp_scope.materialized_literal_count(); |
3259 expected_property_count = temp_scope.expected_property_count(); | 3397 expected_property_count = temp_scope.expected_property_count(); |
3260 only_simple_this_property_assignments = | 3398 only_simple_this_property_assignments = |
3261 temp_scope.only_simple_this_property_assignments(); | 3399 temp_scope.only_simple_this_property_assignments(); |
3262 this_property_assignments = temp_scope.this_property_assignments(); | 3400 this_property_assignments = temp_scope.this_property_assignments(); |
3263 | 3401 |
3264 Expect(Token::RBRACE, CHECK_OK); | 3402 Expect(Token::RBRACE, CHECK_OK); |
3265 end_pos = scanner().location().end_pos; | 3403 end_pos = scanner().location().end_pos; |
3266 } | 3404 } |
3267 | 3405 |
3406 // Validate strict mode. | |
3407 if (temp_scope_->StrictMode()) { | |
3408 if (IsEvalOrArguments(name)) { | |
3409 int position = function_token_position != RelocInfo::kNoPosition | |
Martin Maly
2011/01/14 00:06:28
This is still necessary because property get/set g
| |
3410 ? function_token_position | |
3411 : (start_pos > 0 ? start_pos - 1 : start_pos); | |
3412 ReportMessageAt(Scanner::Location(position, start_pos), | |
3413 "strict_function_name", Vector<const char*>::empty()); | |
3414 *ok = false; | |
3415 return NULL; | |
3416 } | |
3417 if (eval_loc.beg_pos != RelocInfo::kNoPosition) { | |
3418 ReportMessageAt(eval_loc, "strict_param_name", | |
3419 Vector<const char*>::empty()); | |
3420 *ok = false; | |
3421 return NULL; | |
3422 } | |
3423 if (dupe_loc.beg_pos != RelocInfo::kNoPosition) { | |
3424 ReportMessageAt(dupe_loc, "strict_param_dupe", | |
3425 Vector<const char*>::empty()); | |
3426 *ok = false; | |
3427 return NULL; | |
3428 } | |
3429 // TODO(mmaly): Check for octal escape sequence here. | |
3430 } | |
3431 | |
3268 FunctionLiteral* function_literal = | 3432 FunctionLiteral* function_literal = |
3269 new FunctionLiteral(name, | 3433 new FunctionLiteral(name, |
3270 top_scope_, | 3434 top_scope_, |
3271 body, | 3435 body, |
3272 materialized_literal_count, | 3436 materialized_literal_count, |
3273 expected_property_count, | 3437 expected_property_count, |
3274 only_simple_this_property_assignments, | 3438 only_simple_this_property_assignments, |
3275 this_property_assignments, | 3439 this_property_assignments, |
3276 num_parameters, | 3440 num_parameters, |
3277 start_pos, | 3441 start_pos, |
3278 end_pos, | 3442 end_pos, |
3279 function_name->length() > 0, | 3443 function_name->length() > 0, |
3280 temp_scope.ContainsLoops()); | 3444 temp_scope.ContainsLoops(), |
3445 temp_scope.StrictMode()); | |
3281 function_literal->set_function_token_position(function_token_position); | 3446 function_literal->set_function_token_position(function_token_position); |
3282 | 3447 |
3283 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); | 3448 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); |
3284 return function_literal; | 3449 return function_literal; |
3285 } | 3450 } |
3286 } | 3451 } |
3287 | 3452 |
3288 | 3453 |
3289 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 3454 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
3290 // CallRuntime :: | 3455 // CallRuntime :: |
(...skipping 1404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4695 Handle<String> source = Handle<String>(String::cast(script->source())); | 4860 Handle<String> source = Handle<String>(String::cast(script->source())); |
4696 result = parser.ParseProgram(source, info->is_global()); | 4861 result = parser.ParseProgram(source, info->is_global()); |
4697 } | 4862 } |
4698 } | 4863 } |
4699 | 4864 |
4700 info->SetFunction(result); | 4865 info->SetFunction(result); |
4701 return (result != NULL); | 4866 return (result != NULL); |
4702 } | 4867 } |
4703 | 4868 |
4704 } } // namespace v8::internal | 4869 } } // namespace v8::internal |
OLD | NEW |