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; |
| 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 3564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3673 for (size_t i = 0; i < arraysize(eval_func_decl); i++) { | 3694 for (size_t i = 0; i < arraysize(eval_func_decl); i++) { |
3674 InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first, | 3695 InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first, |
3675 "*"); | 3696 "*"); |
3676 auto callable = tester.GetCallable<>(); | 3697 auto callable = tester.GetCallable<>(); |
3677 | 3698 |
3678 Handle<i::Object> return_value = callable().ToHandleChecked(); | 3699 Handle<i::Object> return_value = callable().ToHandleChecked(); |
3679 CHECK(return_value->SameValue(*eval_func_decl[i].second)); | 3700 CHECK(return_value->SameValue(*eval_func_decl[i].second)); |
3680 } | 3701 } |
3681 } | 3702 } |
3682 | 3703 |
| 3704 TEST(InterpreterConstDeclaration) { |
| 3705 HandleAndZoneScope handles; |
| 3706 i::Isolate* isolate = handles.main_isolate(); |
| 3707 i::Factory* factory = isolate->factory(); |
| 3708 |
| 3709 std::pair<const char*, Handle<Object>> const_decl[] = { |
| 3710 {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)}, |
| 3711 {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)}, |
| 3712 {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, |
| 3713 {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, |
| 3714 {"let x; return x;", factory->undefined_value()}, |
| 3715 {"var x = 10; { let x = 30; } return x;", |
| 3716 handle(Smi::FromInt(10), isolate)}, |
| 3717 {"let x = 10; { let x = 20; } return x;", |
| 3718 handle(Smi::FromInt(10), isolate)}, |
| 3719 {"var x = 10; eval('let x = 20;'); return x;", |
| 3720 handle(Smi::FromInt(10), isolate)}, |
| 3721 {"var x = 10; eval('const x = 20;'); return x;", |
| 3722 handle(Smi::FromInt(10), isolate)}, |
| 3723 {"var x = 10; { const x = 20; } return x;", |
| 3724 handle(Smi::FromInt(10), isolate)}, |
| 3725 {"var x = 10; { const x = 20; return x;} return -1;", |
| 3726 handle(Smi::FromInt(20), isolate)}, |
| 3727 {"var a = 10;\n" |
| 3728 "for (var i = 0; i < 10; ++i) {\n" |
| 3729 " const x = i;\n" // const declarations are block scoped. |
| 3730 " a = a + x;\n" |
| 3731 "}\n" |
| 3732 "return a;\n", |
| 3733 handle(Smi::FromInt(55), isolate)}, |
| 3734 }; |
| 3735 |
| 3736 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3737 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); |
| 3738 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3739 auto callable = tester.GetCallable<>(); |
| 3740 |
| 3741 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3742 CHECK(return_value->SameValue(*const_decl[i].second)); |
| 3743 } |
| 3744 |
| 3745 // Tests for strict mode. |
| 3746 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3747 std::string strict_body = |
| 3748 "'use strict'; " + std::string(const_decl[i].first); |
| 3749 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); |
| 3750 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3751 auto callable = tester.GetCallable<>(); |
| 3752 |
| 3753 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3754 CHECK(return_value->SameValue(*const_decl[i].second)); |
| 3755 } |
| 3756 } |
| 3757 |
| 3758 TEST(InterpreterConstDeclarationLookupSlots) { |
| 3759 HandleAndZoneScope handles; |
| 3760 i::Isolate* isolate = handles.main_isolate(); |
| 3761 i::Factory* factory = isolate->factory(); |
| 3762 |
| 3763 std::pair<const char*, Handle<Object>> const_decl[] = { |
| 3764 {"const x = 3; function f1() {return x;}; return x;", |
| 3765 handle(Smi::FromInt(3), isolate)}, |
| 3766 {"let x = 10; x = x + 20; function f1() {return x;}; return x;", |
| 3767 handle(Smi::FromInt(30), isolate)}, |
| 3768 {"let x; x = 20; function f1() {return x;}; return x;", |
| 3769 handle(Smi::FromInt(20), isolate)}, |
| 3770 {"let x; function f1() {return x;}; return x;", |
| 3771 factory->undefined_value()}, |
| 3772 }; |
| 3773 |
| 3774 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3775 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); |
| 3776 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3777 auto callable = tester.GetCallable<>(); |
| 3778 |
| 3779 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3780 CHECK(return_value->SameValue(*const_decl[i].second)); |
| 3781 } |
| 3782 |
| 3783 // Tests for strict mode. |
| 3784 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3785 std::string strict_body = |
| 3786 "'use strict'; " + std::string(const_decl[i].first); |
| 3787 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); |
| 3788 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3789 auto callable = tester.GetCallable<>(); |
| 3790 |
| 3791 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3792 CHECK(return_value->SameValue(*const_decl[i].second)); |
| 3793 } |
| 3794 } |
| 3795 |
| 3796 TEST(InterpreterConstInLookupContextChain) { |
| 3797 HandleAndZoneScope handles; |
| 3798 i::Isolate* isolate = handles.main_isolate(); |
| 3799 |
| 3800 const char* prologue = |
| 3801 "function OuterMost() {\n" |
| 3802 " const outerConst = 10;\n" |
| 3803 " let outerLet = 20;\n" |
| 3804 " function Outer() {\n" |
| 3805 " function Inner() {\n" |
| 3806 " this.innerFunc = function() { "; |
| 3807 const char* epilogue = |
| 3808 " }\n" |
| 3809 " }\n" |
| 3810 " this.getInnerFunc =" |
| 3811 " function() {return new Inner().innerFunc;}\n" |
| 3812 " }\n" |
| 3813 " this.getOuterFunc =" |
| 3814 " function() {return new Outer().getInnerFunc();}" |
| 3815 "}\n" |
| 3816 "var f = new OuterMost().getOuterFunc();\n" |
| 3817 "f();\n"; |
| 3818 std::pair<const char*, Handle<Object>> const_decl[] = { |
| 3819 {"return outerConst;", handle(Smi::FromInt(10), isolate)}, |
| 3820 {"return outerLet;", handle(Smi::FromInt(20), isolate)}, |
| 3821 {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)}, |
| 3822 {"var outerLet = 40; return outerLet;", |
| 3823 handle(Smi::FromInt(40), isolate)}, |
| 3824 {"var outerConst = 50; return outerConst;", |
| 3825 handle(Smi::FromInt(50), isolate)}, |
| 3826 {"try { outerConst = 30 } catch(e) { return -1; }", |
| 3827 handle(Smi::FromInt(-1), isolate)}}; |
| 3828 |
| 3829 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3830 std::string script = std::string(prologue) + |
| 3831 std::string(const_decl[i].first) + |
| 3832 std::string(epilogue); |
| 3833 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*"); |
| 3834 auto callable = tester.GetCallable<>(); |
| 3835 |
| 3836 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3837 CHECK(return_value->SameValue(*const_decl[i].second)); |
| 3838 } |
| 3839 |
| 3840 // Tests for Legacy constant. |
| 3841 std::pair<const char*, Handle<Object>> legacy_const_decl[] = { |
| 3842 {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)}, |
| 3843 {"outerConst = 30; return outerConst;", |
| 3844 handle(Smi::FromInt(10), isolate)}, |
| 3845 }; |
| 3846 |
| 3847 for (size_t i = 0; i < arraysize(legacy_const_decl); i++) { |
| 3848 std::string script = std::string(prologue) + |
| 3849 std::string(legacy_const_decl[i].first) + |
| 3850 std::string(epilogue); |
| 3851 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*"); |
| 3852 auto callable = tester.GetCallableWithLegacyConstants<>(); |
| 3853 |
| 3854 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3855 CHECK(return_value->SameValue(*legacy_const_decl[i].second)); |
| 3856 } |
| 3857 } |
| 3858 |
| 3859 TEST(InterpreterIllegalConstDeclaration) { |
| 3860 HandleAndZoneScope handles; |
| 3861 |
| 3862 std::pair<const char*, const char*> const_decl[] = { |
| 3863 {"const x = x = 10 + 3; return x;", |
| 3864 "Uncaught ReferenceError: x is not defined"}, |
| 3865 {"const x = 10; x = 20; return x;", |
| 3866 "Uncaught TypeError: Assignment to constant variable."}, |
| 3867 {"const x = 10; { x = 20; } return x;", |
| 3868 "Uncaught TypeError: Assignment to constant variable."}, |
| 3869 {"const x = 10; eval('x = 20;'); return x;", |
| 3870 "Uncaught TypeError: Assignment to constant variable."}, |
| 3871 {"let x = x + 10; return x;", |
| 3872 "Uncaught ReferenceError: x is not defined"}, |
| 3873 {"'use strict'; (function f1() { f1 = 123; })() ", |
| 3874 "Uncaught TypeError: Assignment to constant variable."}, |
| 3875 }; |
| 3876 |
| 3877 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3878 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); |
| 3879 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3880 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
| 3881 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second); |
| 3882 char msg[100]; |
| 3883 message->WriteUtf8(msg); |
| 3884 printf("%s\n", msg); |
| 3885 CHECK( |
| 3886 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
| 3887 .FromJust()); |
| 3888 } |
| 3889 |
| 3890 // Tests for strict mode. |
| 3891 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3892 std::string strict_body = |
| 3893 "'use strict'; " + std::string(const_decl[i].first); |
| 3894 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); |
| 3895 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3896 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
| 3897 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second); |
| 3898 CHECK( |
| 3899 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
| 3900 .FromJust()); |
| 3901 } |
| 3902 } |
| 3903 |
| 3904 TEST(InterpreterLegacyConstDeclaration) { |
| 3905 HandleAndZoneScope handles; |
| 3906 i::Isolate* isolate = handles.main_isolate(); |
| 3907 |
| 3908 std::pair<const char*, Handle<Object>> const_decl[] = { |
| 3909 {"const x = x = 10 + 3; return x;", handle(Smi::FromInt(13), isolate)}, |
| 3910 {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)}, |
| 3911 {"var a = 10;\n" |
| 3912 "for (var i = 0; i < 10; ++i) {\n" |
| 3913 " const x = i;\n" // Legacy constants are not block scoped. |
| 3914 " a = a + x;\n" |
| 3915 "}\n" |
| 3916 "return a;\n", |
| 3917 handle(Smi::FromInt(10), isolate)}, |
| 3918 {"const x = 20; eval('x = 10;'); return x;", |
| 3919 handle(Smi::FromInt(20), isolate)}, |
| 3920 }; |
| 3921 |
| 3922 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 3923 std::string source(InterpreterTester::SourceForBody(const_decl[i].first) + |
| 3924 " f();"); |
| 3925 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3926 auto callable = tester.GetCallableWithLegacyConstants<>(); |
| 3927 |
| 3928 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3929 CHECK(return_value->SameValue(*const_decl[i].second)); |
| 3930 } |
| 3931 } |
| 3932 |
3683 } // namespace interpreter | 3933 } // namespace interpreter |
3684 } // namespace internal | 3934 } // namespace internal |
3685 } // namespace v8 | 3935 } // namespace v8 |
OLD | NEW |