Repository: pinojs/pino
Pull request #527 (2018-10-03 11:53:00)

The serializer object should not have a prototype
https://github.com/pinojs/pino/issues/525

@NiXXeD can you please confirm that this fixes your issue?


Patch:
diff --git a/lib/proto.js b/lib/proto.js
index 0389e4c..b6bf1bb 100644
--- a/lib/proto.js
+++ b/lib/proto.js
@@ -64,7 +64,7 @@ function child (bindings) {
   const chindings = asChindings(this, bindings)
   const instance = Object.create(this)
   if (bindings.hasOwnProperty('serializers') === true) {
-    instance[serializersSym] = {}
+    instance[serializersSym] = Object.create(null)
     for (var k in serializers) {
       instance[serializersSym][k] = serializers[k]
     }
diff --git a/lib/tools.js b/lib/tools.js
index 536a0dc..069d12a 100644
--- a/lib/tools.js
+++ b/lib/tools.js
@@ -122,6 +122,10 @@ function asJson (obj, msg, num, time) {
           case 'string':
             value = (stringifiers[key] || asString)(value)
             break
+          case 'function':
+            // ignore functions
+            value = undefined
+            break
           default:
             value = (stringifiers[key] || stringify)(value)
         }
diff --git a/pino.js b/pino.js
index 467e104..427c3d6 100644
--- a/pino.js
+++ b/pino.js
@@ -1,6 +1,6 @@
 'use strict'
 const os = require('os')
-const serializers = require('pino-std-serializers')
+const stdSerializers = require('pino-std-serializers')
 const SonicBoom = require('sonic-boom')
 const redaction = require('./lib/redaction')
 const time = require('./lib/time')
@@ -33,7 +33,7 @@ const {
 const { epochTime, nullTime } = time
 const { pid } = process
 const hostname = os.hostname()
-const defaultErrorSerializer = serializers.err
+const defaultErrorSerializer = stdSerializers.err
 const defaultOptions = {
   level: 'info',
   useLevelLabels: false,
@@ -41,7 +41,9 @@ const defaultOptions = {
   enabled: true,
   prettyPrint: false,
   base: { pid, hostname },
-  serializers: { err: defaultErrorSerializer },
+  serializers: Object.assign(Object.create(null), {
+    err: defaultErrorSerializer
+  }),
   timestamp: epochTime,
   name: undefined,
   redact: null,
@@ -52,6 +54,8 @@ const defaultOptions = {
 
 const normalize = createArgsNormalizer(defaultOptions)
 
+const serializers = Object.assign(Object.create(null), stdSerializers)
+
 function pino (...args) {
   const { opts, stream } = normalize(...args)
   const {
@@ -119,7 +123,7 @@ pino.extreme = (dest = process.stdout.fd) => new SonicBoom(dest, 4096)
 pino.destination = (dest = process.stdout.fd) => new SonicBoom(dest)
 pino.final = final
 pino.levels = mappings()
-pino.stdSerializers = Object.assign({}, serializers)
+pino.stdSerializers = serializers
 pino.stdTimeFunctions = Object.assign({}, time)
 pino.symbols = symbols
 pino.version = version


Test patch:
diff --git a/test/error.test.js b/test/error.test.js
index b3677d4..4f0cfa7 100644
--- a/test/error.test.js
+++ b/test/error.test.js
@@ -153,3 +153,24 @@ test('stack is rendered as any other property if it\'s not a string', t => {
   instance.level = name
   instance[name](err)
 })
+
+test('correctly ignores toString on errors', async ({ same }) => {
+  const err = new Error('myerror')
+  err.toString = () => undefined
+  const stream = sink()
+  const instance = pino({
+    test: 'this'
+  }, stream)
+  instance.fatal(err)
+  const result = await once(stream, 'data')
+  delete result.time
+  same(result, {
+    pid: pid,
+    hostname: hostname,
+    level: 60,
+    type: 'Error',
+    msg: err.message,
+    stack: err.stack,
+    v: 1
+  })
+})
diff --git a/test/helper.js b/test/helper.js
index a46ff6e..cb9038b 100644
--- a/test/helper.js
+++ b/test/helper.js
@@ -18,7 +18,14 @@ function once (emitter, name) {
 }
 
 function sink (func) {
-  const result = split(JSON.parse)
+  const result = split((data) => {
+    try {
+      return JSON.parse(data)
+    } catch (err) {
+      console.log(err)
+      console.log(data)
+    }
+  })
   if (func) result.pipe(writer.obj(func))
   return result
 }