зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1300385 - Fix flaws in SimpleTest.isDeeply. r=Waldo
- When one of the parameters to isDeeply is an object/function and the other is not, isDeeply returned false. Well, isDeeply is supposed to report an error instead of returning a value... - Change the implementation of isDeeply to have SameValue semantics instead of weak equality. - Change the representation of arrays to look like an array, instead of its default toString() value which is indistinguishable from a string due to the lack of brackets and quotes. - Account for missing object properties; Distinguish them from "undefined" with the special DNE tag. MozReview-Commit-ID: F1OJhbXcptl --HG-- extra : rebase_source : 26091a40445064da3f87d61438bd74bbe7491363
This commit is contained in:
Родитель
54cc14572f
Коммит
a03dbe288b
|
@ -92,6 +92,8 @@ if (typeof(repr) == 'undefined') {
|
|||
ostring = (1 / o > 0) ? "+0" : "-0";
|
||||
} else if (typeof o === "string") {
|
||||
ostring = JSON.stringify(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
ostring = "[" + o.map(val => repr(val)).join(", ") + "]";
|
||||
} else {
|
||||
ostring = (o + "");
|
||||
}
|
||||
|
@ -1378,38 +1380,22 @@ if (isPrimaryTestWindow) {
|
|||
|
||||
SimpleTest.DNE = {dne: 'Does not exist'};
|
||||
SimpleTest.LF = "\r\n";
|
||||
SimpleTest._isRef = function (object) {
|
||||
var type = typeof(object);
|
||||
return type == 'object' || type == 'function';
|
||||
};
|
||||
|
||||
|
||||
SimpleTest._deepCheck = function (e1, e2, stack, seen) {
|
||||
var ok = false;
|
||||
// Either they're both references or both not.
|
||||
var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2));
|
||||
if (e1 == null && e2 == null) {
|
||||
if (Object.is(e1, e2)) {
|
||||
// Handles identical primitives and references.
|
||||
ok = true;
|
||||
} else if (e1 != null ^ e2 != null) {
|
||||
} else if (typeof e1 != "object" || typeof e2 != "object" || e1 === null || e2 === null) {
|
||||
// If either argument is a primitive or function, don't consider the arguments the same.
|
||||
ok = false;
|
||||
} else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) {
|
||||
} else if (e1 == SimpleTest.DNE || e2 == SimpleTest.DNE) {
|
||||
ok = false;
|
||||
} else if (sameRef && e1 == e2) {
|
||||
// Handles primitives and any variables that reference the same
|
||||
// object, including functions.
|
||||
ok = true;
|
||||
} else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) {
|
||||
ok = SimpleTest._eqArray(e1, e2, stack, seen);
|
||||
} else if (typeof e1 == "object" && typeof e2 == "object") {
|
||||
ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
|
||||
} else if (typeof e1 == "number" && typeof e2 == "number"
|
||||
&& isNaN(e1) && isNaN(e2)) {
|
||||
ok = true;
|
||||
} else {
|
||||
// If we get here, they're not the same (function references must
|
||||
// always simply reference the same function).
|
||||
stack.push({ vals: [e1, e2] });
|
||||
ok = false;
|
||||
ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
|
@ -1437,11 +1423,11 @@ SimpleTest._eqArray = function (a1, a2, stack, seen) {
|
|||
var ok = true;
|
||||
// Only examines enumerable attributes. Only works for numeric arrays!
|
||||
// Associative arrays return 0. So call _eqAssoc() for them, instead.
|
||||
var max = a1.length > a2.length ? a1.length : a2.length;
|
||||
var max = Math.max(a1.length, a2.length);
|
||||
if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen);
|
||||
for (var i = 0; i < max; i++) {
|
||||
var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i];
|
||||
var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i];
|
||||
var e1 = i < a1.length ? a1[i] : SimpleTest.DNE;
|
||||
var e2 = i < a2.length ? a2[i] : SimpleTest.DNE;
|
||||
stack.push({ type: 'Array', idx: i, vals: [e1, e2] });
|
||||
ok = SimpleTest._deepCheck(e1, e2, stack, seen);
|
||||
if (ok) {
|
||||
|
@ -1482,8 +1468,8 @@ SimpleTest._eqAssoc = function (o1, o2, stack, seen) {
|
|||
var o2Size = 0; for (var i in o2) o2Size++;
|
||||
var bigger = o1Size > o2Size ? o1 : o2;
|
||||
for (var i in bigger) {
|
||||
var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i];
|
||||
var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i];
|
||||
var e1 = i in o1 ? o1[i] : SimpleTest.DNE;
|
||||
var e2 = i in o2 ? o2[i] : SimpleTest.DNE;
|
||||
stack.push({ type: 'Object', idx: i, vals: [e1, e2] });
|
||||
ok = SimpleTest._deepCheck(e1, e2, stack, seen)
|
||||
if (ok) {
|
||||
|
@ -1502,7 +1488,7 @@ SimpleTest._formatStack = function (stack) {
|
|||
var type = entry['type'];
|
||||
var idx = entry['idx'];
|
||||
if (idx != null) {
|
||||
if (/^\d+$/.test(idx)) {
|
||||
if (type == 'Array') {
|
||||
// Numeric array index.
|
||||
variable += '[' + idx + ']';
|
||||
} else {
|
||||
|
@ -1522,39 +1508,26 @@ SimpleTest._formatStack = function (stack) {
|
|||
var out = "Structures begin differing at:" + SimpleTest.LF;
|
||||
for (var i = 0; i < vals.length; i++) {
|
||||
var val = vals[i];
|
||||
if (val == null) {
|
||||
val = 'undefined';
|
||||
if (val === SimpleTest.DNE) {
|
||||
val = "Does not exist";
|
||||
} else {
|
||||
val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'";
|
||||
val = repr(val);
|
||||
}
|
||||
out += vars[i] + ' = ' + val + SimpleTest.LF;
|
||||
}
|
||||
|
||||
out += vars[0] + ' = ' + vals[0] + SimpleTest.LF;
|
||||
out += vars[1] + ' = ' + vals[1] + SimpleTest.LF;
|
||||
|
||||
return ' ' + out;
|
||||
};
|
||||
|
||||
|
||||
SimpleTest.isDeeply = function (it, as, name) {
|
||||
var ok;
|
||||
// ^ is the XOR operator.
|
||||
if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) {
|
||||
// One's a reference, one isn't.
|
||||
ok = false;
|
||||
} else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) {
|
||||
// Neither is an object.
|
||||
ok = SimpleTest.is(it, as, name);
|
||||
var stack = [{ vals: [it, as] }];
|
||||
var seen = [];
|
||||
if ( SimpleTest._deepCheck(it, as, stack, seen)) {
|
||||
SimpleTest.ok(true, name);
|
||||
} else {
|
||||
// We have two objects. Do a deep comparison.
|
||||
var stack = [], seen = [];
|
||||
if ( SimpleTest._deepCheck(it, as, stack, seen)) {
|
||||
ok = SimpleTest.ok(true, name);
|
||||
} else {
|
||||
ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
|
||||
}
|
||||
SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
|
||||
SimpleTest.typeOf = function (object) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче