[d8] Exit with error code upon unhandled promise rejection
With this CL d8 exits with an error code if there is an unhandled promise rejection, e.g. due tue a failed assertion in a promise. Up until now these assertions were just ignored. Bug: v8:10556 Change-Id: I25f20e4be45a2de130562deb15f6a144f0ac976f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2238569 Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#68503}
This commit is contained in:
parent
3fd18f1258
commit
1335b1ec36
111
src/d8/d8.cc
111
src/d8/d8.cc
@ -12,6 +12,7 @@
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -464,6 +465,7 @@ std::map<v8::Isolate*, int> Shell::isolate_running_streaming_tasks_;
|
||||
base::LazyMutex Shell::cached_code_mutex_;
|
||||
std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
|
||||
Shell::cached_code_map_;
|
||||
std::atomic<int> Shell::unhandled_promise_rejections_{0};
|
||||
|
||||
Global<Context> Shell::evaluation_context_;
|
||||
ArrayBuffer::Allocator* Shell::array_buffer_allocator;
|
||||
@ -665,7 +667,10 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
|
||||
StoreInCodeCache(isolate, source, cached_data);
|
||||
delete cached_data;
|
||||
}
|
||||
if (process_message_queue && !EmptyMessageQueues(isolate)) success = false;
|
||||
if (process_message_queue) {
|
||||
if (!EmptyMessageQueues(isolate)) success = false;
|
||||
if (!HandleUnhandledPromiseRejections(isolate)) success = false;
|
||||
}
|
||||
data->realm_current_ = data->realm_switch_;
|
||||
}
|
||||
Local<Value> result;
|
||||
@ -1161,6 +1166,45 @@ MaybeLocal<Context> PerIsolateData::GetTimeoutContext() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void PerIsolateData::RemoveUnhandledPromise(Local<Promise> promise) {
|
||||
// Remove handled promises from the list
|
||||
DCHECK_EQ(promise->GetIsolate(), isolate_);
|
||||
for (auto it = unhandled_promises_.begin(); it != unhandled_promises_.end();
|
||||
++it) {
|
||||
v8::Local<v8::Promise> unhandled_promise = std::get<0>(*it).Get(isolate_);
|
||||
if (unhandled_promise == promise) {
|
||||
unhandled_promises_.erase(it--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerIsolateData::AddUnhandledPromise(Local<Promise> promise,
|
||||
Local<Message> message,
|
||||
Local<Value> exception) {
|
||||
DCHECK_EQ(promise->GetIsolate(), isolate_);
|
||||
unhandled_promises_.push_back(
|
||||
std::make_tuple(v8::Global<v8::Promise>(isolate_, promise),
|
||||
v8::Global<v8::Message>(isolate_, message),
|
||||
v8::Global<v8::Value>(isolate_, exception)));
|
||||
}
|
||||
|
||||
size_t PerIsolateData::GetUnhandledPromiseCount() {
|
||||
return unhandled_promises_.size();
|
||||
}
|
||||
|
||||
int PerIsolateData::HandleUnhandledPromiseRejections() {
|
||||
int unhandled_promises_count = 0;
|
||||
v8::HandleScope scope(isolate_);
|
||||
for (auto& tuple : unhandled_promises_) {
|
||||
Local<v8::Message> message = std::get<1>(tuple).Get(isolate_);
|
||||
Local<v8::Value> value = std::get<2>(tuple).Get(isolate_);
|
||||
Shell::ReportException(isolate_, message, value);
|
||||
unhandled_promises_count++;
|
||||
}
|
||||
unhandled_promises_.clear();
|
||||
return unhandled_promises_count;
|
||||
}
|
||||
|
||||
PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
|
||||
data_->realm_count_ = 1;
|
||||
data_->realm_current_ = 0;
|
||||
@ -2159,8 +2203,50 @@ static void PrintMessageCallback(Local<Message> message, Local<Value> error) {
|
||||
printf("%s:%i: %s\n", filename_string, linenum, msg_string);
|
||||
}
|
||||
|
||||
void Shell::PromiseRejectCallback(v8::PromiseRejectMessage data) {
|
||||
if (options.ignore_unhandled_promises) return;
|
||||
if (data.GetEvent() == v8::kPromiseRejectAfterResolved ||
|
||||
data.GetEvent() == v8::kPromiseResolveAfterResolved) {
|
||||
// Ignore reject/resolve after resolved.
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Promise> promise = data.GetPromise();
|
||||
v8::Isolate* isolate = promise->GetIsolate();
|
||||
PerIsolateData* isolate_data = PerIsolateData::Get(isolate);
|
||||
|
||||
if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
|
||||
isolate_data->RemoveUnhandledPromise(promise);
|
||||
return;
|
||||
}
|
||||
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
bool capture_exceptions =
|
||||
i_isolate->get_capture_stack_trace_for_uncaught_exceptions();
|
||||
isolate->SetCaptureStackTraceForUncaughtExceptions(true);
|
||||
v8::Local<Value> exception = data.GetValue();
|
||||
v8::Local<Message> message;
|
||||
// Assume that all objects are stack-traces.
|
||||
if (exception->IsObject()) {
|
||||
message = v8::Exception::CreateMessage(isolate, exception);
|
||||
}
|
||||
if (!exception->IsNativeError() &&
|
||||
(message.IsEmpty() || message->GetStackTrace().IsEmpty())) {
|
||||
// If there is no real Error object, manually throw and catch a stack trace.
|
||||
v8::TryCatch try_catch(isolate);
|
||||
try_catch.SetVerbose(true);
|
||||
isolate->ThrowException(v8::Exception::Error(
|
||||
v8::String::NewFromUtf8Literal(isolate, "Unhandled Promise.")));
|
||||
message = try_catch.Message();
|
||||
exception = try_catch.Exception();
|
||||
}
|
||||
isolate->SetCaptureStackTraceForUncaughtExceptions(capture_exceptions);
|
||||
|
||||
isolate_data->AddUnhandledPromise(promise, message, exception);
|
||||
}
|
||||
|
||||
void Shell::Initialize(Isolate* isolate, D8Console* console,
|
||||
bool isOnMainThread) {
|
||||
isolate->SetPromiseRejectCallback(PromiseRejectCallback);
|
||||
if (isOnMainThread) {
|
||||
// Set up counters
|
||||
if (i::FLAG_map_counters[0] != '\0') {
|
||||
@ -2968,9 +3054,7 @@ void Worker::ExecuteInThread() {
|
||||
in_semaphore_.Wait();
|
||||
std::unique_ptr<SerializationData> data;
|
||||
if (!in_queue_.Dequeue(&data)) continue;
|
||||
if (!data) {
|
||||
break;
|
||||
}
|
||||
if (!data) break;
|
||||
v8::TryCatch try_catch(isolate);
|
||||
try_catch.SetVerbose(true);
|
||||
HandleScope scope(isolate);
|
||||
@ -2983,6 +3067,7 @@ void Worker::ExecuteInThread() {
|
||||
USE(result);
|
||||
}
|
||||
}
|
||||
// TODO(cbruni): Check for unhandled promises here.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3083,6 +3168,9 @@ bool Shell::SetOptions(int argc, char* argv[]) {
|
||||
// Ignore any -f flags for compatibility with other stand-alone
|
||||
// JavaScript engines.
|
||||
continue;
|
||||
} else if (strcmp(argv[i], "--ignore-unhandled-promises") == 0) {
|
||||
options.ignore_unhandled_promises = true;
|
||||
argv[i] = nullptr;
|
||||
} else if (strcmp(argv[i], "--isolate") == 0) {
|
||||
options.num_isolates++;
|
||||
} else if (strcmp(argv[i], "--throws") == 0) {
|
||||
@ -3240,6 +3328,7 @@ int Shell::RunMain(Isolate* isolate, bool last_run) {
|
||||
PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
|
||||
if (!options.isolate_sources[0].Execute(isolate)) success = false;
|
||||
if (!CompleteMessageLoop(isolate)) success = false;
|
||||
if (!HandleUnhandledPromiseRejections(isolate)) success = false;
|
||||
}
|
||||
if (!use_existing_context) {
|
||||
DisposeModuleEmbedderData(context);
|
||||
@ -3267,6 +3356,11 @@ int Shell::RunMain(Isolate* isolate, bool last_run) {
|
||||
}
|
||||
}
|
||||
WaitForRunningWorkers();
|
||||
if (Shell::unhandled_promise_rejections_.load() > 0) {
|
||||
printf("%i pending unhandled Promise rejection(s) detected.\n",
|
||||
Shell::unhandled_promise_rejections_.load());
|
||||
success = false;
|
||||
}
|
||||
// In order to finish successfully, success must be != expected_to_throw.
|
||||
return success == Shell::options.expected_to_throw ? 1 : 0;
|
||||
}
|
||||
@ -3389,6 +3483,15 @@ void Shell::PostBlockingBackgroundTask(std::unique_ptr<Task> task) {
|
||||
g_default_platform->CallBlockingTaskOnWorkerThread(std::move(task));
|
||||
}
|
||||
|
||||
bool Shell::HandleUnhandledPromiseRejections(Isolate* isolate) {
|
||||
if (options.ignore_unhandled_promises) return true;
|
||||
PerIsolateData* data = PerIsolateData::Get(isolate);
|
||||
int count = data->HandleUnhandledPromiseRejections();
|
||||
Shell::unhandled_promise_rejections_.store(
|
||||
Shell::unhandled_promise_rejections_.load() + count);
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
class Serializer : public ValueSerializer::Delegate {
|
||||
public:
|
||||
explicit Serializer(Isolate* isolate)
|
||||
|
14
src/d8/d8.h
14
src/d8/d8.h
@ -234,6 +234,12 @@ class PerIsolateData {
|
||||
|
||||
AsyncHooks* GetAsyncHooks() { return async_hooks_wrapper_; }
|
||||
|
||||
void RemoveUnhandledPromise(Local<Promise> promise);
|
||||
void AddUnhandledPromise(Local<Promise> promise, Local<Message> message,
|
||||
Local<Value> exception);
|
||||
int HandleUnhandledPromiseRejections();
|
||||
size_t GetUnhandledPromiseCount();
|
||||
|
||||
private:
|
||||
friend class Shell;
|
||||
friend class RealmScope;
|
||||
@ -245,6 +251,8 @@ class PerIsolateData {
|
||||
Global<Value> realm_shared_;
|
||||
std::queue<Global<Function>> set_timeout_callbacks_;
|
||||
std::queue<Global<Context>> set_timeout_contexts_;
|
||||
std::vector<std::tuple<Global<Promise>, Global<Message>, Global<Value>>>
|
||||
unhandled_promises_;
|
||||
AsyncHooks* async_hooks_wrapper_;
|
||||
|
||||
int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
@ -272,6 +280,7 @@ class ShellOptions {
|
||||
bool interactive_shell = false;
|
||||
bool test_shell = false;
|
||||
bool expected_to_throw = false;
|
||||
bool ignore_unhandled_promises = false;
|
||||
bool mock_arraybuffer_allocator = false;
|
||||
size_t mock_arraybuffer_allocator_limit = 0;
|
||||
bool multi_mapped_mock_allocator = false;
|
||||
@ -332,6 +341,8 @@ class Shell : public i::AllStatic {
|
||||
static bool EmptyMessageQueues(Isolate* isolate);
|
||||
static bool CompleteMessageLoop(Isolate* isolate);
|
||||
|
||||
static bool HandleUnhandledPromiseRejections(Isolate* isolate);
|
||||
|
||||
static void PostForegroundTask(Isolate* isolate, std::unique_ptr<Task> task);
|
||||
static void PostBlockingBackgroundTask(std::unique_ptr<Task> task);
|
||||
|
||||
@ -472,6 +483,8 @@ class Shell : public i::AllStatic {
|
||||
static void Initialize(Isolate* isolate, D8Console* console,
|
||||
bool isOnMainThread = true);
|
||||
|
||||
static void PromiseRejectCallback(v8::PromiseRejectMessage reject_message);
|
||||
|
||||
private:
|
||||
static Global<Context> evaluation_context_;
|
||||
static base::OnceType quit_once_;
|
||||
@ -521,6 +534,7 @@ class Shell : public i::AllStatic {
|
||||
static base::LazyMutex cached_code_mutex_;
|
||||
static std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
|
||||
cached_code_map_;
|
||||
static std::atomic<int> unhandled_promise_rejections_;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
@ -2516,6 +2516,10 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions(
|
||||
stack_trace_for_uncaught_exceptions_options_ = options;
|
||||
}
|
||||
|
||||
bool Isolate::get_capture_stack_trace_for_uncaught_exceptions() const {
|
||||
return capture_stack_trace_for_uncaught_exceptions_;
|
||||
}
|
||||
|
||||
void Isolate::SetAbortOnUncaughtExceptionCallback(
|
||||
v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
|
||||
abort_on_uncaught_exception_callback_ = callback;
|
||||
|
@ -733,6 +733,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
|
||||
void SetCaptureStackTraceForUncaughtExceptions(
|
||||
bool capture, int frame_limit, StackTrace::StackTraceOptions options);
|
||||
bool get_capture_stack_trace_for_uncaught_exceptions() const;
|
||||
|
||||
void SetAbortOnUncaughtExceptionCallback(
|
||||
v8::Isolate::AbortOnUncaughtExceptionCallback callback);
|
||||
|
@ -1448,7 +1448,6 @@ DEFINE_BOOL(dump_counters, false, "Dump counters on exit")
|
||||
DEFINE_BOOL(dump_counters_nvp, false,
|
||||
"Dump counters as name-value pairs on exit")
|
||||
DEFINE_BOOL(use_external_strings, false, "Use external strings for source code")
|
||||
|
||||
DEFINE_STRING(map_counters, "", "Map counters to a file")
|
||||
DEFINE_BOOL(mock_arraybuffer_allocator, false,
|
||||
"Use a mock ArrayBuffer allocator for testing.")
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and a
|
||||
// Promise p3 created by Promise.all has no catch handler, and is rejected
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// Flags: --harmony-promise-any
|
||||
// Flags: --harmony-promise-any --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and a
|
||||
// Promise p3 created by Promise.any has no catch handler, and is rejected
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and a
|
||||
// Promise p3 created by Promise.race has no catch handler, and is rejected
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we listen to all exceptions and
|
||||
// there is a catch handler for the exception thrown in a Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// there is only a default reject handler for the to-be-rejected Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test exercises code paths for catching exceptions in the promise constructor
|
||||
// in conjunction with deoptimization.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// the Promise is rejected in the Promise constructor.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we listen to all exceptions and
|
||||
// there is a catch handler for the to-be-rejected Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// there is a catch handler for the to-be-rejected Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// there is no catch handler for the to-be-rejected Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// there is only a default reject handler for the to-be-rejected Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// an exception is thrown in the Promise constructor.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we listen to all exceptions and
|
||||
// there is no catch handler for the exception thrown in a Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// there is a catch handler for the exception thrown in a Promise.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// the Promise is rejected within a try-catch in the Promise constructor.
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Test debug events when we only listen to uncaught exceptions and
|
||||
// an exception is thrown in the Promise constructor, but caught in an
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
Debug = debug.Debug
|
||||
|
||||
let listenerComplete = false;
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
Debug = debug.Debug
|
||||
|
||||
var exception = null;
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
Debug = debug.Debug
|
||||
|
||||
let events = 0;
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
|
||||
|
||||
runPart(0);
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
|
||||
|
||||
runPart(1);
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
|
||||
|
||||
runPart(2);
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
|
||||
|
||||
runPart(3);
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
Debug = debug.Debug
|
||||
|
||||
var exception = null;
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
Debug = debug.Debug
|
||||
function overflow() {
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
|
||||
var Debug = debug.Debug;
|
||||
var expected = ["debugger;", "var x = y;", "debugger;", "var x = y;"];
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
var Debug = debug.Debug;
|
||||
var expected = ["debugger;",
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
var Debug = debug.Debug;
|
||||
var expected = ["debugger;", "var x = y;", "debugger;", "var x = y;"];
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --enable-inspector
|
||||
// Flags: --allow-natives-syntax --enable-inspector --ignore-unhandled-promises
|
||||
|
||||
const Debug = debug.Debug;
|
||||
Debug.setListener(() => {});
|
||||
|
@ -4,6 +4,6 @@
|
||||
//
|
||||
// MODULE
|
||||
//
|
||||
// Flags: --harmony-top-level-await
|
||||
// Flags: --harmony-top-level-await --ignore-unhandled-promises
|
||||
|
||||
import "modules-skip-1-top-level-await-fail.mjs"
|
||||
|
@ -4,6 +4,6 @@
|
||||
//
|
||||
// MODULE
|
||||
//
|
||||
// Flags: --harmony-top-level-await
|
||||
// Flags: --harmony-top-level-await --ignore-unhandled-promises
|
||||
|
||||
import "modules-skip-2-top-level-await-fail.mjs"
|
||||
|
9
test/message/mjsunit/fail/assert-in-promise-fail.js
Normal file
9
test/message/mjsunit/fail/assert-in-promise-fail.js
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
load('test/mjsunit/mjsunit.js');
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
assertEquals('foo', 'bar');
|
||||
});
|
12
test/message/mjsunit/fail/assert-in-promise-fail.out
Normal file
12
test/message/mjsunit/fail/assert-in-promise-fail.out
Normal file
@ -0,0 +1,12 @@
|
||||
undefined:0: Failure: expected <"foo"> found <"bar">
|
||||
|
||||
Stack: MjsUnitAssertionError
|
||||
at assertEquals test/mjsunit/mjsunit.js {NUMBER}:{NUMBER}
|
||||
at *%(basename)s 8:3
|
||||
|
||||
|
||||
MjsUnitAssertionError
|
||||
at assertEquals test/mjsunit/mjsunit.js {NUMBER}:{NUMBER}
|
||||
at *%(basename)s 8:3
|
||||
|
||||
1 pending unhandled Promise rejection(s) detected.
|
@ -43,8 +43,8 @@
|
||||
var value;
|
||||
function foo(x) { return new Promise((resolve, reject) => reject(x)); }
|
||||
%PrepareFunctionForOptimization(foo);
|
||||
foo(1);
|
||||
foo(1);
|
||||
foo(1).catch(() => { /* ignore */ });
|
||||
foo(1).catch(() => { /* ignore */ });
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(1).catch(v => value = v);
|
||||
setTimeout(_ => assertEquals(1, value));
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --ignore-unhandled-promises
|
||||
|
||||
// We have to patch mjsunit because normal assertion failures just throw
|
||||
// exceptions which are swallowed in a then clause.
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --always-opt
|
||||
// Flags: --always-opt --ignore-unhandled-promises
|
||||
|
||||
var __caught = 0;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --ignore-unhandled-promises
|
||||
|
||||
async function f() {
|
||||
var a = [...new Int8Array([, ...new Uint8Array(65536)])];
|
||||
|
@ -3,7 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
// A non-callable reject function throws eagerly
|
||||
|
||||
var log = [];
|
||||
var p = new Promise(function(resolve, reject) {
|
||||
log.push("resolve");
|
||||
resolve();
|
||||
|
@ -25,7 +25,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --ignore-unhandled-promises
|
||||
|
||||
// Make sure we don't rely on functions patchable by monkeys.
|
||||
var call = Function.prototype.call.call.bind(Function.prototype.call)
|
||||
|
@ -25,6 +25,8 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
// Check for correct interleaving of Promises and async/await
|
||||
(function () {
|
||||
const iterations = 10;
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --ignore-unhandled-promises
|
||||
|
||||
'use strict';
|
||||
|
||||
|
@ -9,21 +9,24 @@ var ran = false;
|
||||
var x = {
|
||||
get toString() { return undefined; }
|
||||
};
|
||||
import(x);
|
||||
import(x).then(assertUnreachable,
|
||||
(e) => assertInstanceof(e, TypeError));
|
||||
|
||||
var x = {
|
||||
toString() {
|
||||
throw new Error('42 is the answer');
|
||||
}
|
||||
};
|
||||
import(x);
|
||||
import(x).then(assertUnreachable,
|
||||
(e) => assertEquals(e.message, '42 is the answer'))
|
||||
|
||||
var x = {
|
||||
get toString() {
|
||||
throw new Error('42 is the answer');
|
||||
}
|
||||
};
|
||||
import(x);
|
||||
import(x).then(assertUnreachable,
|
||||
(e) => assertEquals(e.message, '42 is the answer'))
|
||||
|
||||
async function test1() {
|
||||
try {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-dynamic-import --harmony-top-level-await
|
||||
// Flags: --harmony-dynamic-import --harmony-top-level-await --ignore-unhandled-promises
|
||||
|
||||
let ran = false;
|
||||
let m = import('modules-skip-2.mjs');
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-dynamic-import --harmony-top-level-await
|
||||
// Flags: --harmony-dynamic-import --harmony-top-level-await --ignore-unhandled-promises
|
||||
|
||||
let ran = false;
|
||||
try {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-dynamic-import --harmony-top-level-await
|
||||
// Flags: --harmony-dynamic-import --harmony-top-level-await --ignore-unhandled-promises
|
||||
|
||||
let ran = false;
|
||||
try {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --harmony-promise-all-settled
|
||||
// Flags: --allow-natives-syntax --harmony-promise-all-settled --ignore-unhandled-promises
|
||||
|
||||
class MyError extends Error {}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --ignore-unhandled-promises
|
||||
|
||||
load('test/mjsunit/test-async.js');
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
import("./modules-skip-reset1.js").then(() => %AbortJS("must throw"));
|
||||
import("./modules-skip-reset3.js").then(() => %AbortJS("must throw"));
|
||||
import("./modules-skip-reset1.js").then(
|
||||
() => assertUnreachable("must throw"), () => {});
|
||||
import("./modules-skip-reset3.js").then(
|
||||
() => assertUnreachable("must throw"), () => {});
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --ignore-unhandled-promises
|
||||
|
||||
let count = 0;
|
||||
class MyPromise extends Promise {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// Flags: --harmony-dynamic-import
|
||||
// Flags: --harmony-dynamic-import --ignore-unhandled-promises
|
||||
|
||||
__v_1 = {
|
||||
};
|
||||
@ -10,7 +10,7 @@ function __f_8() {
|
||||
try {
|
||||
__f_8();
|
||||
} catch(e) {
|
||||
import(__v_1);
|
||||
import(__v_1).then();
|
||||
}
|
||||
}
|
||||
__f_8();
|
||||
|
@ -4,5 +4,9 @@
|
||||
|
||||
// Flags: --harmony-dynamic-import
|
||||
|
||||
eval(`import('modules-skip-2.js');`);
|
||||
eval(`eval(import('modules-skip-2.js'));`);
|
||||
eval(`import('modules-skip-2.js');`).then(
|
||||
assertUnreachable,
|
||||
() => { /* ignore */});
|
||||
eval(`eval(import('modules-skip-2.js'));`).then(
|
||||
assertUnreachable,
|
||||
() => { /* ignore */});
|
||||
|
@ -23,4 +23,6 @@ let myIterable = {
|
||||
}
|
||||
};
|
||||
|
||||
MyPromise.race(myIterable);
|
||||
MyPromise.race(myIterable).then(
|
||||
assertUnreachable,
|
||||
(e) => { assertEquals(e, "then throws")});
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --expose-async-hooks
|
||||
// Flags: --allow-natives-syntax --expose-async-hooks --ignore-unhandled-promises
|
||||
|
||||
async function* foo() {
|
||||
await 1;
|
||||
|
@ -3,4 +3,5 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
Promise.resolve = function() { return {}; };
|
||||
Promise.race([function() {}]);
|
||||
Promise.race([function() {}]).then(
|
||||
() => assertUnreachable(), () => { /* ignore */})
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --ignore-unhandled-promises
|
||||
|
||||
(async function test() {
|
||||
try {
|
||||
import('does_not_exist.mjs');
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --stack-size=50
|
||||
// Flags: --allow-natives-syntax --stack-size=50 --ignore-unhandled-promises
|
||||
|
||||
let i = 0;
|
||||
function f() {
|
||||
|
@ -14,4 +14,5 @@ binary.emit_bytes([kUnknownSectionCode, 2, 1, 0]);
|
||||
binary.emit_bytes([kUnknownSectionCode, 2, 1, 0]);
|
||||
binary.emit_bytes([ kExprEnd]);
|
||||
let buffer = binary.trunc_buffer();
|
||||
WebAssembly.compile(buffer);
|
||||
WebAssembly.compile(buffer).then(
|
||||
() => assertUnreachable(), () => {/* ignore */});
|
||||
|
@ -11,4 +11,4 @@ builder.addFunction(undefined, kSig_v_i) .addBodyWithEnd([
|
||||
// Intentionally add just a numeric opcode prefix without the index byte.
|
||||
|
||||
const b = builder.toBuffer();
|
||||
WebAssembly.compile(b);
|
||||
WebAssembly.compile(b).then(() => assertUnreachable(), () => { /* ignore */ })
|
||||
|
@ -9,7 +9,9 @@ Object.defineProperty(v11.__proto__, 0, {
|
||||
},
|
||||
set: function() {
|
||||
try {
|
||||
WebAssembly.instantiate();
|
||||
WebAssembly.instantiate().then(
|
||||
() => assertUnreachable(),
|
||||
() => { /* ignore */ });
|
||||
v11[0] = 0;
|
||||
} catch (e) {
|
||||
assertTrue(e instanceof RangeError);
|
||||
|
@ -16,4 +16,5 @@ for (let i = 0; i < 100; ++i) {
|
||||
chain = chain.then(() => WebAssembly.instantiate(buffer));
|
||||
}
|
||||
chain.then(({module, instance}) => instance.exports.fun1155())
|
||||
.then(res => print('Result of executing fun1155: ' + res));
|
||||
.then(res => print('Result of executing fun1155: ' + res))
|
||||
.catch(() => {/* ignore */});
|
||||
|
@ -8,4 +8,4 @@ var {proxy, revoke} = Proxy.revocable({}, {});
|
||||
revoke();
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addImport('m', 'q', kSig_v_v);
|
||||
WebAssembly.instantiate(builder.toModule(), proxy);
|
||||
WebAssembly.instantiate(builder.toModule(), proxy).catch(error => {});
|
||||
|
@ -218,6 +218,7 @@ class TestCase(testcase.D8TestCase):
|
||||
|
||||
def _get_suite_flags(self):
|
||||
return (
|
||||
["--ignore-unhandled-promises"] +
|
||||
(["--throws"] if "negative" in self.test_record else []) +
|
||||
(["--allow-natives-syntax"]
|
||||
if "detachArrayBuffer.js" in self.test_record.get("includes", [])
|
||||
|
@ -21,7 +21,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --harmony
|
||||
// Flags: --harmony --ignore-unhandled-promises
|
||||
'use strict';
|
||||
description('Test Promise.prototype.catch.');
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --harmony
|
||||
// Flags: --harmony --ignore-unhandled-promises
|
||||
'use strict';
|
||||
description('Test Promise.all');
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --harmony
|
||||
// Flags: --harmony --ignore-unhandled-promises
|
||||
'use strict';
|
||||
description('Test Promise.race');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user