blob: f41fafcfa710f250affca5854d63af0669082b90 [file] [log] [blame]
* Copyright 2015 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
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
namespace cobalt {
namespace script {
class Wrappable;
// ScriptObject is a wrapper around JavaScript objects that are being passed
// into Cobalt. These are objects that do not correspond to cobalt Wrappable
// objects. Specifically, this could include objects that implement the
// EventListener interface, and callback functions.
// As long as Cobalt maintains a handle to such an object, it should not be
// garbage collected. Web API implementations should hold on to a reference to
// a ScriptObject implementation by constructing a ScriptObject::Reference
// object.
// The Reference class takes as a constructor parameter a pointer to the
// Wrappable that is holding onto the ScriptObject. This ensures that the
// JavaScript engine's garbage collection is aware of the relationship between
// the ScriptObject and the Wrappable's corresponding JavaScript wrapper. This
// will ensure that the garbage collector can detect when these objects are
// detached from the rest of the graph of JavaScript objects, and can safely
// be garbage collected.
template <class T>
class ScriptObject {
// The Reference class maintains the ownership relationship between a
// Wrappable and the JavaScript object wrapped by a ScriptObject. This is an
// RAII object in that creation of a Reference instance will mark the
// underlying object as owned by this wrappable, and the underlying object
// will be unmarked when this Reference is destructed.
// The lifetime of a Reference must be at least as long as the Wrappable that
// has been passed into the constructor.
class Reference {
Reference(Wrappable* wrappable, const ScriptObject& script_object)
: owner_(wrappable), referenced_object_(script_object.MakeCopy()) {
const T& value() const { return *(referenced_object_->GetScriptObject()); }
// Return the referenced ScriptObject. This ScriptObject can
// be passed back into the JavaScript bindings layer where the referenced
// JavaScript object can be extracted from the ScriptObject.
const ScriptObject<T>& referenced_object() const {
return *(referenced_object_.get());
~Reference() { referenced_object_->DeregisterOwner(owner_); }
Wrappable* const owner_;
scoped_ptr<ScriptObject> referenced_object_;
// Return true iff |other| refers to the same underlying JavaScript object.
virtual bool EqualTo(const ScriptObject& other) const = 0;
// Returns true if this ScriptObject is referring to a NULL JavaScript object.
bool IsNull() const { return GetScriptObject() == NULL; }
virtual ~ScriptObject() {}
// Mark/unmark this Wrappable as owning a handle to the underlying JavaScript
// object.
virtual void RegisterOwner(Wrappable* owner) = 0;
virtual void DeregisterOwner(Wrappable* owner) = 0;
// Return a pointer to the object that wraps the underlying JavaScript object.
virtual const T* GetScriptObject() const = 0;
// Make a new ScriptObject instance that holds a handle to the same underlying
// JavaScript object. This should not be called for a ScriptObject that has a
// NULL script object (that is, GetScriptObject() returns NULL).
virtual scoped_ptr<ScriptObject> MakeCopy() const = 0;
friend class scoped_ptr<ScriptObject>;
} // namespace script
} // namespace cobalt