Unexpected behavior of console.log under certain condition #1634

Closed
kuebk opened this Issue Sep 2, 2011 · 16 comments

Projects

None yet

5 participants

@kuebk
kuebk commented Sep 2, 2011

Sample code:

var util = require('util');
try {
    console.log(undef());
}catch(e){
    console.log(e);
    console.log(util.inspect(e, true, null));
}

Under node 0.5.0 it results with:

{ stack: [Getter/Setter],
    arguments: [ 'undef' ],
    type: 'not_defined',
    message: [Getter/Setter] }
{ stack: [Getter/Setter],
    arguments: [ 'undef', [length]: 1 ],
    message: [Getter/Setter],
    type: 'not_defined' }

But since 0.5.1 it resuls with:

{}
{ [stack]: [Getter/Setter],
    [message]: [Getter/Setter],
    [arguments]: [ 'undef', [length]: 1 ],
    [type]: 'not_defined' }

First console.log is empty, why?

Thanks to @tereska for finding this.

@ry
ry commented Sep 2, 2011

can you provide a test script. im not sure why the behavior changed - but if you desire something specific we can nail it down.

@kuebk
kuebk commented Sep 2, 2011

Was already attached but: https://gist.github.com/1189725

@ry
ry commented Sep 2, 2011

that doesn't tell me what you're expecting

@kuebk
kuebk commented Sep 2, 2011

I expected the console.log(e) to output exacly the same as console.log(util.inspect(e, true, null)) - as it was working till 0.5.1

@bnoordhuis bnoordhuis added a commit to bnoordhuis/node that referenced this issue Sep 3, 2011
@bnoordhuis bnoordhuis test: add #1634 test case 3efebbe
@bnoordhuis bnoordhuis added a commit to bnoordhuis/node that referenced this issue Sep 3, 2011
@bnoordhuis bnoordhuis util: fix exception stringification in .format()
Fixes #1634.
7292023
@bnoordhuis
Member

Someone review 3efebbe and 7292023, por favor!

@koichik
koichik commented Sep 3, 2011

@kuebk - Since Node v0.5.1 (v8 3.4), all properties of Error came to be non-enumerated according to the ES5 specification.
(please refer to "8.6.1 Property Attributes")

@bnoordhuis - In some subclass of Error, the message property is getter/setter.

$ ./node
> try {undef()} catch(e) {console.log(e)}
{ [stack]: [Getter/Setter],
  [message]: [Getter/Setter],
  [arguments]: [ 'undef' ],
  [type]: 'not_defined' }

I think it is not so useful.
How about the format like a function? example: [ReferenceError: undef is not defined]

@bnoordhuis
Member

@koichik - that was my first take actually so yes, I can live with that. =)

@kuebk
kuebk commented Sep 3, 2011

@koichik I didn't know that implemention in v8 <3.4 didn't follow specification.
If specification says so, there is no need to fix this imo.

@tshinnic
tshinnic commented Sep 3, 2011

Umm, ick. Change 7292023 did indeed fix problem of util.inspect with exception objects. Thank you. But this leaves console.log('%j') still having changed behavior. ES5 specification broke my exceptional expectations for sure. Ick.

Test older stable 0.4.x

[Tom@TLSF15A node.js]$ node -v
v0.4.11
[Tom@TLSF15A node.js]$ node
> var util = require('util')
> var e = new Error('blam!')
> e
{ stack: [Getter/Setter],
  arguments: undefined,
  type: undefined,
  message: 'blam!' }
> console.log(' e is %s', e)
 e is Error: blam!
> console.log(' e is %j', e)
 e is {"stack":"Error: blam!\n    at [object Context]:1:9\n    at Interface.<anonymous> (repl.js:171:22)\n    at Interface.emit (events.js:64:17)\n    at Interface._onLine (readline.js:153:10)\n    at Interface._line (readline.js:408:8)\n    at Interface._ttyWrite (readline.js:585:14)\n    at ReadStream.<anonymous> (readline.js:73:12)\n    at ReadStream.emit (events.js:81:20)\n    at ReadStream._emitKey (tty_posix.js:307:10)\n    at ReadStream.onData (tty_posix.js:70:12)",
       "message":"blam!"}
> console.log(' e is %j', util.inspect(e))
 e is "{ stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'blam!' }"
> console.log(' e is %j', util.inspect(e,true))
 e is "{ stack: [Getter/Setter], arguments: undefined, message: 'blam!', type: undefined }"

Test recent master (showing problem)

