Repository: nodejs/node
Pull request: zlib: deprecate classes usage without `new`

Since we documentation-only deprecated the usage without `new` qualifier, we can make it runtime deprecated.

Changed files:
filename: doc/api/deprecations.md
patch: @@ -3737,14 +3737,17 @@ and [`crypto.setEngine()`][] all depend on this functionality from OpenSSL.
 
 <!-- YAML
 changes:
+  - version: REPLACEME
+    pr-url: https://github.com/nodejs/node/pull/55718
+    description: Runtime deprecation.
   - version:
     - v22.9.0
     - v20.18.0
     pr-url: https://github.com/nodejs/node/pull/54708
     description: Documentation-only deprecation.
 -->
 
-Type: Documentation-only
+Type: Runtime
 
 Instantiating classes without the `new` qualifier exported by the `node:zlib` module is deprecated.
 It is recommended to use the `new` qualifier instead. This applies to all Zlib classes, such as `Deflate`,

filename: lib/zlib.js
patch: @@ -46,6 +46,9 @@ const {
   genericNodeError,
 } = require('internal/errors');
 const { Transform, finished } = require('stream');
+const {
+  deprecateInstantiation,
+} = require('internal/util');
 const {
   isArrayBufferView,
   isAnyArrayBuffer,
@@ -686,57 +689,64 @@ Zlib.prototype.params = function params(level, strategy, callback) {
 // generic zlib
 // minimal 2-byte header
 function Deflate(opts) {
-  if (!(this instanceof Deflate))
-    return new Deflate(opts);
+  if (!(this instanceof Deflate)) {
+    return deprecateInstantiation(Deflate, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, DEFLATE]);
 }
 ObjectSetPrototypeOf(Deflate.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(Deflate, Zlib);
 
 function Inflate(opts) {
-  if (!(this instanceof Inflate))
-    return new Inflate(opts);
+  if (!(this instanceof Inflate)) {
+    return deprecateInstantiation(Inflate, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, INFLATE]);
 }
 ObjectSetPrototypeOf(Inflate.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(Inflate, Zlib);
 
 function Gzip(opts) {
-  if (!(this instanceof Gzip))
-    return new Gzip(opts);
+  if (!(this instanceof Gzip)) {
+    return deprecateInstantiation(Gzip, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, GZIP]);
 }
 ObjectSetPrototypeOf(Gzip.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(Gzip, Zlib);
 
 function Gunzip(opts) {
-  if (!(this instanceof Gunzip))
-    return new Gunzip(opts);
+  if (!(this instanceof Gunzip)) {
+    return deprecateInstantiation(Gunzip, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, GUNZIP]);
 }
 ObjectSetPrototypeOf(Gunzip.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(Gunzip, Zlib);
 
 function DeflateRaw(opts) {
   if (opts && opts.windowBits === 8) opts.windowBits = 9;
-  if (!(this instanceof DeflateRaw))
-    return new DeflateRaw(opts);
+  if (!(this instanceof DeflateRaw)) {
+    return deprecateInstantiation(DeflateRaw, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, DEFLATERAW]);
 }
 ObjectSetPrototypeOf(DeflateRaw.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(DeflateRaw, Zlib);
 
 function InflateRaw(opts) {
-  if (!(this instanceof InflateRaw))
-    return new InflateRaw(opts);
+  if (!(this instanceof InflateRaw)) {
+    return deprecateInstantiation(InflateRaw, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, INFLATERAW]);
 }
 ObjectSetPrototypeOf(InflateRaw.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(InflateRaw, Zlib);
 
 function Unzip(opts) {
-  if (!(this instanceof Unzip))
-    return new Unzip(opts);
+  if (!(this instanceof Unzip)) {
+    return deprecateInstantiation(Unzip, 'DEP0184', opts);
+  }
   ReflectApply(Zlib, this, [opts, UNZIP]);
 }
 ObjectSetPrototypeOf(Unzip.prototype, Zlib.prototype);
@@ -801,16 +811,18 @@ ObjectSetPrototypeOf(Brotli.prototype, Zlib.prototype);
 ObjectSetPrototypeOf(Brotli, Zlib);
 
 function BrotliCompress(opts) {
-  if (!(this instanceof BrotliCompress))
-    return new BrotliCompress(opts);
+  if (!(this instanceof BrotliCompress)) {
+    return deprecateInstantiation(BrotliCompress, 'DEP0184', opts);
+  }
   ReflectApply(Brotli, this, [opts, BROTLI_ENCODE]);
 }
 ObjectSetPrototypeOf(BrotliCompress.prototype, Brotli.prototype);
 ObjectSetPrototypeOf(BrotliCompress, Brotli);
 
 function BrotliDecompress(opts) {
-  if (!(this instanceof BrotliDecompress))
-    return new BrotliDecompress(opts);
+  if (!(this instanceof BrotliDecompress)) {
+    return deprecateInstantiation(BrotliDecompress, 'DEP0184', opts);
+  }
   ReflectApply(Brotli, this, [opts, BROTLI_DECODE]);
 }
 ObjectSetPrototypeOf(BrotliDecompress.prototype, Brotli.prototype);

filename: test/parallel/test-zlib.js
patch: @@ -1,3 +1,4 @@
+// Flags: --no-warnings
 // Copyright Joyent, Inc. and other Node contributors.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -230,3 +231,10 @@ testKeys.forEach(common.mustCall((file) => {
     }, trickle.length));
   }, chunkSize.length));
 }, testKeys.length));
+
+{
+  // Test instantiation without 'new'
+  common.expectWarning('DeprecationWarning', `Instantiating Gzip without the 'new' keyword has been deprecated.`, 'DEP0184');
+  const gzip = zlib.Gzip();
+  assert.ok(gzip instanceof zlib.Gzip);
+}