Add functionality to StreamThenPromise()
ReadableStreamNative needs some extra functionality from
StreamThenPromise():
* Support the single argument form of Then(). The |on_rejected| argument
is now optional.
* Behave as Catch() by setting the |on_fulfilled| argument to nullptr.
* Return the return value from Then() instead of void. Only a Promise
resolving to undefined can be created due to the StreamScriptFunction
API having no provision for a return value, but this is sufficient to
implement ReadableStream.
BUG=902633
Change-Id: I44f0ba0109568c8fd09882e2f1f05ba50816364a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1523214
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#641440}
diff --git a/third_party/blink/renderer/core/streams/stream_script_function.cc b/third_party/blink/renderer/core/streams/stream_script_function.cc
index 2bd72878..8204397 100644
--- a/third_party/blink/renderer/core/streams/stream_script_function.cc
+++ b/third_party/blink/renderer/core/streams/stream_script_function.cc
@@ -17,19 +17,32 @@
CallWithLocal(args[0]);
}
-void StreamThenPromise(v8::Local<v8::Context> context,
- v8::Local<v8::Promise> promise,
- StreamScriptFunction* on_fulfilled,
- StreamScriptFunction* on_rejected) {
- DCHECK(on_fulfilled);
- DCHECK(on_rejected);
- auto result = promise->Then(context, on_fulfilled->BindToV8Function(),
- on_rejected->BindToV8Function());
- if (result.IsEmpty()) {
+v8::Local<v8::Promise> StreamThenPromise(v8::Local<v8::Context> context,
+ v8::Local<v8::Promise> promise,
+ StreamScriptFunction* on_fulfilled,
+ StreamScriptFunction* on_rejected) {
+ v8::MaybeLocal<v8::Promise> result_maybe;
+ if (!on_fulfilled) {
+ DCHECK(on_rejected);
+ result_maybe = promise->Catch(context, 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
diff --git a/third_party/blink/renderer/core/streams/stream_script_function.h b/third_party/blink/renderer/core/streams/stream_script_function.h
index 9ed75c0..599e26f 100644
--- a/third_party/blink/renderer/core/streams/stream_script_function.h
+++ b/third_party/blink/renderer/core/streams/stream_script_function.h
@@ -29,11 +29,13 @@
// A convenient wrapper for promise->Then() for when both paths are
// StreamScriptFunctions. It avoids having to call BindToV8Function()
-// explicitly. Both |on_fulfilled| and |on_rejected| must be non-null.
-void StreamThenPromise(v8::Local<v8::Context>,
- v8::Local<v8::Promise>,
- StreamScriptFunction* on_fulfilled,
- StreamScriptFunction* on_rejected);
+// explicitly. If |on_rejected| is null then behaves like single-argument
+// Then(). If |on_fulfilled| is null then it calls Catch().
+v8::Local<v8::Promise> StreamThenPromise(
+ v8::Local<v8::Context>,
+ v8::Local<v8::Promise>,
+ StreamScriptFunction* on_fulfilled,
+ StreamScriptFunction* on_rejected = nullptr);
} // namespace blink