[Tom@TLSF15A node-1]$ ./node -v
v0.5.6-pre
[Tom@TLSF15A node-1]$ ./node
> var util = require('util')
> var e = new Error('blame')
> e
{}
> console.log(' e is %s', e)
 e is Error: blame
> console.log(' e is %j', e)
 e is {}
> console.log(' e is %j', util.inspect(e))
 e is "{}"
> console.log(' e is %j', util.inspect(e,true))
 e is "{ [stack]: [Getter/Setter],\n  [message]: 'blame',\n  [arguments]: undefined,\n  [type]: undefined }"

(and also verified that Windows 0.5.5.exe had same results)

after util: fix exception stringification in .format() Fixes # 1634.

[Tom@TLSF15A node-1]$ ./node -v
v0.5.6-pre
[Tom@TLSF15A node-1]$ ./node
> var util = require('util')
> var e = new Error('bloem')
> e
{ [stack]: [Getter/Setter],
  [arguments]: undefined,
  [type]: undefined ,
  [message]: 'bloem' }
> console.log(' e is %s', e)
 e is Error: bloem
> console.log(' e is %j', e)
 e is {}
> console.log(' e is %j', util.inspect(e))
 e is "{ [stack]: [Getter/Setter],\n  [message]: 'bloem',\n  [arguments]: undefined,\n  [type]: undefined }"
> console.log(' e is %j', util.inspect(e,true))
 e is "{ [stack]: [Getter/Setter],\n  [message]: 'bloem',\n  [arguments]: undefined,\n  [type]: undefined }"
@tshinnic
tshinnic commented Sep 3, 2011

Ah, yes, this is bs and a bug in V8. Someone misread the spec, Error.prototype properties vs. Error properties.

http://code.google.com/p/v8/issues/detail?id=1595

@koichik: not all properties of Error ...

15.11.1.1 Error (message)

If the argument message is not undefined, the message own property
of the newly constructed object is set to ToString(message).

15.11.2.1 new Error (message)

If the argument message is not undefined, the message own property
of the newly constructed object is set to ToString(message).

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

Man, I shouldn't have stopped reviewing drafts mid-last year ... months of sending in "huh?" got pre-empted by "hey get back to work!"

15.11.4.4 Error.prototype.toString ( )

  1. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
  2. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
@koichik
koichik commented Sep 3, 2011

@tshinnic - Hmm... "8.6.1 Property Attributes" says:

If the value of an attribute is not explicitly specified by this specification for a named property, the default value
defined in Table 7 is used.

Table 7:

[[Enumerable]] false

And, In "15.11 Error Object", there is no property for which [[Enumerable]] true is specified.
Therefore all properties of Error are non-enumerable, I think.

Note: an instance of Error has the message own property, but it is non-enumerable.
Because its [[Enumerable]] attribute is not specified.

But my English is very poor, I might be misreading the spec.

@tshinnic
tshinnic commented Sep 3, 2011

Your English is very likely to be better than the English in the specification. And I see the reference in the table, and I'm having a hard time finding the exception to that general rule. So...

I've posted the question on the es-discuss maillist. Hopefully they will pause talking about future ideas long enough to answer a concrete yes or no question.

https://mail.mozilla.org/pipermail/es-discuss/2011-September/thread.html

@bnoordhuis
Member

Okay, let's see how this one plays out. If V8 fixes it upstream, so much the better.

@tshinnic
tshinnic commented Sep 4, 2011

Indeed, I keep seeing the same two responses from each person: "Yes, that's surprising" along with "Yes, that's the spec!"

So we do need your fix, now and probably forever. x-(

@koichik
koichik commented Sep 6, 2011

How about 23e4564?

> try { undef() } catch (e) { console.log(e) }
[ReferenceError: undef is not defined]
> try { undef() } catch (e) { console.log(require('util').inspect(e, true)) }
{ [ReferenceError: undef is not defined]
  [stack]: [Getter/Setter],
  [message]: [Getter/Setter],
  [arguments]: [ 'undef', [length]: 1 ],
  [type]: 'not_defined' }
@koichik
koichik commented Sep 8, 2011

@bnoordhuis - Can you review 7bf77fa?

@koichik koichik added a commit to koichik/node that referenced this issue Sep 9, 2011
@koichik koichik util: Fix inspection for Error
Fixes #1634.
2ff7efc
@koichik koichik added a commit that closed this issue Sep 11, 2011
@koichik koichik util: Fix inspection for Error
Fixes #1634.
389e2a0
@koichik koichik closed this in 389e2a0 Sep 11, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment