OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 19 matching lines...) Expand all Loading... |
30 #include <string.h> | 30 #include <string.h> |
31 | 31 |
32 #include "src/v8.h" | 32 #include "src/v8.h" |
33 | 33 |
34 #include "src/compiler.h" | 34 #include "src/compiler.h" |
35 #include "src/execution.h" | 35 #include "src/execution.h" |
36 #include "src/isolate.h" | 36 #include "src/isolate.h" |
37 #include "src/objects.h" | 37 #include "src/objects.h" |
38 #include "src/parser.h" | 38 #include "src/parser.h" |
39 #include "src/preparser.h" | 39 #include "src/preparser.h" |
| 40 #include "src/rewriter.h" |
40 #include "src/scanner-character-streams.h" | 41 #include "src/scanner-character-streams.h" |
41 #include "src/token.h" | 42 #include "src/token.h" |
42 #include "src/utils.h" | 43 #include "src/utils.h" |
43 #include "test/cctest/cctest.h" | 44 #include "test/cctest/cctest.h" |
44 | 45 |
45 TEST(ScanKeywords) { | 46 TEST(ScanKeywords) { |
46 struct KeywordToken { | 47 struct KeywordToken { |
47 const char* keyword; | 48 const char* keyword; |
48 i::Token::Value token; | 49 i::Token::Value token; |
49 }; | 50 }; |
(...skipping 2492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2542 v8::Local<v8::String> source = | 2543 v8::Local<v8::String> source = |
2543 v8::String::NewFromTwoByte(isolate, two_byte_source); | 2544 v8::String::NewFromTwoByte(isolate, two_byte_source); |
2544 v8::Local<v8::Value> result = CompileRun(source); | 2545 v8::Local<v8::Value> result = CompileRun(source); |
2545 CHECK(result->IsString()); | 2546 CHECK(result->IsString()); |
2546 v8::Local<v8::String> expected_name = | 2547 v8::Local<v8::String> expected_name = |
2547 v8::String::NewFromTwoByte(isolate, two_byte_name); | 2548 v8::String::NewFromTwoByte(isolate, two_byte_name); |
2548 CHECK(result->Equals(expected_name)); | 2549 CHECK(result->Equals(expected_name)); |
2549 i::DeleteArray(two_byte_source); | 2550 i::DeleteArray(two_byte_source); |
2550 i::DeleteArray(two_byte_name); | 2551 i::DeleteArray(two_byte_name); |
2551 } | 2552 } |
| 2553 |
| 2554 |
| 2555 TEST(InnerAssignment) { |
| 2556 i::Isolate* isolate = CcTest::i_isolate(); |
| 2557 i::Factory* factory = isolate->factory(); |
| 2558 i::HandleScope scope(isolate); |
| 2559 LocalContext env; |
| 2560 |
| 2561 const char* prefix = "function f() {"; |
| 2562 const char* midfix = " function g() {"; |
| 2563 const char* suffix = "}}"; |
| 2564 struct { const char* source; bool assigned; bool strict; } outers[] = { |
| 2565 // Actual assignments. |
| 2566 { "var x; var x = 5;", true, false }, |
| 2567 { "var x; { var x = 5; }", true, false }, |
| 2568 { "'use strict'; let x; x = 6;", true, true }, |
| 2569 // Actual non-assignments. |
| 2570 { "var x;", false, false }, |
| 2571 { "var x = 5;", false, false }, |
| 2572 { "'use strict'; let x;", false, true }, |
| 2573 { "'use strict'; let x = 6;", false, true }, |
| 2574 { "'use strict'; var x = 0; { let x = 6; }", false, true }, |
| 2575 { "'use strict'; var x = 0; { let x; x = 6; }", false, true }, |
| 2576 { "'use strict'; let x = 0; { let x = 6; }", false, true }, |
| 2577 { "'use strict'; let x = 0; { let x; x = 6; }", false, true }, |
| 2578 { "var x; try {} catch (x) { x = 5; }", false, false }, |
| 2579 { "function x() {}", false, false }, |
| 2580 // Eval approximation. |
| 2581 { "var x; eval('');", true, false }, |
| 2582 { "eval(''); var x;", true, false }, |
| 2583 { "'use strict'; let x; eval('');", true, true }, |
| 2584 { "'use strict'; eval(''); let x;", true, true }, |
| 2585 // Non-assignments not recognized, because the analysis is approximative. |
| 2586 { "var x; var x;", true, false }, |
| 2587 { "var x = 5; var x;", true, false }, |
| 2588 { "var x; { var x; }", true, false }, |
| 2589 { "var x; function x() {}", true, false }, |
| 2590 { "function x() {}; var x;", true, false }, |
| 2591 { "var x; try {} catch (x) { var x = 5; }", true, false }, |
| 2592 }; |
| 2593 struct { const char* source; bool assigned; bool with; } inners[] = { |
| 2594 // Actual assignments. |
| 2595 { "x = 1;", true, false }, |
| 2596 { "x++;", true, false }, |
| 2597 { "++x;", true, false }, |
| 2598 { "x--;", true, false }, |
| 2599 { "--x;", true, false }, |
| 2600 { "{ x = 1; }", true, false }, |
| 2601 { "'use strict'; { let x; }; x = 0;", true, false }, |
| 2602 { "'use strict'; { const x = 1; }; x = 0;", true, false }, |
| 2603 { "'use strict'; { function x() {} }; x = 0;", true, false }, |
| 2604 { "with ({}) { x = 1; }", true, true }, |
| 2605 { "eval('');", true, false }, |
| 2606 { "'use strict'; { let y; eval('') }", true, false }, |
| 2607 { "function h() { x = 0; }", true, false }, |
| 2608 { "(function() { x = 0; })", true, false }, |
| 2609 { "(function() { x = 0; })", true, false }, |
| 2610 { "with ({}) (function() { x = 0; })", true, true }, |
| 2611 // Actual non-assignments. |
| 2612 { "", false, false }, |
| 2613 { "x;", false, false }, |
| 2614 { "var x;", false, false }, |
| 2615 { "var x = 8;", false, false }, |
| 2616 { "var x; x = 8;", false, false }, |
| 2617 { "'use strict'; let x;", false, false }, |
| 2618 { "'use strict'; let x = 8;", false, false }, |
| 2619 { "'use strict'; let x; x = 8;", false, false }, |
| 2620 { "'use strict'; const x = 8;", false, false }, |
| 2621 { "function x() {}", false, false }, |
| 2622 { "function x() { x = 0; }", false, false }, |
| 2623 { "function h(x) { x = 0; }", false, false }, |
| 2624 { "'use strict'; { let x; x = 0; }", false, false }, |
| 2625 { "{ var x; }; x = 0;", false, false }, |
| 2626 { "with ({}) {}", false, true }, |
| 2627 { "var x; { with ({}) { x = 1; } }", false, true }, |
| 2628 { "try {} catch(x) { x = 0; }", false, false }, |
| 2629 { "try {} catch(x) { with ({}) { x = 1; } }", false, true }, |
| 2630 // Eval approximation. |
| 2631 { "eval('');", true, false }, |
| 2632 { "function h() { eval(''); }", true, false }, |
| 2633 { "(function() { eval(''); })", true, false }, |
| 2634 // Shadowing not recognized because of eval approximation. |
| 2635 { "var x; eval('');", true, false }, |
| 2636 { "'use strict'; let x; eval('');", true, false }, |
| 2637 { "try {} catch(x) { eval(''); }", true, false }, |
| 2638 { "function x() { eval(''); }", true, false }, |
| 2639 { "(function(x) { eval(''); })", true, false }, |
| 2640 }; |
| 2641 i::Handle<i::String> var_name = factory->InternalizeUtf8String("x"); |
| 2642 |
| 2643 int prefix_len = Utf8LengthHelper(prefix); |
| 2644 int midfix_len = Utf8LengthHelper(midfix); |
| 2645 int suffix_len = Utf8LengthHelper(suffix); |
| 2646 for (unsigned i = 0; i < ARRAY_SIZE(outers); ++i) { |
| 2647 const char* outer = outers[i].source; |
| 2648 int outer_len = Utf8LengthHelper(outer); |
| 2649 for (unsigned j = 0; j < ARRAY_SIZE(inners); ++j) { |
| 2650 if (outers[i].strict && inners[j].with) continue; |
| 2651 const char* inner = inners[j].source; |
| 2652 int inner_len = Utf8LengthHelper(inner); |
| 2653 int len = prefix_len + outer_len + midfix_len + inner_len + suffix_len; |
| 2654 i::ScopedVector<char> program(len + 1); |
| 2655 i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner, suffix); |
| 2656 i::Handle<i::String> source = |
| 2657 factory->InternalizeUtf8String(program.start()); |
| 2658 source->PrintOn(stdout); |
| 2659 printf("\n"); |
| 2660 |
| 2661 i::Handle<i::Script> script = factory->NewScript(source); |
| 2662 i::CompilationInfoWithZone info(script); |
| 2663 i::Parser parser(&info); |
| 2664 parser.set_allow_harmony_scoping(true); |
| 2665 CHECK(parser.Parse()); |
| 2666 CHECK(i::Rewriter::Rewrite(&info)); |
| 2667 CHECK(i::Scope::Analyze(&info)); |
| 2668 CHECK(info.function() != NULL); |
| 2669 |
| 2670 i::Scope* scope = info.function()->scope(); |
| 2671 CHECK_EQ(scope->inner_scopes()->length(), 1); |
| 2672 i::Scope* inner_scope = scope->inner_scopes()->at(0); |
| 2673 i::Variable* var = inner_scope->Lookup(var_name); |
| 2674 bool expected = outers[i].assigned || inners[j].assigned; |
| 2675 CHECK(var != NULL); |
| 2676 CHECK(var->is_used() || !expected); |
| 2677 CHECK(var->maybe_assigned() == expected); |
| 2678 } |
| 2679 } |
| 2680 } |
OLD | NEW |