docs: function (sender, contextId, value, optimizeSimpleObject = false) {
    // Determine the type of value.
    const meta = { type: typeof value }
    if (meta.type === 'object') {
      // Recognize certain types of objects.
      if (value === null) {
        meta.type = 'value'
      } else if (bufferUtils.isBuffer(value)) {
        meta.type = 'buffer'
      } else if (Array.isArray(value)) {
        meta.type = 'array'
      } else if (value instanceof Error) {
        meta.type = 'error'
      } else if (value instanceof Date) {
        meta.type = 'date'
      } else if (isPromise(value)) {
        meta.type = 'promise'
      } else if (hasProp.call(value, 'callee') && value.length != null) {
        // Treat the arguments object as array.
        meta.type = 'array'
      } else if (optimizeSimpleObject && v8Util.getHiddenValue(value, 'simple')) {
        // Treat simple objects as value.
        meta.type = 'value'
      }
    }
  
    // Fill the meta object according to value's type.
    if (meta.type === 'array') {
      meta.members = value.map((el) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
    } else if (meta.type === 'object' || meta.type === 'function') {
      meta.name = value.constructor ? value.constructor.name : ''
  
      // Reference the original value if it's an object, because when it's
      // passed to renderer we would assume the renderer keeps a reference of
      // it.
      meta.id = objectsRegistry.add(sender, contextId, value)
      meta.members = getObjectMembers(value)
      meta.proto = getObjectPrototype(value)
    } else if (meta.type === 'buffer') {
      meta.value = bufferUtils.bufferToMeta(value)
    } else if (meta.type === 'promise') {
      // Add default handler to prevent unhandled rejections in main process
      // Instead they should appear in the renderer process
      value.then(function () {}, function () {})
  
      meta.then = valueToMeta(sender, contextId, function (onFulfilled, onRejected) {
        value.then(onFulfilled, onRejected)
      })
    } else if (meta.type === 'error') {
      meta.members = plainObjectToMeta(value)
  
      // Error.name is not part of own properties.
      meta.members.push({
        name: 'name',
        value: value.name
      })
    } else if (meta.type === 'date') {
      meta.value = value.getTime()
    } else {
      meta.type = 'value'
      meta.value = value
    }
    return meta
  }