blob: 522dee1cfdaff87308146633a09dcf14f06073ea [file] [log] [blame]
// Copyright 2017 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/modules/animationworklet/animator.h"
#include "base/stl_util.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_animate_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_state_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_union_workletanimationeffect_workletgroupeffect.h"
#include "third_party/blink/renderer/bindings/modules/v8/worklet_animation_effect_or_worklet_group_effect.h"
#include "third_party/blink/renderer/modules/animationworklet/animator_definition.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "v8/include/v8.h"
namespace blink {
Animator::Animator(v8::Isolate* isolate,
AnimatorDefinition* definition,
v8::Local<v8::Value> instance,
const String& name,
WorkletAnimationOptions options,
const Vector<base::Optional<base::TimeDelta>>& local_times,
const Vector<Timing>& timings)
: definition_(definition),
instance_(isolate, instance),
name_(name),
options_(options),
group_effect_(
MakeGarbageCollected<WorkletGroupEffect>(local_times, timings)) {
DCHECK_GE(local_times.size(), 1u);
}
Animator::~Animator() = default;
void Animator::Trace(Visitor* visitor) const {
visitor->Trace(definition_);
visitor->Trace(instance_);
visitor->Trace(group_effect_);
}
bool Animator::Animate(
v8::Isolate* isolate,
double current_time,
AnimationWorkletDispatcherOutput::AnimationState* output) {
DCHECK(!std::isnan(current_time));
v8::Local<v8::Value> instance = instance_.NewLocal(isolate);
if (IsUndefinedOrNull(instance))
return false;
#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
V8UnionWorkletAnimationEffectOrWorkletGroupEffect* effect = nullptr;
if (group_effect_->getChildren().size() == 1) {
effect =
MakeGarbageCollected<V8UnionWorkletAnimationEffectOrWorkletGroupEffect>(
group_effect_->getChildren()[0]);
} else {
effect =
MakeGarbageCollected<V8UnionWorkletAnimationEffectOrWorkletGroupEffect>(
group_effect_);
}
#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
WorkletAnimationEffectOrWorkletGroupEffect effect;
if (group_effect_->getChildren().size() == 1) {
effect.SetWorkletAnimationEffect(group_effect_->getChildren()[0]);
} else {
effect.SetWorkletGroupEffect(group_effect_);
}
#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
if (definition_->AnimateFunction()
->Invoke(instance, current_time, effect)
.IsNothing()) {
return false;
}
GetLocalTimes(output->local_times);
return true;
}
Vector<Timing> Animator::GetTimings() const {
Vector<Timing> timings;
timings.ReserveInitialCapacity(group_effect_->getChildren().size());
for (const auto& effect : group_effect_->getChildren()) {
timings.push_back(effect->SpecifiedTiming());
}
return timings;
}
bool Animator::IsStateful() const {
return definition_->IsStateful();
}
v8::Local<v8::Value> Animator::State(v8::Isolate* isolate,
ExceptionState& exception_state) {
if (!IsStateful())
return v8::Undefined(isolate);
v8::Local<v8::Value> instance = instance_.NewLocal(isolate);
DCHECK(!IsUndefinedOrNull(instance));
v8::TryCatch try_catch(isolate);
v8::Maybe<ScriptValue> state = definition_->StateFunction()->Invoke(instance);
if (try_catch.HasCaught()) {
exception_state.RethrowV8Exception(try_catch.Exception());
return v8::Undefined(isolate);
}
return state.ToChecked().V8Value();
}
} // namespace blink