Skip to content

Commit f155fe1

Browse files
committed
[cleanup] update assert and add deepEqual circular test
1 parent 5fa8c3f commit f155fe1

File tree

2 files changed

+55
-54
lines changed

2 files changed

+55
-54
lines changed

builtin/assert.js

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
11
// UTILITY
22
var util = require('util');
3-
var Buffer = require("buffer").Buffer;
3+
var shims = require('./_shims.js');
44
var pSlice = Array.prototype.slice;
55

6-
function objectKeys(object) {
7-
if (Object.keys) return Object.keys(object);
8-
var result = [];
9-
for (var name in object) {
10-
if (Object.prototype.hasOwnProperty.call(object, name)) {
11-
result.push(name);
12-
}
13-
}
14-
return result;
15-
}
16-
176
// 1. The assert module provides functions that throw
187
// AssertionError's when particular conditions are not met. The
198
// assert module must conform to the following interface.
@@ -27,53 +16,41 @@ var assert = module.exports = ok;
2716

2817
assert.AssertionError = function AssertionError(options) {
2918
this.name = 'AssertionError';
30-
this.message = options.message;
3119
this.actual = options.actual;
3220
this.expected = options.expected;
3321
this.operator = options.operator;
34-
var stackStartFunction = options.stackStartFunction || fail;
35-
36-
if (Error.captureStackTrace) {
37-
Error.captureStackTrace(this, stackStartFunction);
38-
}
22+
this.message = options.message || getMessage(this);
3923
};
4024

4125
// assert.AssertionError instanceof Error
4226
util.inherits(assert.AssertionError, Error);
4327

