blob: cdcf27bc2174bc19e4f4998e67e1d7e2bc6f5fb9 [file] [log] [blame]
/*
* Copyright 2014 Google Inc. 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.
*/
#ifndef COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_BASE_H_
#define COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_BASE_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "cobalt/script/javascriptcore/jsc_global_object.h"
#include "cobalt/script/script_exception.h"
#include "cobalt/script/wrappable.h"
#include "third_party/WebKit/Source/JavaScriptCore/runtime/ErrorInstance.h"
#include "third_party/WebKit/Source/JavaScriptCore/runtime/JSDestructibleObject.h"
namespace cobalt {
namespace script {
namespace javascriptcore {
// All JavaScriptCore wrapper classes will inherit from this. This provides a
// common base class for all wrapper objects. It holds a reference-counted
// handle to a Wrappable object, which is the base class of all objects that
// can be referenced from JavaScript.
// The WrappableBase template class must be derived from script::Wrappable.
template <typename JSCBaseClass, typename WrappableBase>
class WrapperBase : public JSCBaseClass {
public:
const scoped_refptr<WrappableBase>& wrappable() { return wrappable_; }
scoped_refptr<WrappableBase> GetOpaqueRoot() {
if (!get_opaque_root_function_.is_null()) {
return get_opaque_root_function_.Run(wrappable_);
}
return NULL;
}
static scoped_refptr<WrappableBase>& GetWrappable(JSC::JSObject* js_object) {
ASSERT_GC_OBJECT_INHERITS(js_object, WrapperBase::s_classinfo());
WrapperBase* wrapper_base = JSC::jsCast<WrapperBase*>(js_object);
return wrapper_base->wrappable_;
}
protected:
typedef base::Callback<scoped_refptr<WrappableBase>(
const scoped_refptr<WrappableBase>&)> GetOpaqueRootFunction;
WrapperBase(JSC::JSGlobalData* global_data, JSC::Structure* structure,
ScriptObjectRegistry* script_object_registry,
const scoped_refptr<WrappableBase>& impl)
: JSCBaseClass(*global_data, structure),
wrappable_(impl),
script_object_registry_(script_object_registry) {}
void set_get_opaque_root_function(
const GetOpaqueRootFunction& get_opaque_root_function) {
DCHECK(get_opaque_root_function_.is_null());
get_opaque_root_function_ = get_opaque_root_function;
}
// static override. This function will be called during garbage collection
// to mark any garbage-collected objects that are referencable from this
// object.
static void visitChildren(JSC::JSCell* cell,
JSC::SlotVisitor& visitor) { // NOLINT(runtime/references)
JSCBaseClass::visitChildren(cell, visitor);
WrapperBase* this_object = JSC::jsCast<WrapperBase*>(cell);
ASSERT_GC_OBJECT_INHERITS(this_object, WrapperBase::s_classinfo());
// In general most wrappers won't have any such owned objects, but
// this shouldn't be too expensive.
this_object->script_object_registry_->VisitOwnedObjects(
this_object->wrappable_.get(), &visitor);
}
// static override. This will be called when this object is garbage collected.
static void destroy(JSC::JSCell* cell) {
// Note that the WrapperBase destructor is non-virtual.
// JSC's garbage-collected heap seems to not support classes with virtual
// functions, as suggested by the lack of a virtual destructor in JSCell,
// the base class for all GC objects, and the lack of any virtual functions
// in WebKit's bindings implementation.
// Garbage-collected classes with a non-trivial destructor and/or
// member variables that need to be destructed must override destroy() to
// ensure that the class is destructed properly.
static_cast<WrapperBase*>(cell)->~WrapperBase();
}
private:
scoped_refptr<WrappableBase> wrappable_;
ScriptObjectRegistry* script_object_registry_;
GetOpaqueRootFunction get_opaque_root_function_;
};
// Base for regular interfaces.
typedef WrapperBase<JSC::JSDestructibleObject, Wrappable> InterfaceBase;
// Base for exception interfaces.
typedef WrapperBase<JSC::ErrorInstance, ScriptException> ExceptionBase;
} // namespace javascriptcore
} // namespace script
} // namespace cobalt
#endif // COBALT_SCRIPT_JAVASCRIPTCORE_WRAPPER_BASE_H_