summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorgarykac <garykac@chromium.org>2015-03-31 11:31:39 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-31 18:32:26 +0000
commit2683fe7e0cdc04c01afb870817116b8d62a355ca (patch)
tree9d00e4bab3a936803b7604b7bdafb4037c767ad7 /remoting
parent3074045136e6a83a08de513e847c68ccfb71e4dd (diff)
downloadchromium_src-2683fe7e0cdc04c01afb870817116b8d62a355ca.zip
chromium_src-2683fe7e0cdc04c01afb870817116b8d62a355ca.tar.gz
chromium_src-2683fe7e0cdc04c01afb870817116b8d62a355ca.tar.bz2
[Chromoting] Fix base.inherits so parent methods can be used in parent ctor.
The current code calls the parent constructor before merging in the parent prototypes. This means that when a child is created, the parent methods aren't available in the parent ctor the first time that object is created. Also, the base.inherits tests set up the Parent, Child and GrandChild classes once before any tests are run. This means that the objects are global and that the prototype chain for the parent is "fixed" the first time a child object of that type is created. To fix this, the Class setup is now done in a setupTestClasses function. BUG=465878 Review URL: https://codereview.chromium.org/1035363002 Cr-Commit-Position: refs/heads/master@{#323076}
Diffstat (limited to 'remoting')
-rw-r--r--remoting/webapp/base/js/base.js12
-rw-r--r--remoting/webapp/base/js/base_inherits_unittest.js81
-rw-r--r--remoting/webapp/js_proto/qunit_proto.js2
3 files changed, 58 insertions, 37 deletions
diff --git a/remoting/webapp/base/js/base.js b/remoting/webapp/base/js/base.js
index 417979b..9257a86 100644
--- a/remoting/webapp/base/js/base.js
+++ b/remoting/webapp/base/js/base.js
@@ -165,13 +165,17 @@ base.extend = function(dest, src) {
*
* @param {*} childObject
* @param {*} parentCtor
- * @param {...} parentCtorAargs
+ * @param {...} parentCtorArgs
* @suppress {checkTypes|reportUnknownTypes}
*/
-base.inherits = function(childObject, parentCtor, parentCtorAargs) {
+base.inherits = function(childObject, parentCtor, parentCtorArgs) {
base.debug.assert(parentCtor && parentCtor.prototype,
'Invalid parent constructor.');
var parentArgs = Array.prototype.slice.call(arguments, 2);
+
+ // Mix in the parent's prototypes so that they're available during the parent
+ // ctor.
+ base.mix(childObject, parentCtor.prototype);
parentCtor.apply(childObject, parentArgs);
// Note that __proto__ is deprecated.
@@ -179,10 +183,6 @@ base.inherits = function(childObject, parentCtor, parentCtorAargs) {
// Global_Objects/Object/proto.
// It is used so that childObject instanceof parentCtor will
// return true.
- //
- // Alternatively, this could be implemented using mixins, e.g.
- // base.mix(childObject, parentCtor.prototype);
- // if we don't care about the correctness of instanceof in the future.
childObject.__proto__.__proto__ = parentCtor.prototype;
base.debug.assert(childObject instanceof parentCtor);
};
diff --git a/remoting/webapp/base/js/base_inherits_unittest.js b/remoting/webapp/base/js/base_inherits_unittest.js
index baa5b6f..32df103 100644
--- a/remoting/webapp/base/js/base_inherits_unittest.js
+++ b/remoting/webapp/base/js/base_inherits_unittest.js
@@ -2,18 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-(function() {
-
'use strict';
-QUnit.module('base.inherits');
+QUnit.module('base.inherits', {
+ beforeEach: function() {
+ base_inherits.setupTestClasses();
+ }
+});
+
+var base_inherits = {};
+
+base_inherits.setupTestClasses = function() {
/**
* @constructor
- * @extends {ChildClass}
+ * @extends {base_inherits.ChildClass}
*/
-var GrandChildClass = function() {
- base.inherits(this, ChildClass);
+base_inherits.GrandChildClass = function() {
+ base.inherits(this, base_inherits.ChildClass);
this.name = 'grandChild';
}
@@ -21,16 +27,16 @@ var GrandChildClass = function() {
* @param {string} arg
* @return {string}
*/
-GrandChildClass.prototype.overrideMethod = function(arg) {
+base_inherits.GrandChildClass.prototype.overrideMethod = function(arg) {
return 'overrideMethod - grandChild - ' + arg;
}
/**
* @constructor
- * @extends {ParentClass}
+ * @extends {base_inherits.ParentClass}
*/
-var ChildClass = function() {
- base.inherits(this, ParentClass, 'parentArg');
+base_inherits.ChildClass = function() {
+ base.inherits(this, base_inherits.ParentClass, 'parentArg');
this.name = 'child';
this.childOnly = 'childOnly';
}
@@ -39,12 +45,12 @@ var ChildClass = function() {
* @param {string} arg
* @return {string}
*/
-ChildClass.prototype.overrideMethod = function(arg) {
+base_inherits.ChildClass.prototype.overrideMethod = function(arg) {
return 'overrideMethod - child - ' + arg;
}
/** @return {string} */
-ChildClass.prototype.childMethod = function() {
+base_inherits.ChildClass.prototype.childMethod = function() {
return 'childMethod';
}
@@ -52,17 +58,21 @@ ChildClass.prototype.childMethod = function() {
* @param {string} arg
* @constructor
*/
-var ParentClass = function(arg) {
+base_inherits.ParentClass = function(arg) {
/** @type {string} */
this.name = 'parent';
/** @type {string} */
this.parentOnly = 'parentOnly';
/** @type {string} */
this.parentConstructorArg = arg;
+
+ // Record the parent method so that we can ensure that it is available in
+ // the parent constructor regardless of what type of object |this| points to.
+ this.parentMethodDuringCtor = this.parentMethod;
}
/** @return {string} */
-ParentClass.prototype.parentMethod = function() {
+base_inherits.ParentClass.prototype.parentMethod = function() {
return 'parentMethod';
}
@@ -70,34 +80,36 @@ ParentClass.prototype.parentMethod = function() {
* @param {string} arg
* @return {string}
*/
-ParentClass.prototype.overrideMethod = function(arg) {
+base_inherits.ParentClass.prototype.overrideMethod = function(arg) {
return 'overrideMethod - parent - ' + arg;
}
+};
+
QUnit.test('should invoke parent constructor with the correct arguments',
function(assert) {
- var child = new ChildClass();
+ var child = new base_inherits.ChildClass();
assert.equal(child.parentConstructorArg, 'parentArg');
});
QUnit.test('should preserve parent property and method', function(assert) {
- var child = new ChildClass();
+ var child = new base_inherits.ChildClass();
assert.equal(child.parentOnly, 'parentOnly');
assert.equal(child.parentMethod(), 'parentMethod');
});
QUnit.test('should preserve instanceof', function(assert) {
- var child = new ChildClass();
- var grandChild = new GrandChildClass();
- assert.ok(child instanceof ParentClass);
- assert.ok(child instanceof ChildClass);
- assert.ok(grandChild instanceof ParentClass);
- assert.ok(grandChild instanceof ChildClass);
- assert.ok(grandChild instanceof GrandChildClass);
+ var child = new base_inherits.ChildClass();
+ var grandChild = new base_inherits.GrandChildClass();
+ assert.ok(child instanceof base_inherits.ParentClass);
+ assert.ok(child instanceof base_inherits.ChildClass);
+ assert.ok(grandChild instanceof base_inherits.ParentClass);
+ assert.ok(grandChild instanceof base_inherits.ChildClass);
+ assert.ok(grandChild instanceof base_inherits.GrandChildClass);
});
QUnit.test('should override parent property and method', function(assert) {
- var child = new ChildClass();
+ var child = new base_inherits.ChildClass();
assert.equal(child.name, 'child');
assert.equal(child.overrideMethod('123'), 'overrideMethod - child - 123');
assert.equal(child.childOnly, 'childOnly');
@@ -105,7 +117,7 @@ QUnit.test('should override parent property and method', function(assert) {
});
QUnit.test('should work on an inheritance chain', function(assert) {
- var grandChild = new GrandChildClass();
+ var grandChild = new base_inherits.GrandChildClass();
assert.equal(grandChild.name, 'grandChild');
assert.equal(grandChild.overrideMethod('246'),
'overrideMethod - grandChild - 246');
@@ -116,16 +128,25 @@ QUnit.test('should work on an inheritance chain', function(assert) {
});
QUnit.test('should be able to access parent class methods', function(assert) {
- var grandChild = new GrandChildClass();
+ var grandChild = new base_inherits.GrandChildClass();
assert.equal(grandChild.overrideMethod('789'),
'overrideMethod - grandChild - 789');
- var childMethod = ChildClass.prototype.overrideMethod.call(grandChild, '81');
+ var childMethod = base_inherits.ChildClass.prototype.overrideMethod.
+ call(grandChild, '81');
assert.equal(childMethod, 'overrideMethod - child - 81');
- var parentMethod = ParentClass.prototype.overrideMethod.call(grandChild, '4');
+ var parentMethod = base_inherits.ParentClass.prototype.overrideMethod.
+ call(grandChild, '4');
assert.equal(parentMethod, 'overrideMethod - parent - 4');
});
-})();
+QUnit.test('parent ctor should have access to parent methods',
+ function(assert) {
+ var child = new base_inherits.ChildClass();
+ assert.ok(child.parentMethodDuringCtor);
+
+ var parent = new base_inherits.ParentClass('blah');
+ assert.ok(parent.parentMethodDuringCtor);
+});
diff --git a/remoting/webapp/js_proto/qunit_proto.js b/remoting/webapp/js_proto/qunit_proto.js
index 33b30f7..274282b 100644
--- a/remoting/webapp/js_proto/qunit_proto.js
+++ b/remoting/webapp/js_proto/qunit_proto.js
@@ -43,7 +43,7 @@ QUnit.Assert.prototype.async = function() {};
QUnit.Assert.prototype.notEqual = function(a, b, opt_desc) {};
/**
- * @param {boolean} cond
+ * @param {*} cond Passes if cond is truthy.
* @param {string=} desc
* @return {boolean}
*/