Skip to content

Commit 6191e2e

Browse files
committed
Node.js util.format('%s') breaking change bug
The documentation says that util.format('%s', obj) will call String(obj) iff obj has a user-defined .toString method, but in v12.12.0 it only calls String(obj) if either obj or obj.constructor.prototype has an own property named toString, causing inherited toString implementations to be ignored. Submitted as nodejs/node#30333
1 parent 61b38b5 commit 6191e2e

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

node/format-bug.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* The documentation says that util.format('%s', obj) will call
2+
* String(obj) iff obj has a user-defined .toString method, but in
3+
* v12.12.0 it only calls String(obj)
4+
*
5+
* Submitted as https://github.com/nodejs/node/issues/30333
6+
*/
7+
8+
// ES6 subclassing:
9+
class A {
10+
toString() {
11+
return 'custom A';
12+
}
13+
}
14+
15+
class B extends A {
16+
}
17+
18+
// ES5 subclassing:
19+
function C() {
20+
};
21+
22+
C.prototype.toString = function() {
23+
return 'custom C';
24+
}
25+
26+
function D() {
27+
C.call(this);
28+
}
29+
30+
D.prototype = Object.create(C.prototype);
31+
// What if we forget to set the .constructor?
32+
// D.prototype.constructor = D;
33+
34+
console.log('%s', new A()); // expected/actual: custom A
35+
console.log('%s', new B()); // expected: custom A / actual: B {}
36+
console.log('%s', new C()); // expected/actual: custom C
37+
console.log('%s', new D()); // expected/actual: custom C (!)
38+
39+
// Fix forgotten .constructor:
40+
D.prototype.constructor = D;
41+
console.log('%s', new D()); // expected: custom C / actual: D {}

0 commit comments

Comments
 (0)