blob: e123d1d04e5a94668aee793f832fd225ceed61f2 [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/script/v8c/wrapper_factory.h"
#include <memory>
#include <utility>
#include "base/lazy_instance.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "cobalt/script/v8c/v8c_wrapper_handle.h"
#include "cobalt/script/v8c/wrapper_private.h"
#include "v8/include/v8.h"
namespace cobalt {
namespace script {
namespace v8c {
void WrapperFactory::RegisterWrappableType(
base::TypeId wrappable_type, const CreateWrapperFunction& create_function,
const GetFunctionTemplate& get_function_template) {
auto insert_pair = wrappable_type_functions_.insert(std::make_pair(
wrappable_type,
WrappableTypeFunctions(create_function, get_function_template)));
DCHECK(insert_pair.second)
<< "RegisterWrappableType registered for type more than once.";
}
v8::Local<v8::Object> WrapperFactory::GetWrapper(
const scoped_refptr<Wrappable>& wrappable) {
v8::Local<v8::Object> wrapper;
v8::MaybeLocal<v8::Object> maybe_wrapper = V8cWrapperHandle::MaybeGetObject(
isolate_, GetCachedWrapper(wrappable.get()));
if (!maybe_wrapper.ToLocal(&wrapper)) {
std::unique_ptr<Wrappable::WeakWrapperHandle> object_handle =
CreateWrapper(wrappable);
SetCachedWrapper(wrappable.get(), std::move(object_handle));
wrapper = V8cWrapperHandle::MaybeGetObject(
isolate_, GetCachedWrapper(wrappable.get()))
.ToLocalChecked();
}
return wrapper;
}
WrapperPrivate* WrapperFactory::MaybeGetWrapperPrivate(Wrappable* wrappable) {
return V8cWrapperHandle::MaybeGetWrapperPrivate(isolate_,
GetCachedWrapper(wrappable));
}
std::unique_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
const scoped_refptr<Wrappable>& wrappable) const {
auto it = wrappable_type_functions_.find(wrappable->GetWrappableType());
if (it == wrappable_type_functions_.end()) {
NOTREACHED();
return std::unique_ptr<Wrappable::WeakWrapperHandle>();
}
v8::Local<v8::Object> new_object =
it->second.create_wrapper.Run(isolate_, wrappable);
WrapperPrivate* wrapper_private =
WrapperPrivate::GetFromWrapperObject(new_object);
DCHECK(wrapper_private);
return std::unique_ptr<Wrappable::WeakWrapperHandle>(
new V8cWrapperHandle(wrapper_private));
}
bool WrapperFactory::DoesObjectImplementInterface(v8::Local<v8::Object> object,
base::TypeId type_id) const {
// If the object doesn't have a wrapper private, then that means it is not a
// platform object, so the object doesn't implement the interface.
if (!WrapperPrivate::HasWrapperPrivate(object)) {
return false;
}
auto it = wrappable_type_functions_.find(type_id);
DCHECK(it != wrappable_type_functions_.end());
v8::Local<v8::FunctionTemplate> function_template =
it->second.get_function_template.Run(isolate_);
return function_template->HasInstance(object);
}
} // namespace v8c
} // namespace script
} // namespace cobalt