blob: 03e2f7695329c0fa30c4e402397214a81587277e [file] [log] [blame]
// Copyright 2020 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/testing/module_test_base.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
namespace blink {
v8::Local<v8::Module> ModuleTestBase::CompileModule(
v8::Isolate* isolate,
const char* source,
const KURL& url,
ExceptionState& exception_state) {
return CompileModule(isolate, String(source), url, exception_state);
}
v8::Local<v8::Module> ModuleTestBase::CompileModule(
v8::Isolate* isolate,
String source,
const KURL& url,
ExceptionState& exception_state) {
ModuleScriptCreationParams params(
/*source_url=*/url, /*base_url=*/url,
ScriptSourceLocationType::kExternalFile, ModuleType::kJavaScript,
ParkableString(source.Impl()), nullptr,
network::mojom::CredentialsMode::kOmit);
return ModuleRecord::Compile(isolate, params, ScriptFetchOptions(),
TextPosition::MinimumPosition(),
exception_state);
}
void ParametrizedModuleTestBase::SetUp(bool use_top_level_await) {
if (use_top_level_await) {
feature_list_.InitAndEnableFeature(features::kTopLevelAwait);
} else {
feature_list_.InitAndDisableFeature(features::kTopLevelAwait);
}
SetV8Flags(use_top_level_await);
}
void ParametrizedModuleTestBase::SetV8Flags(bool use_top_level_await) {
if (use_top_level_await) {
v8::V8::SetFlagsFromString("--harmony-top-level-await");
} else {
v8::V8::SetFlagsFromString("--no-harmony-top-level-await");
}
}
void ParametrizedModuleTest::SetUp() {
ParametrizedModuleTestBase::SetUp(UseTopLevelAwait());
}
class SaveResultFunction final : public ScriptFunction {
public:
explicit SaveResultFunction(ScriptState* script_state)
: ScriptFunction(script_state) {}
v8::Local<v8::Function> Bind() { return BindToV8Function(); }
v8::Local<v8::Value> GetResult() {
EXPECT_TRUE(result_);
EXPECT_FALSE(result_->IsEmpty());
return result_->V8Value();
}
private:
ScriptValue Call(ScriptValue value) override {
*result_ = value;
return value;
}
ScriptValue* result_ = nullptr;
};
class ExpectNotReached final : public ScriptFunction {
public:
static v8::Local<v8::Function> Create(ScriptState* script_state) {
auto* self = MakeGarbageCollected<ExpectNotReached>(script_state);
return self->BindToV8Function();
}
explicit ExpectNotReached(ScriptState* script_state)
: ScriptFunction(script_state) {}
private:
ScriptValue Call(ScriptValue value) override {
ADD_FAILURE() << "ExpectNotReached was reached";
return value;
}
};
v8::Local<v8::Value> ParametrizedModuleTestBase::GetResult(
ScriptState* script_state,
ScriptEvaluationResult result) {
CHECK_EQ(result.GetResultType(),
ScriptEvaluationResult::ResultType::kSuccess);
if (!base::FeatureList::IsEnabled(features::kTopLevelAwait)) {
return result.GetSuccessValue();
}
ScriptPromise script_promise = result.GetPromise(script_state);
v8::Local<v8::Promise> promise = script_promise.V8Promise();
if (promise->State() == v8::Promise::kFulfilled) {
return promise->Result();
}
auto* resolve_function =
MakeGarbageCollected<SaveResultFunction>(script_state);
result.GetPromise(script_state)
.Then(resolve_function->Bind(), ExpectNotReached::Create(script_state));
v8::MicrotasksScope::PerformCheckpoint(script_state->GetIsolate());
return resolve_function->GetResult();
}
v8::Local<v8::Value> ParametrizedModuleTestBase::GetException(
ScriptState* script_state,
ScriptEvaluationResult result) {
if (!base::FeatureList::IsEnabled(features::kTopLevelAwait)) {
CHECK_EQ(result.GetResultType(),
ScriptEvaluationResult::ResultType::kException);
return result.GetExceptionForModule();
}
CHECK_EQ(result.GetResultType(),
ScriptEvaluationResult::ResultType::kSuccess);
ScriptPromise script_promise = result.GetPromise(script_state);
v8::Local<v8::Promise> promise = script_promise.V8Promise();
if (promise->State() == v8::Promise::kRejected) {
return promise->Result();
}
auto* reject_function =
MakeGarbageCollected<SaveResultFunction>(script_state);
script_promise.Then(ExpectNotReached::Create(script_state),
reject_function->Bind());
v8::MicrotasksScope::PerformCheckpoint(script_state->GetIsolate());
return reject_function->GetResult();
}
} // namespace blink