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 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 if (!bad) { | 910 if (!bad) { |
911 i += input_offset; | 911 i += input_offset; |
912 character_length -= output_adjust; | 912 character_length -= output_adjust; |
913 } | 913 } |
914 } | 914 } |
915 } | 915 } |
916 return character_length; | 916 return character_length; |
917 } | 917 } |
918 | 918 |
919 | 919 |
| 920 TEST(ScopeUsesThisAndArguments) { |
| 921 static const struct { |
| 922 const char* prefix; |
| 923 const char* suffix; |
| 924 } surroundings[] = { |
| 925 { "function f() {", "}" }, |
| 926 { "var f = () => {", "}" }, |
| 927 }; |
| 928 |
| 929 static const struct { |
| 930 const char* body; |
| 931 bool uses_this; |
| 932 bool uses_arguments; |
| 933 bool inner_uses_this; |
| 934 bool inner_uses_arguments; |
| 935 } source_data[] = { |
| 936 { "", |
| 937 false, false, false, false }, |
| 938 { "return this", |
| 939 true, false, false, false }, |
| 940 { "return arguments", |
| 941 false, true, false, false }, |
| 942 { "return arguments[0]", |
| 943 false, true, false, false }, |
| 944 { "return this + arguments[0]", |
| 945 true, true, false, false }, |
| 946 { "return x => this + x", |
| 947 false, false, true, false }, |
| 948 { "this.foo = 42;", |
| 949 true, false, false, false }, |
| 950 { "this.foo();", |
| 951 true, false, false, false }, |
| 952 { "if (foo()) { this.f() }", |
| 953 true, false, false, false }, |
| 954 { "if (arguments.length) { this.f() }", |
| 955 true, true, false, false }, |
| 956 { "while (true) { this.f() }", |
| 957 true, false, false, false }, |
| 958 { "if (true) { while (true) this.foo(arguments) }", |
| 959 true, true, false, false }, |
| 960 // Multiple nesting levels must work as well. |
| 961 { "while (true) { while (true) { while (true) return this } }", |
| 962 true, false, false, false }, |
| 963 { "if (1) { return () => { while (true) new this() } }", |
| 964 false, false, true, false }, |
| 965 // Note that propagation of the inner_uses_this() value does not |
| 966 // cross boundaries of normal functions onto parent scopes. |
| 967 { "return function (x) { return this + x }", |
| 968 false, false, false, false }, |
| 969 { "var x = function () { this.foo = 42 };", |
| 970 false, false, false, false }, |
| 971 { "if (1) { return function () { while (true) new this() } }", |
| 972 false, false, false, false }, |
| 973 { "return function (x) { return () => this }", |
| 974 false, false, false, false }, |
| 975 // Flags must be correctly set when using block scoping. |
| 976 { "\"use strict\"; while (true) { let x; this, arguments; }", |
| 977 false, false, true, true }, |
| 978 { "\"use strict\"; if (foo()) { let x; this.f() }", |
| 979 false, false, true, false }, |
| 980 { "\"use strict\"; if (1) {" |
| 981 " let x; return function () { return this + arguments }" |
| 982 "}", |
| 983 false, false, false, false }, |
| 984 }; |
| 985 |
| 986 i::Isolate* isolate = CcTest::i_isolate(); |
| 987 i::Factory* factory = isolate->factory(); |
| 988 |
| 989 v8::HandleScope handles(CcTest::isolate()); |
| 990 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); |
| 991 v8::Context::Scope context_scope(context); |
| 992 |
| 993 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - |
| 994 128 * 1024); |
| 995 |
| 996 for (unsigned j = 0; j < arraysize(surroundings); ++j) { |
| 997 for (unsigned i = 0; i < arraysize(source_data); ++i) { |
| 998 int kProgramByteSize = i::StrLength(surroundings[j].prefix) + |
| 999 i::StrLength(surroundings[j].suffix) + |
| 1000 i::StrLength(source_data[i].body); |
| 1001 i::ScopedVector<char> program(kProgramByteSize + 1); |
| 1002 i::SNPrintF(program, "%s%s%s", surroundings[j].prefix, |
| 1003 source_data[i].body, surroundings[j].suffix); |
| 1004 i::Handle<i::String> source = |
| 1005 factory->NewStringFromUtf8(i::CStrVector(program.start())) |
| 1006 .ToHandleChecked(); |
| 1007 i::Handle<i::Script> script = factory->NewScript(source); |
| 1008 i::CompilationInfoWithZone info(script); |
| 1009 i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(), |
| 1010 isolate->heap()->HashSeed(), |
| 1011 isolate->unicode_cache()}; |
| 1012 i::Parser parser(&info, &parse_info); |
| 1013 parser.set_allow_arrow_functions(true); |
| 1014 parser.set_allow_harmony_scoping(true); |
| 1015 info.MarkAsGlobal(); |
| 1016 parser.Parse(); |
| 1017 CHECK(i::Rewriter::Rewrite(&info)); |
| 1018 CHECK(i::Scope::Analyze(&info)); |
| 1019 CHECK(info.function() != NULL); |
| 1020 |
| 1021 i::Scope* global_scope = info.function()->scope(); |
| 1022 CHECK(global_scope->is_global_scope()); |
| 1023 CHECK_EQ(1, global_scope->inner_scopes()->length()); |
| 1024 |
| 1025 i::Scope* scope = global_scope->inner_scopes()->at(0); |
| 1026 CHECK_EQ(source_data[i].uses_this, scope->uses_this()); |
| 1027 CHECK_EQ(source_data[i].uses_arguments, scope->uses_arguments()); |
| 1028 CHECK_EQ(source_data[i].inner_uses_this, scope->inner_uses_this()); |
| 1029 CHECK_EQ(source_data[i].inner_uses_arguments, |
| 1030 scope->inner_uses_arguments()); |
| 1031 } |
| 1032 } |
| 1033 } |
| 1034 |
| 1035 |
920 TEST(ScopePositions) { | 1036 TEST(ScopePositions) { |
921 v8::internal::FLAG_harmony_scoping = true; | 1037 v8::internal::FLAG_harmony_scoping = true; |
922 | 1038 |
923 // Test the parser for correctly setting the start and end positions | 1039 // Test the parser for correctly setting the start and end positions |
924 // of a scope. We check the scope positions of exactly one scope | 1040 // of a scope. We check the scope positions of exactly one scope |
925 // nested in the global scope of a program. 'inner source' is the | 1041 // nested in the global scope of a program. 'inner source' is the |
926 // source code that determines the part of the source belonging | 1042 // source code that determines the part of the source belonging |
927 // to the nested scope. 'outer_prefix' and 'outer_suffix' are | 1043 // to the nested scope. 'outer_prefix' and 'outer_suffix' are |
928 // parts of the source that belong to the global scope. | 1044 // parts of the source that belong to the global scope. |
929 struct SourceData { | 1045 struct SourceData { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 " }", "\n" | 1083 " }", "\n" |
968 " more;", i::BLOCK_SCOPE, i::STRICT }, | 1084 " more;", i::BLOCK_SCOPE, i::STRICT }, |
969 { " start;\n" | 1085 { " start;\n" |
970 " function fun", "(a,b) { infunction; }", " more;", | 1086 " function fun", "(a,b) { infunction; }", " more;", |
971 i::FUNCTION_SCOPE, i::SLOPPY }, | 1087 i::FUNCTION_SCOPE, i::SLOPPY }, |
972 { " start;\n" | 1088 { " start;\n" |
973 " function fun", "(a,b) {\n" | 1089 " function fun", "(a,b) {\n" |
974 " infunction;\n" | 1090 " infunction;\n" |
975 " }", "\n" | 1091 " }", "\n" |
976 " more;", i::FUNCTION_SCOPE, i::SLOPPY }, | 1092 " more;", i::FUNCTION_SCOPE, i::SLOPPY }, |
977 // TODO(aperez): Change to use i::ARROW_SCOPE when implemented | |
978 { " start;\n", "(a,b) => a + b", "; more;", | 1093 { " start;\n", "(a,b) => a + b", "; more;", |
979 i::FUNCTION_SCOPE, i::SLOPPY }, | 1094 i::ARROW_SCOPE, i::SLOPPY }, |
980 { " start;\n", "(a,b) => { return a+b; }", "\nmore;", | 1095 { " start;\n", "(a,b) => { return a+b; }", "\nmore;", |
981 i::FUNCTION_SCOPE, i::SLOPPY }, | 1096 i::ARROW_SCOPE, i::SLOPPY }, |
982 { " start;\n" | 1097 { " start;\n" |
983 " (function fun", "(a,b) { infunction; }", ")();", | 1098 " (function fun", "(a,b) { infunction; }", ")();", |
984 i::FUNCTION_SCOPE, i::SLOPPY }, | 1099 i::FUNCTION_SCOPE, i::SLOPPY }, |
985 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;", | 1100 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;", |
986 i::BLOCK_SCOPE, i::STRICT }, | 1101 i::BLOCK_SCOPE, i::STRICT }, |
987 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;", | 1102 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;", |
988 i::BLOCK_SCOPE, i::STRICT }, | 1103 i::BLOCK_SCOPE, i::STRICT }, |
989 { " for ", "(let x = 1 ; x < 10; ++ x) {\n" | 1104 { " for ", "(let x = 1 ; x < 10; ++ x) {\n" |
990 " block;\n" | 1105 " block;\n" |
991 " }", "\n" | 1106 " }", "\n" |
(...skipping 3088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4080 | 4195 |
4081 const char* name_data[] = { | 4196 const char* name_data[] = { |
4082 "function* g() { ({yield}); }", | 4197 "function* g() { ({yield}); }", |
4083 NULL | 4198 NULL |
4084 }; | 4199 }; |
4085 | 4200 |
4086 static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; | 4201 static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; |
4087 RunParserSyncTest(context_data, name_data, kError, NULL, 0, | 4202 RunParserSyncTest(context_data, name_data, kError, NULL, 0, |
4088 always_flags, arraysize(always_flags)); | 4203 always_flags, arraysize(always_flags)); |
4089 } | 4204 } |
OLD | NEW |