OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/execution.h" | 7 #include "src/execution.h" |
8 #include "src/handles.h" | 8 #include "src/handles.h" |
9 #include "src/interpreter/bytecode-array-builder.h" | 9 #include "src/interpreter/bytecode-array-builder.h" |
10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 : InterpreterTester(isolate, source, MaybeHandle<BytecodeArray>(), | 89 : InterpreterTester(isolate, source, MaybeHandle<BytecodeArray>(), |
90 MaybeHandle<TypeFeedbackVector>(), filter) {} | 90 MaybeHandle<TypeFeedbackVector>(), filter) {} |
91 | 91 |
92 virtual ~InterpreterTester() {} | 92 virtual ~InterpreterTester() {} |
93 | 93 |
94 template <class... A> | 94 template <class... A> |
95 InterpreterCallable<A...> GetCallable() { | 95 InterpreterCallable<A...> GetCallable() { |
96 return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>()); | 96 return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>()); |
97 } | 97 } |
98 | 98 |
99 template <class... A> | |
100 InterpreterCallable<A...> GetCallableWithLegacyConstants() { | |
101 i::FLAG_legacy_const = true; | |
rmcilroy
2016/02/03 12:28:27
Again you can just do this in the test rather than
mythria
2016/02/04 10:28:53
Done.
| |
102 Handle<JSFunction> function = GetBytecodeFunction<A...>(); | |
103 auto interpreter_callable = InterpreterCallable<A...>(isolate_, function); | |
104 i::FLAG_legacy_const = false; | |
105 return interpreter_callable; | |
106 } | |
107 | |
108 Local<Message> CheckThrowsReturnMessage() { | |
109 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_)); | |
110 auto callable = GetCallable<>(); | |
111 MaybeHandle<Object> no_result = callable(); | |
112 CHECK(isolate_->has_pending_exception()); | |
113 CHECK(try_catch.HasCaught()); | |
114 CHECK(no_result.is_null()); | |
115 isolate_->OptionalRescheduleException(true); | |
116 CHECK(!try_catch.Message().IsEmpty()); | |
117 return try_catch.Message(); | |
118 } | |
119 | |
99 static Handle<Object> NewObject(const char* script) { | 120 static Handle<Object> NewObject(const char* script) { |
100 return v8::Utils::OpenHandle(*CompileRun(script)); | 121 return v8::Utils::OpenHandle(*CompileRun(script)); |
101 } | 122 } |
102 | 123 |
103 static Handle<String> GetName(Isolate* isolate, const char* name) { | 124 static Handle<String> GetName(Isolate* isolate, const char* name) { |
104 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(name); | 125 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(name); |
105 return isolate->factory()->string_table()->LookupString(isolate, result); | 126 return isolate->factory()->string_table()->LookupString(isolate, result); |
106 } | 127 } |
107 | 128 |
108 static std::string SourceForBody(const char* body) { | 129 static std::string SourceForBody(const char* body) { |
(...skipping 3718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3827 InterpreterTester tester(handles.main_isolate(), source.c_str()); | 3848 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
3828 auto callable = tester.GetCallable<>(); | 3849 auto callable = tester.GetCallable<>(); |
3829 | 3850 |
3830 Handle<i::Object> return_value = callable().ToHandleChecked(); | 3851 Handle<i::Object> return_value = callable().ToHandleChecked(); |
3831 CHECK(return_value->SameValue(*do_expr[i].second)); | 3852 CHECK(return_value->SameValue(*do_expr[i].second)); |
3832 } | 3853 } |
3833 | 3854 |
3834 FLAG_harmony_do_expressions = old_flag; | 3855 FLAG_harmony_do_expressions = old_flag; |
3835 } | 3856 } |
3836 | 3857 |
3858 TEST(InterpreterConstDeclaration) { | |
3859 HandleAndZoneScope handles; | |
3860 i::Isolate* isolate = handles.main_isolate(); | |
3861 i::Factory* factory = isolate->factory(); | |
3862 | |
3863 std::pair<const char*, Handle<Object>> const_decl[] = { | |
3864 {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)}, | |
3865 {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)}, | |
3866 {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, | |
3867 {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, | |
3868 {"let x; return x;", factory->undefined_value()}, | |
3869 {"var x = 10; { let x = 30; } return x;", | |
3870 handle(Smi::FromInt(10), isolate)}, | |
3871 {"let x = 10; { let x = 20; } return x;", | |
3872 handle(Smi::FromInt(10), isolate)}, | |
3873 {"var x = 10; eval('let x = 20;'); return x;", | |
3874 handle(Smi::FromInt(10), isolate)}, | |
3875 {"var x = 10; eval('const x = 20;'); return x;", | |
3876 handle(Smi::FromInt(10), isolate)}, | |
3877 {"var x = 10; { const x = 20; } return x;", | |
3878 handle(Smi::FromInt(10), isolate)}, | |
3879 {"var x = 10; { const x = 20; return x;} return -1;", | |
3880 handle(Smi::FromInt(20), isolate)}, | |
3881 {"var a = 10;\n" | |
3882 "for (var i = 0; i < 10; ++i) {\n" | |
3883 " const x = i;\n" // const declarations are block scoped. | |
3884 " a = a + x;\n" | |
3885 "}\n" | |
3886 "return a;\n", | |
3887 handle(Smi::FromInt(55), isolate)}, | |
3888 }; | |
3889 | |
3890 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
rmcilroy
2016/02/03 12:28:27
comment - tests for sloppy mode.
mythria
2016/02/04 10:28:53
Done.
| |
3891 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); | |
3892 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
3893 auto callable = tester.GetCallable<>(); | |
3894 | |
3895 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
3896 CHECK(return_value->SameValue(*const_decl[i].second)); | |
3897 } | |
3898 | |
3899 // Tests for strict mode. | |
3900 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
3901 std::string strict_body = | |
3902 "'use strict'; " + std::string(const_decl[i].first); | |
3903 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); | |
3904 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
3905 auto callable = tester.GetCallable<>(); | |
3906 | |
3907 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
3908 CHECK(return_value->SameValue(*const_decl[i].second)); | |
3909 } | |
3910 } | |
3911 | |
3912 TEST(InterpreterConstDeclarationLookupSlots) { | |
3913 HandleAndZoneScope handles; | |
3914 i::Isolate* isolate = handles.main_isolate(); | |
3915 i::Factory* factory = isolate->factory(); | |
3916 | |
3917 std::pair<const char*, Handle<Object>> const_decl[] = { | |
3918 {"const x = 3; function f1() {return x;}; return x;", | |
3919 handle(Smi::FromInt(3), isolate)}, | |
3920 {"let x = 10; x = x + 20; function f1() {return x;}; return x;", | |
3921 handle(Smi::FromInt(30), isolate)}, | |
3922 {"let x; x = 20; function f1() {return x;}; return x;", | |
3923 handle(Smi::FromInt(20), isolate)}, | |
3924 {"let x; function f1() {return x;}; return x;", | |
3925 factory->undefined_value()}, | |
3926 }; | |
3927 | |
3928 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
rmcilroy
2016/02/03 12:28:27
ditto
mythria
2016/02/04 10:28:53
Done.
| |
3929 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); | |
3930 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
3931 auto callable = tester.GetCallable<>(); | |
3932 | |
3933 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
3934 CHECK(return_value->SameValue(*const_decl[i].second)); | |
3935 } | |
3936 | |
3937 // Tests for strict mode. | |
3938 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
3939 std::string strict_body = | |
3940 "'use strict'; " + std::string(const_decl[i].first); | |
3941 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); | |
3942 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
3943 auto callable = tester.GetCallable<>(); | |
3944 | |
3945 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
3946 CHECK(return_value->SameValue(*const_decl[i].second)); | |
3947 } | |
3948 } | |
3949 | |
3950 TEST(InterpreterConstInLookupContextChain) { | |
3951 HandleAndZoneScope handles; | |
3952 i::Isolate* isolate = handles.main_isolate(); | |
3953 | |
3954 const char* prologue = | |
3955 "function OuterMost() {\n" | |
3956 " const outerConst = 10;\n" | |
3957 " let outerLet = 20;\n" | |
3958 " function Outer() {\n" | |
3959 " function Inner() {\n" | |
3960 " this.innerFunc = function() { "; | |
3961 const char* epilogue = | |
3962 " }\n" | |
3963 " }\n" | |
3964 " this.getInnerFunc =" | |
3965 " function() {return new Inner().innerFunc;}\n" | |
3966 " }\n" | |
3967 " this.getOuterFunc =" | |
3968 " function() {return new Outer().getInnerFunc();}" | |
3969 "}\n" | |
3970 "var f = new OuterMost().getOuterFunc();\n" | |
3971 "f();\n"; | |
3972 std::pair<const char*, Handle<Object>> const_decl[] = { | |
3973 {"return outerConst;", handle(Smi::FromInt(10), isolate)}, | |
3974 {"return outerLet;", handle(Smi::FromInt(20), isolate)}, | |
3975 {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)}, | |
3976 {"var outerLet = 40; return outerLet;", | |
3977 handle(Smi::FromInt(40), isolate)}, | |
3978 {"var outerConst = 50; return outerConst;", | |
3979 handle(Smi::FromInt(50), isolate)}, | |
3980 {"try { outerConst = 30 } catch(e) { return -1; }", | |
3981 handle(Smi::FromInt(-1), isolate)}}; | |
3982 | |
3983 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
3984 std::string script = std::string(prologue) + | |
3985 std::string(const_decl[i].first) + | |
3986 std::string(epilogue); | |
3987 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*"); | |
3988 auto callable = tester.GetCallable<>(); | |
3989 | |
3990 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
3991 CHECK(return_value->SameValue(*const_decl[i].second)); | |
3992 } | |
3993 | |
3994 // Tests for Legacy constant. | |
3995 std::pair<const char*, Handle<Object>> legacy_const_decl[] = { | |
3996 {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)}, | |
3997 {"outerConst = 30; return outerConst;", | |
3998 handle(Smi::FromInt(10), isolate)}, | |
3999 }; | |
4000 | |
4001 for (size_t i = 0; i < arraysize(legacy_const_decl); i++) { | |
4002 std::string script = std::string(prologue) + | |
4003 std::string(legacy_const_decl[i].first) + | |
4004 std::string(epilogue); | |
4005 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*"); | |
4006 auto callable = tester.GetCallableWithLegacyConstants<>(); | |
4007 | |
4008 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
4009 CHECK(return_value->SameValue(*legacy_const_decl[i].second)); | |
4010 } | |
4011 } | |
4012 | |
4013 TEST(InterpreterIllegalConstDeclaration) { | |
4014 HandleAndZoneScope handles; | |
4015 | |
4016 std::pair<const char*, const char*> const_decl[] = { | |
4017 {"const x = x = 10 + 3; return x;", | |
4018 "Uncaught ReferenceError: x is not defined"}, | |
4019 {"const x = 10; x = 20; return x;", | |
4020 "Uncaught TypeError: Assignment to constant variable."}, | |
4021 {"const x = 10; { x = 20; } return x;", | |
4022 "Uncaught TypeError: Assignment to constant variable."}, | |
4023 {"const x = 10; eval('x = 20;'); return x;", | |
4024 "Uncaught TypeError: Assignment to constant variable."}, | |
4025 {"let x = x + 10; return x;", | |
4026 "Uncaught ReferenceError: x is not defined"}, | |
4027 {"'use strict'; (function f1() { f1 = 123; })() ", | |
4028 "Uncaught TypeError: Assignment to constant variable."}, | |
4029 }; | |
4030 | |
4031 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
rmcilroy
2016/02/03 12:28:27
ditto
mythria
2016/02/04 10:28:53
Done.
| |
4032 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); | |
4033 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
4034 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); | |
4035 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second); | |
4036 CHECK( | |
4037 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) | |
4038 .FromJust()); | |
4039 } | |
4040 | |
4041 // Tests for strict mode. | |
4042 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
4043 std::string strict_body = | |
4044 "'use strict'; " + std::string(const_decl[i].first); | |
4045 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); | |
4046 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
4047 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); | |
4048 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second); | |
4049 CHECK( | |
4050 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) | |
4051 .FromJust()); | |
4052 } | |
4053 } | |
4054 | |
4055 TEST(InterpreterLegacyConstDeclaration) { | |
4056 HandleAndZoneScope handles; | |
4057 i::Isolate* isolate = handles.main_isolate(); | |
4058 | |
4059 std::pair<const char*, Handle<Object>> const_decl[] = { | |
4060 {"const x = (x = 10) + 3; return x;", handle(Smi::FromInt(13), isolate)}, | |
4061 {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)}, | |
4062 {"var a = 10;\n" | |
4063 "for (var i = 0; i < 10; ++i) {\n" | |
4064 " const x = i;\n" // Legacy constants are not block scoped. | |
4065 " a = a + x;\n" | |
4066 "}\n" | |
4067 "return a;\n", | |
4068 handle(Smi::FromInt(10), isolate)}, | |
4069 {"const x = 20; eval('x = 10;'); return x;", | |
4070 handle(Smi::FromInt(20), isolate)}, | |
4071 }; | |
4072 | |
4073 for (size_t i = 0; i < arraysize(const_decl); i++) { | |
4074 std::string source(InterpreterTester::SourceForBody(const_decl[i].first) + | |
4075 " f();"); | |
4076 InterpreterTester tester(handles.main_isolate(), source.c_str()); | |
4077 auto callable = tester.GetCallableWithLegacyConstants<>(); | |
4078 | |
4079 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
4080 CHECK(return_value->SameValue(*const_decl[i].second)); | |
4081 } | |
4082 } | |
4083 | |
3837 } // namespace interpreter | 4084 } // namespace interpreter |
3838 } // namespace internal | 4085 } // namespace internal |
3839 } // namespace v8 | 4086 } // namespace v8 |
OLD | NEW |