blob: 556956f921ea04745f23561d5080b0c581613bcc [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/streams/promise_handler.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
namespace {
void NoopFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&) {}
} // namespace
PromiseHandler::PromiseHandler(ScriptState* script_state)
: PromiseHandlerBase(script_state) {}
void PromiseHandler::CallRaw(const v8::FunctionCallbackInfo<v8::Value>& args) {
DCHECK_EQ(args.Length(), 1);
CallWithLocal(args[0]);
}
PromiseHandlerWithValue::PromiseHandlerWithValue(ScriptState* script_state)
: PromiseHandlerBase(script_state) {}
void PromiseHandlerWithValue::CallRaw(
const v8::FunctionCallbackInfo<v8::Value>& args) {
DCHECK_EQ(args.Length(), 1);
auto ret = CallWithLocal(args[0]);
args.GetReturnValue().Set(ret);
}
v8::Local<v8::Promise> StreamThenPromise(v8::Local<v8::Context> context,
v8::Local<v8::Promise> promise,
PromiseHandlerBase* on_fulfilled,
PromiseHandlerBase* on_rejected) {
v8::MaybeLocal<v8::Promise> result_maybe;
if (!on_fulfilled) {
DCHECK(on_rejected);
// v8::Promise::Catch is not safe as it calls promise.then() which can be
// tampered with by JavaScript. v8::Promise::Then won't accept an undefined
// value for on_fulfilled, it has to be a function. So we pass a no-op
// function, which gives us approximately the semantics we need.
// TODO(ricea): Add a safe variant of v8::Promise::Catch to V8.
v8::Local<v8::Function> noop;
if (!v8::Function::New(context, NoopFunctionCallback).ToLocal(&noop)) {
DVLOG(3) << "Assuming that the failure of v8::Function::New() is caused "
<< "by shutdown and ignoring it";
return v8::Promise::Resolver::New(context).ToLocalChecked()->GetPromise();
}
result_maybe =
promise->Then(context, noop, on_rejected->BindToV8Function());
} else if (on_rejected) {
result_maybe = promise->Then(context, on_fulfilled->BindToV8Function(),
on_rejected->BindToV8Function());
} else {
result_maybe = promise->Then(context, on_fulfilled->BindToV8Function());
}
v8::Local<v8::Promise> result;
if (!result_maybe.ToLocal(&result)) {
DVLOG(3)
<< "assuming that failure of promise->Then() is caused by shutdown and"
"ignoring it";
// Try to create a dummy promise so that the calling code can continue. If
// we can't create one, then we can't return to the calling context so we
// have to crash. This shouldn't happen except on OOM.
result = v8::Promise::Resolver::New(context).ToLocalChecked()->GetPromise();
}
return result;
}
} // namespace blink