Commit a4f10d1e authored by brettw@chromium.org's avatar brettw@chromium.org

Fix some egregious bugs in Var.

Self-assignment was broken and would lose the reference. I uncovered this when
running a test. It outputted a warning to the console, but we never looked at
it. I made a more explicit test.

This also fixes output exceptions. The OutException helper class detected
whether the existing object had an exception or not incorrectly. This was
exposed when var assignment was fixed.

TEST=included
BUG=none
Review URL: http://codereview.chromium.org/7511026

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95690 0039d316-1c4b-4281-b951-d872f2087c98
parent 4ccc9dd4
...@@ -86,7 +86,7 @@ class VarPrivate : public Var { ...@@ -86,7 +86,7 @@ class VarPrivate : public Var {
public: public:
OutException(Var* v) OutException(Var* v)
: output_(v), : output_(v),
originally_had_exception_(v && v->is_null()) { originally_had_exception_(v && !v->is_undefined()) {
if (output_) { if (output_) {
temp_ = output_->pp_var(); temp_ = output_->pp_var();
} else { } else {
......
...@@ -117,20 +117,27 @@ Var::~Var() { ...@@ -117,20 +117,27 @@ Var::~Var() {
} }
Var& Var::operator=(const Var& other) { Var& Var::operator=(const Var& other) {
if (needs_release_ && has_interface<PPB_Var>()) // Early return for self-assignment. Note however, that two distinct vars
get_interface<PPB_Var>()->Release(var_); // can refer to the same object, so we still need to be careful about the
var_ = other.var_; // refcounting below.
if (NeedsRefcounting(var_)) { if (this == &other)
if (has_interface<PPB_Var>()) { return *this;
needs_release_ = true;
get_interface<PPB_Var>()->AddRef(var_); // Be careful to keep the ref alive for cases where we're assigning an
} else { // object to itself by addrefing the new one before releasing the old one.
var_.type = PP_VARTYPE_NULL; bool old_needs_release = needs_release_;
needs_release_ = false; if (NeedsRefcounting(other.var_)) {
} // Assume we already has_interface<PPB_Var> for refcounted vars or else we
// couldn't have created them in the first place.
needs_release_ = true;
get_interface<PPB_Var>()->AddRef(other.var_);
} else { } else {
needs_release_ = false; needs_release_ = false;
} }
if (old_needs_release)
get_interface<PPB_Var>()->Release(var_);
var_ = other.var_;
return *this; return *this;
} }
......
...@@ -257,7 +257,7 @@ class Var { ...@@ -257,7 +257,7 @@ class Var {
/// A constructor. /// A constructor.
OutException(Var* v) OutException(Var* v)
: output_(v), : output_(v),
originally_had_exception_(v && v->is_null()) { originally_had_exception_(v && !v->is_undefined()) {
if (output_) { if (output_) {
temp_ = output_->var_; temp_ = output_->var_;
} else { } else {
......
...@@ -64,6 +64,13 @@ std::string TestVar::TestBasicString() { ...@@ -64,6 +64,13 @@ std::string TestVar::TestBasicString() {
ASSERT_EQ(NULL, result); ASSERT_EQ(NULL, result);
} }
// Make sure we can assign a C++ object to itself and it stays alive.
{
pp::Var a("test");
a = a;
ASSERT_TRUE(a.AsString() == "test");
}
// Make sure nothing leaked. // Make sure nothing leaked.
ASSERT_TRUE(testing_interface_->GetLiveObjectsForInstance( ASSERT_TRUE(testing_interface_->GetLiveObjectsForInstance(
instance_->pp_instance()) == before_object); instance_->pp_instance()) == before_object);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment