diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 53a6398a..650bc825 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -6,6 +6,7 @@ unreleased: - GH-1035 Added missing buffer APIs to expose a uniform interface across environments - GH-1052 Added support URL, Encoding, File, Cryptography, and Stream globals - GH-1049 Replaced shims for atob and btoa with native implementations + - GH-1050 Deprecated `atob`, `btoa`, `backbone`, 'crypto-js' and `tv4` libraries fixed bugs: - GH-1036 Fixed `uncaughtException` event listener not being removed - GH-1034 Fixed an issue where sandbox crashes for large response body diff --git a/lib/sandbox/execute-context.js b/lib/sandbox/execute-context.js index f58e2490..c49a878c 100644 --- a/lib/sandbox/execute-context.js +++ b/lib/sandbox/execute-context.js @@ -1,6 +1,14 @@ const { isNonLegacySandbox } = require('./non-legacy-codemarkers'); const _ = require('lodash'), - legacy = require('./postman-legacy-interface'); + legacy = require('./postman-legacy-interface'), + + DEPRECATED_LIBS = { + atob: 'global "atob" function', + btoa: 'global "btoa" function', + 'crypto-js': 'global "crypto" object', + tv4: '"ajv" library', + backbone: null + }; module.exports = function (scope, code, execution, console, timers, pmapi, onAssertion, options) { // if there is no code, then no point bubbling anything up @@ -44,7 +52,18 @@ module.exports = function (scope, code, execution, console, timers, pmapi, onAss setImmediate: timers.setImmediate, clearTimeout: timers.clearTimeout, clearInterval: timers.clearInterval, - clearImmediate: timers.clearImmediate + clearImmediate: timers.clearImmediate, + + require: (...args) => { + const key = args?.[0], + alt = DEPRECATED_LIBS[key]; + + if (alt !== undefined) { + console.warn(`Using "${key}" library is deprecated.${alt !== null ? ` Use ${alt} instead.` : ''}`); + } + + return require(...args); + } }); scope.exec(code, { async: true }, function (err) { diff --git a/lib/sandbox/postman-legacy-interface.js b/lib/sandbox/postman-legacy-interface.js index a3a7d98f..b0458744 100644 --- a/lib/sandbox/postman-legacy-interface.js +++ b/lib/sandbox/postman-legacy-interface.js @@ -20,34 +20,33 @@ const _ = require('lodash'), ], LEGACY_GLOBS_ALTERNATIVES = { - tests: 'pm.test()', - globals: 'pm.globals', - environment: 'pm.environment', - data: 'pm.iterationData', - request: 'pm.request', - responseCookies: 'pm.cookies', - responseHeaders: 'pm.response.headers', - responseTime: 'pm.response.responseTime', - responseCode: 'pm.response.code', - responseBody: 'pm.response.text()', - iteration: 'pm.info.iteration', - _: 'require(\'lodash\')', - CryptoJS: 'require(\'crypto-js\')', - tv4: 'require(\'ajv\')', - xml2Json: 'require(\'xml2js\')', - Backbone: 'require(\'backbone\')', - cheerio: 'require(\'cheerio\')', - 'postman.setNextRequest': 'pm.execution.setNextRequest()', - 'postman.setEnvironmentVariable': 'pm.environment.set()', - 'postman.getEnvironmentVariable': 'pm.environment.get()', - 'postman.clearEnvironmentVariables': 'pm.environment.clear()', - 'postman.clearEnvironmentVariable': 'pm.environment.unset()', - 'postman.setGlobalVariable': 'pm.globals.set()', - 'postman.getGlobalVariable': 'pm.globals.get()', - 'postman.clearGlobalVariables': 'pm.globals.clear()', - 'postman.clearGlobalVariable': 'pm.globals.unset()', - 'postman.getResponseCookie': 'pm.cookies.get()', - 'postman.getResponseHeader': 'pm.response.headers.get()' + tests: '"pm.test()"', + globals: '"pm.globals"', + environment: '"pm.environment"', + data: '"pm.iterationData"', + request: '"pm.request"', + responseCookies: '"pm.cookies"', + responseHeaders: '"pm.response.headers"', + responseTime: '"pm.response.responseTime"', + responseCode: '"pm.response.code"', + responseBody: '"pm.response.text()"', + iteration: '"pm.info.iteration"', + _: '"require(\'lodash\')"', + CryptoJS: 'global "crypto" object', + tv4: '"require(\'ajv\')"', + xml2Json: '"require(\'xml2js\')"', + cheerio: '"require(\'cheerio\')"', + 'postman.setNextRequest': '"pm.execution.setNextRequest()"', + 'postman.setEnvironmentVariable': '"pm.environment.set()"', + 'postman.getEnvironmentVariable': '"pm.environment.get()"', + 'postman.clearEnvironmentVariables': '"pm.environment.clear()"', + 'postman.clearEnvironmentVariable': '"pm.environment.unset()"', + 'postman.setGlobalVariable': '"pm.globals.set()"', + 'postman.getGlobalVariable': '"pm.globals.get()"', + 'postman.clearGlobalVariables': '"pm.globals.clear()"', + 'postman.clearGlobalVariable': '"pm.globals.unset()"', + 'postman.getResponseCookie': '"pm.cookies.get()"', + 'postman.getResponseHeader': '"pm.response.headers.get()"' }, E = '', @@ -192,7 +191,7 @@ function logDeprecationWarning (key, legacyUsageSet, console) { legacyUsageSet.add(key); if (LEGACY_GLOBS_ALTERNATIVES[key]) { - console.warn(`Using "${key}" is deprecated. Use "${LEGACY_GLOBS_ALTERNATIVES[key]}" instead.`); + console.warn(`Using "${key}" is deprecated. Use ${LEGACY_GLOBS_ALTERNATIVES[key]} instead.`); } else if (LEGACY_GLOBS.includes(key)) { console.warn(`Using "${key}" is deprecated.`); diff --git a/npm/utils/templates.js b/npm/utils/templates.js index 1ffbc492..2f824501 100644 --- a/npm/utils/templates.js +++ b/npm/utils/templates.js @@ -93,17 +93,17 @@ declare var iteration; declare var _; /** - * @deprecated Use require('crypto-js') instead + * @deprecated Use global "crypto" object instead */ declare var CryptoJS; /** - * @deprecated Use require('atob') instead + * @deprecated Use global "atob" function instead */ declare var atob; /** - * @deprecated Use require('btoa') instead + * @deprecated Use global "btoa" function instead */ declare var btoa; @@ -118,7 +118,7 @@ declare var tv4; declare var xml2Json; /** - * @deprecated Use require('backbone') instead + * @deprecated */ declare var Backbone; diff --git a/test/unit/sandbox-libraries/deprecation.test.js b/test/unit/sandbox-libraries/deprecation.test.js new file mode 100644 index 00000000..9668d7cc --- /dev/null +++ b/test/unit/sandbox-libraries/deprecation.test.js @@ -0,0 +1,164 @@ +const env = require('../../../lib/environment'), + DEPRECATED_LIBS = ['atob', 'btoa', 'crypto-js', 'tv4', 'backbone']; + +describe('sandbox library - deprecation', function () { + this.timeout(1000 * 60); + var Sandbox = require('../../../'), + context; + + beforeEach(function (done) { + Sandbox.createContext({}, function (err, ctx) { + context = ctx; + done(err); + }); + }); + + afterEach(function () { + context.dispose(); + context = null; + }); + + it('should show deprecation warning for "tv4"', function (done) { + const consoleSpy = sinon.spy(); + + context.on('console', consoleSpy); + context.execute(` + const requiredTv4 = require('tv4'); + tv4.validate; + `, function (err) { + if (err) { + return done(err); + } + + expect(consoleSpy).to.be.calledTwice; + + expect(consoleSpy.firstCall.args[1]).to.equal('warn'); + expect(consoleSpy.firstCall.args[2]) + .to.equal('Using "tv4" library is deprecated. Use "ajv" library instead.'); + + expect(consoleSpy.secondCall.args[1]).to.equal('warn'); + expect(consoleSpy.secondCall.args[2]) + .to.equal('Using "tv4" is deprecated. Use "require(\'ajv\')" instead.'); + + done(); + }); + }); + + it('should show deprecation warning for "crypto-js"', function (done) { + const consoleSpy = sinon.spy(); + + context.on('console', consoleSpy); + context.execute(` + const requiredCryptoJS = require('crypto-js'); + CryptoJS.lib; + `, function (err) { + if (err) { + return done(err); + } + + expect(consoleSpy).to.be.calledTwice; + + expect(consoleSpy.firstCall.args[1]).to.equal('warn'); + expect(consoleSpy.firstCall.args[2]) + .to.equal('Using "crypto-js" library is deprecated. Use global "crypto" object instead.'); + + expect(consoleSpy.secondCall.args[1]).to.equal('warn'); + expect(consoleSpy.secondCall.args[2]) + .to.equal('Using "CryptoJS" is deprecated. Use global "crypto" object instead.'); + + done(); + }); + }); + + + it('should show deprecation warning for "backbone', function (done) { + const consoleSpy = sinon.spy(); + + context.on('console', consoleSpy); + context.execute(` + const requiredBackbone = require('backbone'); + Backbone.Backbone; + `, function (err) { + if (err) { + return done(err); + } + + expect(consoleSpy).to.be.calledTwice; + + expect(consoleSpy.firstCall.args[1]).to.equal('warn'); + expect(consoleSpy.firstCall.args[2]) + .to.equal('Using "backbone" library is deprecated.'); + + expect(consoleSpy.secondCall.args[1]).to.equal('warn'); + expect(consoleSpy.secondCall.args[2]) + .to.equal('Using "Backbone" is deprecated.'); + + done(); + }); + }); + + it('should show deprecation warning for "atob', function (done) { + const consoleSpy = sinon.spy(); + + context.on('console', consoleSpy); + context.execute(` + const requiredAtob = require('atob'); + atob('YQ=='); + `, function (err) { + if (err) { + return done(err); + } + + expect(consoleSpy).to.be.calledOnce; + + expect(consoleSpy.firstCall.args[1]).to.equal('warn'); + expect(consoleSpy.firstCall.args[2]) + .to.equal('Using "atob" library is deprecated. Use global "atob" function instead.'); + + done(); + }); + }); + + it('should show deprecation warning for "btoa', function (done) { + const consoleSpy = sinon.spy(); + + context.on('console', consoleSpy); + context.execute(` + const requiredBtoa = require('btoa'); + btoa('a'); + `, function (err) { + if (err) { + return done(err); + } + + expect(consoleSpy).to.be.calledOnce; + + expect(consoleSpy.firstCall.args[1]).to.equal('warn'); + expect(consoleSpy.firstCall.args[2]) + .to.equal('Using "btoa" library is deprecated. Use global "btoa" function instead.'); + + done(); + }); + }); + + it('should not show warning for non-deprecated libraries', function (done) { + const consoleSpy = sinon.spy(), + libs = Object.entries(env.require).map(([key, value]) => { + return value.expose ?? key; + }), + code = libs.map((lib) => { + return !DEPRECATED_LIBS.includes(lib) ? `require('${lib}');` : ''; + }).join('\n'); + + + context.on('console', consoleSpy); + context.execute(code, function (err) { + if (err) { + return done(err); + } + + expect(consoleSpy).to.not.be.called; + done(); + }); + }); +}); diff --git a/test/unit/sandbox-libraries/legacy.test.js b/test/unit/sandbox-libraries/legacy.test.js index bd5870a9..1476c220 100644 --- a/test/unit/sandbox-libraries/legacy.test.js +++ b/test/unit/sandbox-libraries/legacy.test.js @@ -55,7 +55,7 @@ describe('sandbox library - legacy', function () { context.on('console', consoleSpy); context.execute(` - CryptoJS.AES.encrypt('my message', 'secret key 123') + cheerio.load('foo'); `, function (err) { if (err) { return done(err); @@ -64,7 +64,7 @@ describe('sandbox library - legacy', function () { expect(consoleSpy).to.be.calledOnce; expect(consoleSpy.firstCall.args[1]).to.equal('warn'); expect(consoleSpy.firstCall.args[2]) - .to.equal('Using "CryptoJS" is deprecated. Use "require(\'crypto-js\')" instead.'); + .to.equal('Using "cheerio" is deprecated. Use "require(\'cheerio\')" instead.'); done(); }); }); diff --git a/types/sandbox/prerequest.d.ts b/types/sandbox/prerequest.d.ts index b95273f0..44fc9391 100644 --- a/types/sandbox/prerequest.d.ts +++ b/types/sandbox/prerequest.d.ts @@ -55,17 +55,17 @@ declare var iteration; declare var _; /** - * @deprecated Use require('crypto-js') instead + * @deprecated Use global "crypto" object instead */ declare var CryptoJS; /** - * @deprecated Use require('atob') instead + * @deprecated Use global "atob" function instead */ declare var atob; /** - * @deprecated Use require('btoa') instead + * @deprecated Use global "btoa" function instead */ declare var btoa; @@ -80,7 +80,7 @@ declare var tv4; declare var xml2Json; /** - * @deprecated Use require('backbone') instead + * @deprecated */ declare var Backbone; diff --git a/types/sandbox/test.d.ts b/types/sandbox/test.d.ts index 512296d2..64d89d9d 100644 --- a/types/sandbox/test.d.ts +++ b/types/sandbox/test.d.ts @@ -85,17 +85,17 @@ declare var iteration; declare var _; /** - * @deprecated Use require('crypto-js') instead + * @deprecated Use global "crypto" object instead */ declare var CryptoJS; /** - * @deprecated Use require('atob') instead + * @deprecated Use global "atob" function instead */ declare var atob; /** - * @deprecated Use require('btoa') instead + * @deprecated Use global "btoa" function instead */ declare var btoa; @@ -110,7 +110,7 @@ declare var tv4; declare var xml2Json; /** - * @deprecated Use require('backbone') instead + * @deprecated */ declare var Backbone;