Skip to content

Commit

Permalink
Warn when functions intended as constructors are called without new (#…
Browse files Browse the repository at this point in the history
…2021)

* Warn when pg.Pool() isn’t called as a constructor

in preparation for #1541. `eval` is a bit awkward, but it’s more accurate than an `instanceof` check and will work on platforms new enough to support pg 8 (i.e. only not Node 4).

* Warn when Query() isn’t called as a constructor
  • Loading branch information
charmander authored and brianc committed Dec 17, 2019
1 parent c1f954b commit 2b59209
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
22 changes: 22 additions & 0 deletions lib/compat/check-constructor.js
@@ -0,0 +1,22 @@
'use strict'

const warnDeprecation = require('./warn-deprecation')

// Node 4 doesn’t support new.target.
let hasNewTarget

try {
// eslint-disable-next-line no-eval
eval('(function () { new.target })')
hasNewTarget = true
} catch (error) {
hasNewTarget = false
}

const checkConstructor = (name, code, getNewTarget) => {
if (hasNewTarget && getNewTarget() === undefined) {
warnDeprecation(`Constructing a ${name} without new is deprecated and will stop working in pg 8.`, code)
}
}

module.exports = checkConstructor
19 changes: 19 additions & 0 deletions lib/compat/warn-deprecation.js
@@ -0,0 +1,19 @@
'use strict'

const util = require('util')

const dummyFunctions = new Map()

// Node 4 doesn’t support process.emitWarning(message, 'DeprecationWarning', code).
const emitDeprecationWarning = (message, code) => {
let dummy = dummyFunctions.get(code)

if (dummy === undefined) {
dummy = util.deprecate(() => {}, message)
dummyFunctions.set(code, dummy)
}

dummy()
}

module.exports = emitDeprecationWarning
4 changes: 4 additions & 0 deletions lib/index.js
Expand Up @@ -12,9 +12,13 @@ var Client = require('./client')
var defaults = require('./defaults')
var Connection = require('./connection')
var Pool = require('pg-pool')
const checkConstructor = require('./compat/check-constructor')

const poolFactory = (Client) => {
var BoundPool = function (options) {
// eslint-disable-next-line no-eval
checkConstructor('pg.Pool', 'PG-POOL-NEW', () => eval('new.target'))

var config = Object.assign({ Client: Client }, options)
return new Pool(config)
}
Expand Down
5 changes: 4 additions & 1 deletion lib/query.js
Expand Up @@ -9,12 +9,15 @@

var EventEmitter = require('events').EventEmitter
var util = require('util')
const checkConstructor = require('./compat/check-constructor')

var Result = require('./result')
var utils = require('./utils')

var Query = function (config, values, callback) {
// use of "new" optional
// use of "new" optional in pg 7
// eslint-disable-next-line no-eval
checkConstructor('Query', 'PG-QUERY-NEW', () => eval('new.target'))
if (!(this instanceof Query)) { return new Query(config, values, callback) }

config = utils.normalizeQueryConfig(config, values, callback)
Expand Down

0 comments on commit 2b59209

Please sign in to comment.