Commit b0d863a2 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[blink] Add ModuleRecordEvaluationResult

The newly introduced will make the return type of
ModuleRecord::Evaluation explicit.

Currently an empty v8::Local return value corresponds to a successful
evaluation and any returned value is treated as an exception.

This is different when top-level await is enabled. In this case
ModuleRecord::Evaluation always returns a Promise on success. Thus
simply checking for an empty or non-empty v8::Local is no longer
sufficient and we need a dedicated flag to detect Exceptions.

Bug: 1022182, v8:9344
Change-Id: Ida7684bff79d68624548c99aee6e7b6f2e334afc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2105315
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750914}
parent a273c6b9
......@@ -3,7 +3,8 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "base/feature_list.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
......@@ -18,6 +19,49 @@
namespace blink {
// static
ModuleEvaluationResult ModuleEvaluationResult::Empty() {
DCHECK(!base::FeatureList::IsEnabled(features::kTopLevelAwait));
return ModuleEvaluationResult(true, {});
}
// static
ModuleEvaluationResult ModuleEvaluationResult::FromResult(
v8::Local<v8::Value> promise) {
DCHECK(base::FeatureList::IsEnabled(features::kTopLevelAwait) ||
promise.IsEmpty());
DCHECK(!base::FeatureList::IsEnabled(features::kTopLevelAwait) ||
promise->IsPromise());
return ModuleEvaluationResult(true, promise);
}
// static
ModuleEvaluationResult ModuleEvaluationResult::FromException(
v8::Local<v8::Value> exception) {
DCHECK(!exception.IsEmpty());
return ModuleEvaluationResult(false, exception);
}
ModuleEvaluationResult& ModuleEvaluationResult::Escape(
ScriptState::EscapableScope* scope) {
value_ = scope->Escape(value_);
return *this;
}
v8::Local<v8::Value> ModuleEvaluationResult::GetException() const {
DCHECK(IsException());
DCHECK(!value_.IsEmpty());
return value_;
}
ScriptPromise ModuleEvaluationResult::GetPromise(
ScriptState* script_state) const {
DCHECK(base::FeatureList::IsEnabled(features::kTopLevelAwait));
DCHECK(IsSuccess());
DCHECK(!value_.IsEmpty());
return ScriptPromise(script_state, value_);
}
ModuleRecordProduceCacheData::ModuleRecordProduceCacheData(
v8::Isolate* isolate,
SingleCachedMetadataHandler* cache_handler,
......
......@@ -23,6 +23,48 @@ class KURL;
class ScriptFetchOptions;
class ScriptState;
class ScriptValue;
class ScriptPromise;
// ModuleEvaluationResult encapsulates the result of a module evaluation.
// - Without top-level-await
// - succeed and not return a value, or
// (IsSuccess() == true), no return value is available.
// - throw any object.
// (IsException() == true && GetException()) returns the thrown exception
// - With top-level-await a module can either
// - return a promise, or
// (IsSuccess() == true && GetPromise()) returns a valid ScriptPromise())
// - throw any object.
// (IsException() == true && GetException()) returns the thrown exception
class CORE_EXPORT ModuleEvaluationResult final {
STACK_ALLOCATED();
public:
ModuleEvaluationResult() = delete;
static ModuleEvaluationResult Empty();
static ModuleEvaluationResult FromResult(v8::Local<v8::Value> promise);
static ModuleEvaluationResult FromException(v8::Local<v8::Value> exception);
ModuleEvaluationResult(const ModuleEvaluationResult& value) = default;
ModuleEvaluationResult& operator=(const ModuleEvaluationResult& value) =
default;
~ModuleEvaluationResult() = default;
ModuleEvaluationResult& Escape(ScriptState::EscapableScope* scope);
bool IsSuccess() const { return is_success_; }
bool IsException() const { return !is_success_; }
v8::Local<v8::Value> GetException() const;
ScriptPromise GetPromise(ScriptState* script_state) const;
private:
ModuleEvaluationResult(bool is_success, v8::Local<v8::Value> value)
: is_success_(is_success), value_(value) {}
bool is_success_;
v8::Local<v8::Value> value_;
};
// ModuleRecordProduceCacheData is a parameter object for
// ModuleRecord::ProduceCache().
......@@ -78,7 +120,7 @@ class CORE_EXPORT ModuleRecord final {
v8::Local<v8::Module> record,
const KURL& source_url);
// Returns exception, if any.
// Returns exception, if any
static ScriptValue Evaluate(ScriptState*,
v8::Local<v8::Module> record,
const KURL& source_url);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment