| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6c56c97 commit 17e6031
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1949,6 +1949,15 @@ Object Isolate::UnwindAndFindHandler() { | |||
| 1949 | 1949 | // Special handling of termination exceptions, uncatchable by JavaScript and | |
| 1950 | 1950 | // Wasm code, we unwind the handlers until the top ENTRY handler is found. | |
| 1951 | 1951 | bool catchable_by_js = is_catchable_by_javascript(exception); | |
| 1952 | + if (!catchable_by_js && !context().is_null()) { | ||
| 1953 | + // Because the array join stack will not pop the elements when throwing the | ||
| 1954 | + // uncatchable terminate exception, we need to clear the array join stack to | ||
| 1955 | + // avoid leaving the stack in an invalid state. | ||
| 1956 | + // See also CycleProtectedArrayJoin. | ||
| 1957 | + raw_native_context().set_array_join_stack( | ||
| 1958 | + ReadOnlyRoots(this).undefined_value()); | ||
| 1959 | + } | ||
| 1960 | + | ||
| 1952 | 1961 | int visited_frames = 0; | |
| 1953 | 1962 | ||
| 1954 | 1963 | #if V8_ENABLE_WEBASSEMBLY | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,48 @@ | |||
| 1 | + Tests that Runtime.evaluate with REPL mode correctly handles Array.prototype.join. | ||
| 2 | + { | ||
| 3 | + id : <messageId> | ||
| 4 | + result : { | ||
| 5 | + result : { | ||
| 6 | + className : Array | ||
| 7 | + description : Array(1) | ||
| 8 | + objectId : <objectId> | ||
| 9 | + subtype : array | ||
| 10 | + type : object | ||
| 11 | + } | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | + { | ||
| 15 | + id : <messageId> | ||
| 16 | + result : { | ||
| 17 | + exceptionDetails : { | ||
| 18 | + columnNumber : -1 | ||
| 19 | + exception : { | ||
| 20 | + className : EvalError | ||
| 21 | + description : EvalError: Possible side-effect in debug-evaluate | ||
| 22 | + objectId : <objectId> | ||
| 23 | + subtype : error | ||
| 24 | + type : object | ||
| 25 | + } | ||
| 26 | + exceptionId : <exceptionId> | ||
| 27 | + lineNumber : -1 | ||
| 28 | + scriptId : <scriptId> | ||
| 29 | + text : Uncaught | ||
| 30 | + } | ||
| 31 | + result : { | ||
| 32 | + className : EvalError | ||
| 33 | + description : EvalError: Possible side-effect in debug-evaluate | ||
| 34 | + objectId : <objectId> | ||
| 35 | + subtype : error | ||
| 36 | + type : object | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | + } | ||
| 40 | + { | ||
| 41 | + id : <messageId> | ||
| 42 | + result : { | ||
| 43 | + result : { | ||
| 44 | + type : string | ||
| 45 | + value : /a/ | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,32 @@ | |||
| 1 | + // Copyright 2022 the V8 project authors. All rights reserved. | ||
| 2 | + // Use of this source code is governed by a BSD-style license that can be | ||
| 3 | + // found in the LICENSE file. | ||
| 4 | + | ||
| 5 | + let {Protocol} = InspectorTest.start( | ||
| 6 | + 'Tests that Runtime.evaluate with REPL mode correctly handles \ | ||
| 7 | + Array.prototype.join.'); | ||
| 8 | + | ||
| 9 | + Protocol.Runtime.enable(); | ||
| 10 | + (async function () { | ||
| 11 | + await evaluateReplWithSideEffects('a=[/a/]') | ||
| 12 | + await evaluateRepl('a.toString()'); | ||
| 13 | + await evaluateReplWithSideEffects('a.toString()'); | ||
| 14 | + | ||
| 15 | + InspectorTest.completeTest(); | ||
| 16 | + })(); | ||
| 17 | + | ||
| 18 | + async function evaluateRepl(expression) { | ||
| 19 | + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ | ||
| 20 | + expression: expression, | ||
| 21 | + replMode: true, | ||
| 22 | + throwOnSideEffect: true | ||
| 23 | + })); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + async function evaluateReplWithSideEffects(expression) { | ||
| 27 | + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ | ||
| 28 | + expression: expression, | ||
| 29 | + replMode: true, | ||
| 30 | + throwOnSideEffect: false | ||
| 31 | + })); | ||
| 32 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,6 +33,7 @@ | |||
| 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) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments