|
33 | 33 | #include "src/init/v8.h"
|
34 | 34 | #include "src/objects/objects-inl.h"
|
35 | 35 | #include "test/unittests/test-utils.h"
|
| 36 | +#include "testing/gmock-support.h" |
36 | 37 | #include "testing/gtest/include/gtest/gtest.h"
|
37 | 38 |
|
38 | 39 | namespace v8 {
|
@@ -889,6 +890,75 @@ TEST_F(ThreadTerminationTest, TerminateConsole) {
|
889 | 890 | CHECK(isolate()->IsExecutionTerminating());
|
890 | 891 | }
|
891 | 892 |
|
| 893 | +TEST_F(ThreadTerminationTest, TerminationClearArrayJoinStack) { |
| 894 | + internal::v8_flags.allow_natives_syntax = true; |
| 895 | + HandleScope scope(isolate()); |
| 896 | + Local<ObjectTemplate> global_template = |
| 897 | + CreateGlobalTemplate(isolate(), TerminateCurrentThread, DoLoopNoCall); |
| 898 | + { |
| 899 | + Local<Context> context = Context::New(isolate(), nullptr, global_template); |
| 900 | + Context::Scope context_scope(context); |
| 901 | + { |
| 902 | + TryCatch try_catch(isolate()); |
| 903 | + TryRunJS( |
| 904 | + "var error = false;" |
| 905 | + "var a = [{toString(){if(error)loop()}}];" |
| 906 | + "function Join(){ return a.join();}; " |
| 907 | + "%PrepareFunctionForOptimization(Join);" |
| 908 | + "Join();" |
| 909 | + "%OptimizeFunctionOnNextCall(Join);" |
| 910 | + "error = true;" |
| 911 | + "Join();"); |
| 912 | + CHECK(try_catch.HasTerminated()); |
| 913 | + CHECK(isolate()->IsExecutionTerminating()); |
| 914 | + } |
| 915 | + EXPECT_THAT(RunJS("a[0] = 1; Join();"), testing::IsString("1")); |
| 916 | + } |
| 917 | + { |
| 918 | + Local<Context> context = Context::New(isolate(), nullptr, global_template); |
| 919 | + Context::Scope context_scope(context); |
| 920 | + { |
| 921 | + TryCatch try_catch(isolate()); |
| 922 | + TryRunJS( |
| 923 | + "var a = [{toString(){loop()}}];" |
| 924 | + "function Join(){ return a.join();}; " |
| 925 | + "Join();"); |
| 926 | + CHECK(try_catch.HasTerminated()); |
| 927 | + CHECK(isolate()->IsExecutionTerminating()); |
| 928 | + } |
| 929 | + EXPECT_THAT(RunJS("a[0] = 1; Join();"), testing::IsString("1")); |
| 930 | + } |
| 931 | + { |
| 932 | + ConsoleImpl console; |
| 933 | + debug::SetConsoleDelegate(isolate(), &console); |
| 934 | + HandleScope scope(isolate()); |
| 935 | + Local<Context> context = Context::New(isolate(), nullptr, global_template); |
| 936 | + Context::Scope context_scope(context); |
| 937 | + { |
| 938 | + // setup console global. |
| 939 | + HandleScope scope(isolate()); |
| 940 | + Local<String> name = String::NewFromUtf8Literal( |
| 941 | + isolate(), "console", NewStringType::kInternalized); |
| 942 | + Local<Value> console = context->GetExtrasBindingObject() |
| 943 | + ->Get(context, name) |
| 944 | + .ToLocalChecked(); |
| 945 | + context->Global()->Set(context, name, console).FromJust(); |
| 946 | + } |
| 947 | + CHECK(!isolate()->IsExecutionTerminating()); |
| 948 | + { |
| 949 | + TryCatch try_catch(isolate()); |
| 950 | + CHECK(!isolate()->IsExecutionTerminating()); |
| 951 | + CHECK(TryRunJS("var a = [{toString(){terminate();console.log();fail()}}];" |
| 952 | + "function Join() {return a.join();}" |
| 953 | + "Join();") |
| 954 | + .IsEmpty()); |
| 955 | + CHECK(try_catch.HasCaught()); |
| 956 | + CHECK(isolate()->IsExecutionTerminating()); |
| 957 | + } |
| 958 | + EXPECT_THAT(RunJS("a[0] = 1; Join();"), testing::IsString("1")); |
| 959 | + } |
| 960 | +} |
| 961 | + |
892 | 962 | class TerminatorSleeperThread : public base::Thread {
|
893 | 963 | public:
|
894 | 964 | explicit TerminatorSleeperThread(Isolate* isolate, int sleep_ms)
|
|
0 commit comments