Chromium Code Reviews| 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 |