4428
function replacer(key, value) {
45-
if (value === undefined) {
29+
if (util.isUndefined(value)) {
4630
return '' + value;
4731
}
48-
if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
32+
if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
4933
return value.toString();
5034
}
51-
if (typeof value === 'function' || value instanceof RegExp) {
35+
if (util.isFunction(value) || util.isRegExp(value)) {
5236
return value.toString();
5337
}
5438
return value;
5539
}
5640

5741
function truncate(s, n) {
58-
if (typeof s == 'string') {
42+
if (util.isString(s)) {
5943
return s.length < n ? s : s.slice(0, n);
6044
} else {
6145
return s;
6246
}
6347
}
6448

65-
assert.AssertionError.prototype.toString = function() {
66-
if (this.message) {
67-
return [this.name + ':', this.message].join(' ');
68-
} else {
69-
return [
70-
this.name + ':',
71-
truncate(JSON.stringify(this.actual, replacer), 128),
72-
this.operator,
73-
truncate(JSON.stringify(this.expected, replacer), 128)
74-
].join(' ');
75-
}
76-
};
49+
function getMessage(self) {
50+
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
51+
self.operator + ' ' +
52+
truncate(JSON.stringify(self.expected, replacer), 128);
53+
}
7754

7855
// At present only the three keys mentioned above are used and
7956
// understood by the spec. Implementations or sub modules can pass
@@ -102,12 +79,12 @@ assert.fail = fail;
10279
// 4. Pure assertion tests whether a value is truthy, as determined
10380
// by !!guard.
10481
// assert.ok(guard, message_opt);
105-
// This statement is equivalent to assert.equal(true, guard,
82+
// This statement is equivalent to assert.equal(true, !!guard,
10683
// message_opt);. To test strictly for the value true, use
10784
// assert.strictEqual(true, guard, message_opt);.
10885

10986
function ok(value, message) {
110-
if (!!!value) fail(value, true, message, '==', assert.ok);
87+
if (!value) fail(value, true, message, '==', assert.ok);
11188
}
11289
assert.ok = ok;
11390

@@ -142,7 +119,7 @@ function _deepEqual(actual, expected) {
142119
if (actual === expected) {
143120
return true;
144121

145-
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
122+
} else if (util.isBuffer(actual) && util.isBuffer(expected)) {
146123
if (actual.length != expected.length) return false;
147124

148125
for (var i = 0; i < actual.length; i++) {
@@ -153,15 +130,25 @@ function _deepEqual(actual, expected) {
153130

154131
// 7.2. If the expected value is a Date object, the actual value is
155132
// equivalent if it is also a Date object that refers to the same time.
156-
} else if (actual instanceof Date && expected instanceof Date) {
133+
} else if (util.isDate(actual) && util.isDate(expected)) {
157134
return actual.getTime() === expected.getTime();
158135

159-
// 7.3. Other pairs that do not both pass typeof value == 'object',
136+
// 7.3 If the expected value is a RegExp object, the actual value is
137+
// equivalent if it is also a RegExp object with the same source and
138+
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
139+
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
140+
return actual.source === expected.source &&
141+
actual.global === expected.global &&
142+
actual.multiline === expected.multiline &&
143+
actual.lastIndex === expected.lastIndex &&
144+
actual.ignoreCase === expected.ignoreCase;
145+
146+
// 7.4. Other pairs that do not both pass typeof value == 'object',
160147
// equivalence is determined by ==.
161-
} else if (typeof actual != 'object' && typeof expected != 'object') {
148+
} else if (!util.isObject(actual) && !util.isObject(expected)) {
162149
return actual == expected;
163150

164-
// 7.4. For all other Object pairs, including Array objects, equivalence is
151+
// 7.5 For all other Object pairs, including Array objects, equivalence is
165152
// determined by having the same number of owned properties (as verified
166153
// with Object.prototype.hasOwnProperty.call), the same set of keys
167154
// (although not necessarily the same order), equivalent values for every
@@ -172,16 +159,12 @@ function _deepEqual(actual, expected) {
172159
}
173160
}
174161

175-
function isUndefinedOrNull(value) {
176-
return value === null || value === undefined;
177-
}
178-
179162
function isArguments(object) {
180163
return Object.prototype.toString.call(object) == '[object Arguments]';
181164
}
182165

183166
function objEquiv(a, b) {
184-
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
167+
if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
185168
return false;
186169
// an identical 'prototype' property.
187170
if (a.prototype !== b.prototype) return false;
@@ -196,8 +179,8 @@ function objEquiv(a, b) {
196179
return _deepEqual(a, b);
197180
}
198181
try {
199-
var ka = objectKeys(a),
200-
kb = objectKeys(b),
182+
var ka = shims.keys(a),
183+
kb = shims.keys(b),
201184
key, i;
202185
} catch (e) {//happens when one is a string literal and the other isn't
203186
return false;
@@ -255,7 +238,7 @@ function expectedException(actual, expected) {
255238
return false;
256239
}
257240

258-
if (expected instanceof RegExp) {
241+
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
259242
return expected.test(actual);
260243
} else if (actual instanceof expected) {
261244
return true;
@@ -269,7 +252,7 @@ function expectedException(actual, expected) {
269252
function _throws(shouldThrow, block, expected, message) {
270253
var actual;
271254

272-
if (typeof expected === 'string') {
255+
if (util.isString(expected)) {
273256
message = expected;
274257
expected = null;
275258
}
@@ -284,11 +267,11 @@ function _throws(shouldThrow, block, expected, message) {
284267
(message ? ' ' + message : '.');
285268

286269
if (shouldThrow && !actual) {
287-
fail('Missing expected exception' + message);
270+
fail(actual, expected, 'Missing expected exception' + message);
288271
}
289272

290273
if (!shouldThrow && expectedException(actual, expected)) {
291-
fail('Got unwanted exception' + message);
274+
fail(actual, expected, 'Got unwanted exception' + message);
292275
}
293276

294277
if ((shouldThrow && actual && expected &&
@@ -305,8 +288,8 @@ assert.throws = function(block, /*optional*/error, /*optional*/message) {
305288
};
306289

307290
// EXTENSION! This is annoying to write outside this module.
308-
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
291+
assert.doesNotThrow = function(block, /*optional*/message) {
309292
_throws.apply(this, [false].concat(pSlice.call(arguments)));
310293
};
311294

312-
assert.ifError = function(err) { if (err) {throw err;}};
295+
assert.ifError = function(err) { if (err) {throw err;}};

test/browser/assert-simple.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,21 @@ test('assert.ok - pass', function (t) {
2727
}
2828
t.end();
2929
});
30+
31+
test('assert.deepEqual Make sure deepEqual doesn\'t loop forever on circular refs', function (t) {
32+
var b = {};
33+
b.b = b;
34+
35+
var c = {};
36+
c.b = c;
37+
38+
var gotError = false;
39+
try {
40+
assert.deepEqual(b, c);
41+
} catch (e) {
42+
gotError = true;
43+
}
44+
45+
t.ok(gotError);
46+
t.end();
47+
});

0 commit comments

Comments
 (0)