Skip to content

Commit 1c83115

Browse files
author
Wolfram Kriesing
committedAug 9, 2009
+ better namespacing, added doh.assert.* and doh.util.*
+ properly separate errors and failures + added selftest for assertEqual on arrays
1 parent a1e1e58 commit 1c83115

File tree

6 files changed

+258
-249
lines changed

6 files changed

+258
-249
lines changed
 

‎assert.js

+135-149
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,149 @@
1-
//
2-
// Assertions and In-Test Utilities
3-
//
1+
doh.assert = {
2+
assertTrue:function(/*Object*/ condition, /*String?*/ hint){
3+
// summary:
4+
// is the passed item "truthy"?
5+
if(arguments.length < 1){
6+
throw new doh.assert.Failure("assertTrue failed because it was not passed at least 1 argument");
7+
}
8+
if(!eval(condition)){
9+
throw new doh.assert.Failure("assertTrue('" + condition + "') failed", hint);
10+
}
11+
},
412

5-
doh.t = doh.assertTrue = function(/*Object*/ condition, /*String?*/ hint){
6-
// summary:
7-
// is the passed item "truthy"?
8-
if(arguments.length < 1){
9-
throw new doh._AssertFailure("assertTrue failed because it was not passed at least 1 argument");
10-
}
11-
if(!eval(condition)){
12-
throw new doh._AssertFailure("assertTrue('" + condition + "') failed", hint);
13-
}
14-
}
13+
assertFalse:function(/*Object*/ condition, /*String?*/ hint){
14+
// summary:
15+
// is the passed item "falsey"?
16+
if(arguments.length < 1){
17+
throw new doh.assert.Failure("assertFalse failed because it was not passed at least 1 argument");
18+
}
19+
if(eval(condition)){
20+
throw new doh.assert.Failure("assertFalse('" + condition + "') failed", hint);
21+
}
22+
},
1523

16-
doh.f = doh.assertFalse = function(/*Object*/ condition, /*String?*/ hint){
17-
// summary:
18-
// is the passed item "falsey"?
19-
if(arguments.length < 1){
20-
throw new doh._AssertFailure("assertFalse failed because it was not passed at least 1 argument");
21-
}
22-
if(eval(condition)){
23-
throw new doh._AssertFailure("assertFalse('" + condition + "') failed", hint);
24-
}
25-
}
24+
assertError:function(/*Error object*/expectedError, /*Object*/scope, /*String*/functionName, /*Array*/args, /*String?*/ hint){
25+
// summary:
26+
// Test for a certain error to be thrown by the given function.
27+
// example:
28+
// t.assertError(dojox.data.QueryReadStore.InvalidAttributeError, store, "getValue", [item, "NOT THERE"]);
29+
// t.assertError(dojox.data.QueryReadStore.InvalidItemError, store, "getValue", ["not an item", "NOT THERE"]);
30+
try{
31+
scope[functionName].apply(scope, args);
32+
}catch (e){
33+
if(e instanceof expectedError){
34+
return true;
35+
}else{
36+
throw new doh.assert.Failure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut got\n\t\t"+e+"\n\n", hint);
37+
}
38+
}
39+
throw new doh.assert.Failure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut no error caught\n\n", hint);
40+
},
2641

27-
doh.e = doh.assertError = function(/*Error object*/expectedError, /*Object*/scope, /*String*/functionName, /*Array*/args, /*String?*/ hint){
28-
// summary:
29-
// Test for a certain error to be thrown by the given function.
30-
// example:
31-
// t.assertError(dojox.data.QueryReadStore.InvalidAttributeError, store, "getValue", [item, "NOT THERE"]);
32-
// t.assertError(dojox.data.QueryReadStore.InvalidItemError, store, "getValue", ["not an item", "NOT THERE"]);
33-
try{
34-
scope[functionName].apply(scope, args);
35-
}catch (e){
36-
if(e instanceof expectedError){
42+
assertEqual:function(/*Object*/ expected, /*Object*/ actual, /*String?*/ hint){
43+
// summary:
44+
// are the passed expected and actual objects/values deeply
45+
// equivalent?
46+
47+
// Compare undefined always with three equal signs, because undefined==null
48+
// is true, but undefined===null is false.
49+
if((expected === undefined)&&(actual === undefined)){
3750
return true;
38-
}else{
39-
throw new doh._AssertFailure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut got\n\t\t"+e+"\n\n", hint);
4051
}
41-
}
42-
throw new doh._AssertFailure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut no error caught\n\n", hint);
43-
}
44-
45-
46-
doh.is = doh.assertEqual = function(/*Object*/ expected, /*Object*/ actual, /*String?*/ hint){
47-
// summary:
48-
// are the passed expected and actual objects/values deeply
49-
// equivalent?
52+
if(arguments.length < 2){
53+
throw doh.assert.Failure("assertEqual failed because it was not passed 2 arguments");
54+
}
55+
if((expected === actual)||(expected == actual)){
56+
return true;
57+
}
58+
if( (doh.util.isArray(expected) && doh.util.isArray(actual))&&
59+
(doh.assert._arrayEq(expected, actual)) ){
60+
return true;
61+
}
62+
if( ((typeof expected == "object")&&((typeof actual == "object")))&&
63+
(doh.assert._objPropEq(expected, actual)) ){
64+
return true;
65+
}
66+
throw new doh.assert.Failure("assertEqual() failed:\n\texpected\n\t\t"+expected+"\n\tbut got\n\t\t"+actual+"\n\n", hint);
67+
},
5068

51-
// Compare undefined always with three equal signs, because undefined==null
52-
// is true, but undefined===null is false.
53-
if((expected === undefined)&&(actual === undefined)){
54-
return true;
55-
}
56-
if(arguments.length < 2){
57-
throw doh._AssertFailure("assertEqual failed because it was not passed 2 arguments");
58-
}
59-
if((expected === actual)||(expected == actual)){
60-
return true;
61-
}
62-
if( (this._isArray(expected) && this._isArray(actual))&&
63-
(this._arrayEq(expected, actual)) ){
64-
return true;
65-
}
66-
if( ((typeof expected == "object")&&((typeof actual == "object")))&&
67-
(this._objPropEq(expected, actual)) ){
69+
assertNotEqual:function(/*Object*/ notExpected, /*Object*/ actual, /*String?*/ hint){
70+
// summary:
71+
// are the passed notexpected and actual objects/values deeply
72+
// not equivalent?
73+
74+
// Compare undefined always with three equal signs, because undefined==null
75+
// is true, but undefined===null is false.
76+
if((notExpected === undefined)&&(actual === undefined)){
77+
throw new doh.assert.Failure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
78+
}
79+
if(arguments.length < 2){
80+
throw doh.assert.Failure("assertEqual failed because it was not passed 2 arguments");
81+
}
82+
if((notExpected === actual)||(notExpected == actual)){
83+
throw new doh.assert.Failure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
84+
}
85+
if( (doh.util.isArray(notExpected) && doh.util.isArray(actual))&&
86+
(doh.assert._arrayEq(notExpected, actual)) ){
87+
throw new doh.assert.Failure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
88+
}
89+
if( ((typeof notExpected == "object")&&((typeof actual == "object")))&&
90+
(doh.assert._objPropEq(notExpected, actual)) ){
91+
throw new doh.assert.Failure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
92+
}
6893
return true;
69-
}
70-
throw new doh._AssertFailure("assertEqual() failed:\n\texpected\n\t\t"+expected+"\n\tbut got\n\t\t"+actual+"\n\n", hint);
71-
}
72-
73-
doh.isNot = doh.assertNotEqual = function(/*Object*/ notExpected, /*Object*/ actual, /*String?*/ hint){
74-
// summary:
75-
// are the passed notexpected and actual objects/values deeply
76-
// not equivalent?
94+
},
7795

78-
// Compare undefined always with three equal signs, because undefined==null
79-
// is true, but undefined===null is false.
80-
if((notExpected === undefined)&&(actual === undefined)){
81-
throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
82-
}
83-
if(arguments.length < 2){
84-
throw doh._AssertFailure("assertEqual failed because it was not passed 2 arguments");
85-
}
86-
if((notExpected === actual)||(notExpected == actual)){
87-
throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
88-
}
89-
if( (this._isArray(notExpected) && this._isArray(actual))&&
90-
(this._arrayEq(notExpected, actual)) ){
91-
throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
92-
}
93-
if( ((typeof notExpected == "object")&&((typeof actual == "object")))&&
94-
(this._objPropEq(notExpected, actual)) ){
95-
throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
96-
}
97-
return true;
98-
}
99-
100-
doh._arrayEq = function(expected, actual){
101-
if(expected.length != actual.length){ return false; }
102-
// FIXME: we're not handling circular refs. Do we care?
103-
for(var x=0; x<expected.length; x++){
104-
if(!doh.assertEqual(expected[x], actual[x])){ return false; }
105-
}
106-
return true;
107-
}
108-
109-
doh._objPropEq = function(expected, actual){
110-
// Degenerate case: if they are both null, then their "properties" are equal.
111-
if(expected === null && actual === null){
112-
return true;
113-
}
114-
// If only one is null, they aren't equal.
115-
if(expected === null || actual === null){
116-
return false;
117-
}
118-
if(expected instanceof Date){
119-
return actual instanceof Date && expected.getTime()==actual.getTime();
120-
}
121-
var x;
122-
// Make sure ALL THE SAME properties are in both objects!
123-
for(x in actual){ // Lets check "actual" here, expected is checked below.
124-
if(expected[x] === undefined){
125-
return false;
96+
_arrayEq:function(expected, actual){
97+
if(expected.length != actual.length){ return false; }
98+
// FIXME: we're not handling circular refs. Do we care?
99+
for(var x=0; x<expected.length; x++){
100+
if(!doh.assert.assertEqual(expected[x], actual[x])){ return false; }
126101
}
127-
};
102+
return true;
103+
},
128104

129-
for(x in expected){
130-
if(!doh.assertEqual(expected[x], actual[x])){
105+
_objPropEq:function(expected, actual){
106+
// Degenerate case: if they are both null, then their "properties" are equal.
107+
if(expected === null && actual === null){
108+
return true;
109+
}
110+
// If only one is null, they aren't equal.
111+
if(expected === null || actual === null){
131112
return false;
132113
}
133-
}
134-
return true;
135-
}
136-
137-
doh._isArray = function(it){
138-
return (it && it instanceof Array || typeof it == "array" ||
139-
(
140-
!!doh.global["dojo"] &&
141-
doh.global["dojo"]["NodeList"] !== undefined &&
142-
it instanceof doh.global["dojo"]["NodeList"]
143-
)
144-
);
145-
}
146-
147-
148-
doh._AssertFailure = function(msg, hint){
149-
// idea for this as way of dis-ambiguating error types is from JUM.
150-
// The JUM is dead! Long live the JUM!
114+
if(expected instanceof Date){
115+
return actual instanceof Date && expected.getTime()==actual.getTime();
116+
}
117+
var x;
118+
// Make sure ALL THE SAME properties are in both objects!
119+
for(x in actual){ // Lets check "actual" here, expected is checked below.
120+
if(expected[x] === undefined){
121+
return false;
122+
}
123+
};
124+
125+
for(x in expected){
126+
if(!doh.assert.assertEqual(expected[x], actual[x])){
127+
return false;
128+
}
129+
}
130+
return true;
131+
},
151132

152-
if(!(this instanceof doh._AssertFailure)){
153-
return new doh._AssertFailure(msg);
154-
}
155-
if(hint){
156-
msg = (new String(msg||""))+" with hint: \n\t\t"+(new String(hint)+"\n");
133+
Failure:function(msg, hint){
134+
// idea for this as way of dis-ambiguating error types is from JUM.
135+
// The JUM is dead! Long live the JUM!
136+
137+
if(!(this instanceof doh.assert.Failure)){
138+
return new doh.assert.Failure(msg);
139+
}
140+
if(hint){
141+
msg = (new String(msg||""))+" with hint: \n\t\t"+(new String(hint)+"\n");
142+
}
143+
this.message = new String(msg||"");
144+
return this;
157145
}
158-
this.message = new String(msg||"");
159-
return this;
160-
}
161-
doh._AssertFailure.prototype = new Error();
162-
doh._AssertFailure.prototype.constructor = doh._AssertFailure;
163-
doh._AssertFailure.prototype.name = "doh._AssertFailure";
146+
};
147+
doh.assert.Failure.prototype = new Error();
148+
doh.assert.Failure.prototype.constructor = doh.assert.Failure;
149+
doh.assert.Failure.prototype.name = "doh.assert.Failure";

‎deferred.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ doh.Deferred = function(canceller){
88
this.silentlyCancelled = false;
99
};
1010

11-
doh.extend(doh.Deferred, {
11+
doh.util.extend(doh.Deferred, {
1212
getTestErrback: function(cb, scope){
1313
// summary: Replaces outer getTextCallback's in nested situations to avoid multiple callback(true)'s
1414
var _this = this;
1515
return function(){
1616
try{
17-
cb.apply(scope||doh.global||_this, arguments);
17+
cb.apply(scope||doh.util.global||_this, arguments);
1818
}catch(e){
1919
_this.errback(e);
2020
}
@@ -25,7 +25,7 @@ doh.extend(doh.Deferred, {
2525
var _this = this;
2626
return function(){
2727
try{
28-
cb.apply(scope||doh.global||_this, arguments);
28+
cb.apply(scope||doh.util.global||_this, arguments);
2929
}catch(e){
3030
_this.errback(e);
3131
return;
@@ -40,10 +40,10 @@ doh.extend(doh.Deferred, {
4040
if(typeof a[0] == "function"){
4141
return a[0];
4242
}else if(typeof a[0] == "string"){
43-
return doh.global[a[0]];
43+
return doh.util.global[a[0]];
4444
}
4545
}else if((a[0])&&(a[1])){
46-
return doh.hitch(a[0], a[1]);
46+
return doh.util.hitch(a[0], a[1]);
4747
}
4848
return null;
4949
},
@@ -124,23 +124,23 @@ doh.extend(doh.Deferred, {
124124
addBoth: function(cb, cbfn){
125125
var enclosed = this.getFunctionFromArgs(cb, cbfn);
126126
if(arguments.length > 2){
127-
enclosed = doh.hitch(null, enclosed, arguments, 2);
127+
enclosed = doh.util.hitch(null, enclosed, arguments, 2);
128128
}
129129
return this.addCallbacks(enclosed, enclosed);
130130
},
131131

132132
addCallback: function(cb, cbfn){
133133
var enclosed = this.getFunctionFromArgs(cb, cbfn);
134134
if(arguments.length > 2){
135-
enclosed = doh.hitch(null, enclosed, arguments, 2);
135+
enclosed = doh.util.hitch(null, enclosed, arguments, 2);
136136
}
137137
return this.addCallbacks(enclosed, null);
138138
},
139139

140140
addErrback: function(cb, cbfn){
141141
var enclosed = this.getFunctionFromArgs(cb, cbfn);
142142
if(arguments.length > 2){
143-
enclosed = doh.hitch(null, enclosed, arguments, 2);
143+
enclosed = doh.util.hitch(null, enclosed, arguments, 2);
144144
}
145145
return this.addCallbacks(null, enclosed);
146146
},

‎doh.js

+15-10
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ doh = {
5353
}
5454
for (var i=0, l=tests.length, t; i<l; i++){
5555
t = {};
56-
doh.mixin(t, tests[i]);
57-
//t.test = doh.hitch(this, "_makeDeferred", [t.test]);
56+
doh.util.mixin(t, tests[i]);
5857
group.tests.push(t);
5958
}
6059
this._numTests += tests.length;
@@ -91,13 +90,13 @@ doh = {
9190
return;
9291
}
9392
try{
94-
var ret = doh[method].apply(doh, args);
93+
var ret = doh.assert[method].apply(doh, args);
9594
d.callback(ret || true);
9695
}catch(e){
9796
d.errback(e);
9897
}
9998
};
100-
for (var methodName in doh){
99+
for (var methodName in doh.assert){
101100
if (methodName.indexOf("assert")===0){
102101
this[methodName] = (function(methodName){return function(){
103102
this._assertClosure(methodName, arguments);
@@ -118,7 +117,7 @@ doh = {
118117
if (c.groupIndex < this._groups.length-1){
119118
c.groupIndex++;
120119
c.group = this._groups[c.groupIndex];
121-
doh.mixin(c.group, this._additionalGroupProperties);
120+
doh.util.mixin(c.group, this._additionalGroupProperties);
122121
this.ui.groupStarted(c.group);
123122
c.testIndex = 0;
124123
} else {
@@ -165,9 +164,15 @@ doh = {
165164
deferred.test = t;
166165

167166
deferred.addErrback(function(err){
168-
g.numFailures++;
169-
doh._numFailures++;
170-
doh.ui.testFailed(g, t, err);
167+
if (err instanceof doh.assert.Failure){
168+
g.numFailures++;
169+
doh._numFailures++;
170+
doh.ui.testFailure(g, t, err);
171+
} else {
172+
g.numErrors++;
173+
doh._numErrors++;
174+
doh.ui.testError(g, t, err);
175+
}
171176
});
172177

173178
var retEnd = function(){
@@ -189,7 +194,7 @@ doh = {
189194
deferred.errback(new Error("test timeout in " + t.name.toString()));
190195
}, t.timeout || doh._defaultTimeout);
191196

192-
deferred.addBoth(doh.hitch(this, function(arg){
197+
deferred.addBoth(doh.util.hitch(this, function(arg){
193198
// Copy over the result if an asynchronous test has writte a result.
194199
// It must be available through the test object.
195200
// TODO maybe copy over all additional properties, compare to which props assertWrapperObject had upon creation and what new ones had been added, pass them all to t.*
@@ -199,7 +204,7 @@ doh = {
199204
clearTimeout(timer);
200205
retEnd();
201206
this._testInFlight = false;
202-
setTimeout(doh.hitch(this, "_runNextTest"), 1);
207+
setTimeout(doh.util.hitch(this, "_runNextTest"), 1);
203208
}));
204209
this._testInFlight = true;
205210

‎selftests.js

+15-4
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,22 @@ doh.register("Synchronously written tests.",
4949
t.assertEqual(1, "2");
5050
}
5151
},{
52-
name:"success: assertFalse numbers",
52+
name:"success: assertEqual numbers",
5353
test:function(t){
5454
t.assertEqual(1, "1");
5555
}
5656
},
57+
{
58+
name:"fail: assertEqual arrays",
59+
test:function(t){
60+
t.assertEqual([1,2], [2,1]);
61+
}
62+
},{
63+
name:"success: assertEqual arrays",
64+
test:function(t){
65+
t.assertEqual([2,3], [2,3]);
66+
}
67+
},
5768

5869

5970

@@ -65,12 +76,12 @@ doh.register("Synchronously written tests.",
6576

6677
{
6778
// A missing assert call.
68-
name:"fail: timeout, assert() missing",
79+
name:"error: timeout, assert() missing",
6980
test:function(t){
7081
}
7182
},{
7283
// This test will fail, because it has no implementation of the test method.
73-
name:"fail: test() missing"
84+
name:"error: test() missing"
7485
}
7586
]
7687
);
@@ -98,7 +109,7 @@ doh.register("Asynchronous tests.",
98109
}
99110
},
100111
{
101-
name:"fail: timeout",
112+
name:"error: timeout",
102113
timeout:100, // This timeout is shorter than the setTimeout below, this test should fail.
103114
test:function(t){
104115
setTimeout(function(){

‎ui.js

+18-8
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,46 @@
11
doh.ui = {
2+
// summary: This object contains the functions that are responsible for rendering out the results of each test.
3+
// description: Override this object or the funtion(s) you need to override.
24

35
started:function(){
46
// summary: This is called when run() was called the first time.
57
console.log(doh._numTests + " tests registered, in " + doh._groups.length + " groups");
68
console.log("--------");
79
},
8-
9-
testRegistered:function(group, test){
10-
},
1110

1211
groupStarted:function(group){
12+
// summary: Called before a group's tests get executed.
1313
console.log("Starting group '" + group.name + "', " + group.tests.length + " tests");
1414
},
1515

1616
groupFinished:function(group){
17+
// summary: After all group's tests ran.
1718
console.log(group.numTestsExecuted + " tests ran, " +
1819
group.numFailures + " failures, " +
1920
group.numErrors + " errors");
2021
console.log("--------");
2122
},
22-
23+
2324
testStarted:function(group, test){
25+
// summary: Before a test's test() method is executed.
2426
},
25-
26-
testFailed:function(group, test, error){
27-
console.log(test.name + " FAILED, " + error.message);
27+
28+
testFailure:function(group, test, error){
29+
// summary: After a test failed.
30+
console.log(test.name + " FAILURE, " + error.message);
2831
},
29-
32+
33+
testError:function(group, test, error){
34+
// summary: After a test failed.
35+
console.log(test.name + " ERROR, " + error.message);
36+
},
37+
3038
testFinished:function(group, test, success){
39+
// summary:
3140
},
3241

3342
report:function(){
43+
// summary:
3444
console.log(doh._numTestsExecuted + " tests ran, " +
3545
doh._numFailures + " failures, " +
3646
doh._numErrors + " errors");

‎util.js

+67-70
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,74 @@
1-
// package system gunk. e
2-
try{
3-
dojo.provide("doh.runner");
4-
}catch(e){
5-
if(!this["doh"]){
6-
doh = {};
7-
}
8-
}
9-
10-
//
11-
// Utility Functions and Classes
12-
//
13-
14-
doh.selfTest = false;
15-
16-
doh.global = this;
1+
doh.util = {
2+
hitch:function(/*Object*/thisObject, /*Function|String*/method /*, ...*/){
3+
var args = [];
4+
for(var x=2; x<arguments.length; x++){
5+
args.push(arguments[x]);
6+
}
7+
var fcn = ((typeof method == "string") ? thisObject[method] : method) || function(){};
8+
return function(){
9+
var ta = args.concat([]); // make a copy
10+
for(var x=0; x<arguments.length; x++){
11+
ta.push(arguments[x]);
12+
}
13+
return fcn.apply(thisObject, ta); // Function
14+
};
15+
},
1716

18-
doh.hitch = function(/*Object*/thisObject, /*Function|String*/method /*, ...*/){
19-
var args = [];
20-
for(var x=2; x<arguments.length; x++){
21-
args.push(arguments[x]);
22-
}
23-
var fcn = ((typeof method == "string") ? thisObject[method] : method) || function(){};
24-
return function(){
25-
var ta = args.concat([]); // make a copy
26-
for(var x=0; x<arguments.length; x++){
27-
ta.push(arguments[x]);
17+
_mixin:function(/*Object*/ obj, /*Object*/ props){
18+
// summary:
19+
// Adds all properties and methods of props to obj. This addition is
20+
// "prototype extension safe", so that instances of objects will not
21+
// pass along prototype defaults.
22+
var tobj = {};
23+
for(var x in props){
24+
// the "tobj" condition avoid copying properties in "props"
25+
// inherited from Object.prototype. For example, if obj has a custom
26+
// toString() method, don't overwrite it with the toString() method
27+
// that props inherited from Object.protoype
28+
if(tobj[x] === undefined || tobj[x] != props[x]){
29+
obj[x] = props[x];
30+
}
2831
}
29-
return fcn.apply(thisObject, ta); // Function
30-
};
31-
}
32+
// IE doesn't recognize custom toStrings in for..in
33+
if( this["document"]
34+
&& document.all
35+
&& (typeof props["toString"] == "function")
36+
&& (props["toString"] != obj["toString"])
37+
&& (props["toString"] != tobj["toString"])
38+
){
39+
obj.toString = props.toString;
40+
}
41+
return obj; // Object
42+
},
3243

33-
doh._mixin = function(/*Object*/ obj, /*Object*/ props){
34-
// summary:
35-
// Adds all properties and methods of props to obj. This addition is
36-
// "prototype extension safe", so that instances of objects will not
37-
// pass along prototype defaults.
38-
var tobj = {};
39-
for(var x in props){
40-
// the "tobj" condition avoid copying properties in "props"
41-
// inherited from Object.prototype. For example, if obj has a custom
42-
// toString() method, don't overwrite it with the toString() method
43-
// that props inherited from Object.protoype
44-
if(tobj[x] === undefined || tobj[x] != props[x]){
45-
obj[x] = props[x];
44+
mixin:function(/*Object*/obj, /*Object...*/props){
45+
// summary: Adds all properties and methods of props to obj.
46+
for(var i=1, l=arguments.length; i<l; i++){
47+
this._mixin(obj, arguments[i]);
4648
}
47-
}
48-
// IE doesn't recognize custom toStrings in for..in
49-
if( this["document"]
50-
&& document.all
51-
&& (typeof props["toString"] == "function")
52-
&& (props["toString"] != obj["toString"])
53-
&& (props["toString"] != tobj["toString"])
54-
){
55-
obj.toString = props.toString;
56-
}
57-
return obj; // Object
58-
}
49+
return obj; // Object
50+
},
5951

60-
doh.mixin = function(/*Object*/obj, /*Object...*/props){
61-
// summary: Adds all properties and methods of props to obj.
62-
for(var i=1, l=arguments.length; i<l; i++){
63-
doh._mixin(obj, arguments[i]);
52+
extend:function(/*Object*/ constructor, /*Object...*/ props){
53+
// summary:
54+
// Adds all properties and methods of props to constructor's
55+
// prototype, making them available to all instances created with
56+
// constructor.
57+
for(var i=1, l=arguments.length; i<l; i++){
58+
this._mixin(constructor.prototype, arguments[i]);
59+
}
60+
return constructor; // Object
61+
},
62+
63+
isArray:function(it){
64+
return (it && it instanceof Array || typeof it == "array" ||
65+
(
66+
!!doh.util.global["dojo"] &&
67+
doh.util.global["dojo"]["NodeList"] !== undefined &&
68+
it instanceof doh.util.global["dojo"]["NodeList"]
69+
)
70+
);
6471
}
65-
return obj; // Object
66-
}
72+
};
6773

68-
doh.extend = function(/*Object*/ constructor, /*Object...*/ props){
69-
// summary:
70-
// Adds all properties and methods of props to constructor's
71-
// prototype, making them available to all instances created with
72-
// constructor.
73-
for(var i=1, l=arguments.length; i<l; i++){
74-
doh._mixin(constructor.prototype, arguments[i]);
75-
}
76-
return constructor; // Object
77-
}
74+
doh.util.global = this;

0 commit comments

Comments
 (0)
Please sign in to comment.