From 1553e617c409f844c2a124c40203072e64e9313f Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Thu, 29 Aug 2024 14:23:54 +0530 Subject: [PATCH 01/12] Add support for configuring module resolver based on environment --- CHANGELOG.yaml | 4 ++++ lib/bundle/index.js | 28 +++++++++++++++++++++++++--- npm/cache.js | 4 +++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 617c6a39..b471bb2c 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -1,3 +1,7 @@ +unreleased: + chores: + - Add support for configuring module resolver based on environment + 5.1.1: date: 2024-08-01 fixed bugs: diff --git a/lib/bundle/index.js b/lib/bundle/index.js index 6a289a3b..7a2088ca 100644 --- a/lib/bundle/index.js +++ b/lib/bundle/index.js @@ -57,11 +57,18 @@ class Bundle { */ this.compress = options.compress; + this.preferBrowserResolver = options.preferBrowserResolver; + // process any list of modules externally required and also accommodate the use of built-ins if needed _.forEach(options.require, (options, resolve) => { // allow resolution override where the required module is resolved // from a different name than the one provided in options - options.resolve && (resolve = options.resolve); + if (this.preferBrowserResolver && options.resolveBrowser) { + resolve = options.resolveBrowser; + } + else if (options.resolve) { + resolve = options.resolve; + } // set the name using which the module is exported to the one marked as the module name (only in case when // one is not explicitly provided in options.) @@ -88,10 +95,25 @@ class Bundle { this.bundler.bundle((err, bundle) => { if (err) { return done(err); } + // Expose only the required node built-ins to be used in vendor modules + // These will be cleared out by sandbox when the bundle is loaded + const safeExposeBuiltIns = ` + if (typeof require === 'function') { + globalThis._nodeRequires = { + buffer: require('buffer') + }; + + // prevent access to node's require function + require = null; + } + `, + + bundleString = safeExposeBuiltIns + bundle.toString(); + // bail out if compression is disabled - if (!this.compress) { return done(null, bundle.toString()); } + if (!this.compress) { return done(null, bundleString); } - minify(bundle.toString(), { + minify(bundleString, { compress: { drop_console: true // discard calls to console.* functions }, diff --git a/npm/cache.js b/npm/cache.js index c0ad9ffe..a4b58c8c 100755 --- a/npm/cache.js +++ b/npm/cache.js @@ -21,7 +21,7 @@ function createBundle (options, file, done) { // @note: we are appending "require=null;" here to avoid access to // node's require function when running sandbox in worker_threads. // This does not affect the require function injected by browserify. - fs.writeFile(file, `module.exports=c=>c(null,${JSON.stringify('require=null;' + codeString)})`, next); + fs.writeFile(file, `module.exports=c=>c(null,${JSON.stringify(codeString)})`, next); }, function (next) { @@ -48,10 +48,12 @@ module.exports = function (exit) { async.parallel([ async.apply(createBundle, _.merge({ compress: true, + preferBrowserResolver: false, bundler: { browserField: false } }, options), './.cache/bootcode.js'), async.apply(createBundle, _.merge({ compress: true, + preferBrowserResolver: true, bundler: { browserField: true } }, options), './.cache/bootcode.browser.js') ], function (err) { From 37ed81610ddb5004e59d2827effd9f226d2f8ac3 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Thu, 29 Aug 2024 18:43:02 +0530 Subject: [PATCH 02/12] Use native Buffer whenever available --- CHANGELOG.yaml | 2 + lib/environment.js | 7 +- lib/sandbox/index.js | 7 ++ lib/vendor/buffer/buffer.js | 57 +++++++++ lib/vendor/buffer/index.browser.js | 9 ++ lib/vendor/buffer/index.js | 9 ++ test/unit/sandbox-libraries/buffer.test.js | 127 ++++++++++++++++++++- 7 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 lib/vendor/buffer/buffer.js create mode 100644 lib/vendor/buffer/index.browser.js create mode 100644 lib/vendor/buffer/index.js diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index b471bb2c..04bbb424 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -1,6 +1,8 @@ unreleased: chores: - Add support for configuring module resolver based on environment + new features: + - Enhanced performance when operating on buffers in Node environment 5.1.1: date: 2024-08-01 diff --git a/lib/environment.js b/lib/environment.js index add774ff..756937ed 100644 --- a/lib/environment.js +++ b/lib/environment.js @@ -11,7 +11,12 @@ module.exports = { util: { preferBuiltin: true, glob: true }, stream: { preferBuiltin: true, glob: true }, string_decoder: { preferBuiltin: true, glob: true }, - buffer: { resolve: 'buffer/index.js', expose: 'buffer', glob: true }, + buffer: { + resolve: '../vendor/buffer/index.js', + resolveBrowser: '../vendor/buffer/index.browser.js', + expose: 'buffer', + glob: true + }, url: { preferBuiltin: true, glob: true }, punycode: { preferBuiltin: true, glob: true }, querystring: { preferBuiltin: true, glob: true }, diff --git a/lib/sandbox/index.js b/lib/sandbox/index.js index cde7c047..fa152b21 100644 --- a/lib/sandbox/index.js +++ b/lib/sandbox/index.js @@ -22,6 +22,13 @@ // Setup Timerz before we delete the global timers require('./timers'); +// Require buffer to make sure it's available in the sandbox +// Browserify statically analyses the usage of buffers and only +// injects Buffer into the scope if it's used. `Buffer` injected +// by browserify is part of the functional scope and does not get +// deleted when we mutate the global scope below. +require('buffer'); + // Although we execute the user code in a well-defined scope using the uniscope // module but still to cutoff the reference to the globally available properties // we sanitize the global scope by deleting the forbidden properties in this UVM diff --git a/lib/vendor/buffer/buffer.js b/lib/vendor/buffer/buffer.js new file mode 100644 index 00000000..bbe05078 --- /dev/null +++ b/lib/vendor/buffer/buffer.js @@ -0,0 +1,57 @@ +function SpecificBuffer (_Buffer) { + const Buffer = function () { + if (typeof arguments[0] === 'number') { + return _Buffer.alloc(...arguments); + } + + return _Buffer.from(...arguments); + } + + Buffer.poolSize = _Buffer.poolSize; + + Object.defineProperty(Buffer, Symbol.hasInstance, { + value: function (instance) { + return instance instanceof _Buffer; + } + }); + + Buffer.isBuffer = function () { + return _Buffer.isBuffer(...arguments); + } + + Buffer.alloc = function () { + return _Buffer.alloc(...arguments); + } + + Buffer.allocUnsafe = function () { + return _Buffer.allocUnsafe(...arguments); + } + + Buffer.allocUnsafeSlow = function () { + return _Buffer.allocUnsafeSlow(...arguments); + } + + Buffer.from = function () { + return _Buffer.from(...arguments); + } + + Buffer.compare = function () { + return _Buffer.compare(...arguments); + } + + Buffer.isEncoding = function () { + return _Buffer.isEncoding(...arguments); + } + + Buffer.concat = function () { + return _Buffer.concat(...arguments); + } + + Buffer.byteLength = function () { + return _Buffer.byteLength(...arguments); + } + + return Buffer; +} + +module.exports = SpecificBuffer; diff --git a/lib/vendor/buffer/index.browser.js b/lib/vendor/buffer/index.browser.js new file mode 100644 index 00000000..96f052b5 --- /dev/null +++ b/lib/vendor/buffer/index.browser.js @@ -0,0 +1,9 @@ +const SpecificBuffer = require('./buffer'); +const buffer = require('buffer/'); + +module.exports = { + Buffer: SpecificBuffer(buffer.Buffer), + SlowBuffer: buffer.SlowBuffer, + INSPECT_MAX_BYTES: buffer.INSPECT_MAX_BYTES, + kMaxLength: buffer.kMaxLength +} diff --git a/lib/vendor/buffer/index.js b/lib/vendor/buffer/index.js new file mode 100644 index 00000000..eed3ce6e --- /dev/null +++ b/lib/vendor/buffer/index.js @@ -0,0 +1,9 @@ +const SpecificBuffer = require('./buffer'); +const buffer = globalThis._nodeRequires.buffer; + +module.exports = { + Buffer: SpecificBuffer(globalThis.Buffer), + SlowBuffer: buffer.SlowBuffer, + INSPECT_MAX_BYTES: buffer.INSPECT_MAX_BYTES, + kMaxLength: buffer.kMaxLength +} diff --git a/test/unit/sandbox-libraries/buffer.test.js b/test/unit/sandbox-libraries/buffer.test.js index 6ee0baa7..07599d47 100644 --- a/test/unit/sandbox-libraries/buffer.test.js +++ b/test/unit/sandbox-libraries/buffer.test.js @@ -114,12 +114,137 @@ describe('sandbox library - buffer', function () { context.execute(` var assert = require('assert'), buf1 = new Buffer('buffer'), - buf2 = new Buffer(buf1); + buf2 = new Buffer(buf1), + buf3 = Buffer(1); buf1[0] = 0x61; + buf3[0] = 0x61; assert.strictEqual(buf1.toString(), 'auffer'); assert.strictEqual(buf2.toString(), 'buffer'); + assert.strictEqual(buf3.toString(), 'a'); `, done); }); + + it('should be able to detect Buffer instances using isBuffer', function (done) { + context.execute(` + const assert = require('assert'), + + bufUsingFrom = Buffer.from('test'), + bufUsingNew = new Buffer('test'), + buf = Buffer(1); + + assert.strictEqual(Buffer.isBuffer(bufUsingFrom), true); + assert.strictEqual(Buffer.isBuffer(bufUsingNew), true); + assert.strictEqual(Buffer.isBuffer(buf), true); + `, done); + }); + + it('should be able to detect Buffer instances using Symbol.hasInstance', function (done) { + context.execute(` + const assert = require('assert'), + + bufUsingFrom = Buffer.from('test'), + bufUsingNew = new Buffer('test'); + buf = Buffer(1); + + assert.strictEqual(bufUsingFrom instanceof Buffer, true); + assert.strictEqual(bufUsingNew instanceof Buffer, true); + assert.strictEqual(buf instanceof Buffer, true); + `, done); + }); + + it('should be able to convert large buffer to string', function (done) { + // For native buffer, the max string length is ~512MB + // For browser buffer, the max string length is ~100MB + const SIZE = (typeof window === 'undefined' ? 511 : 100) * 1024 * 1024; + + context.execute(` + const assert = require('assert'), + buf = Buffer.alloc(${SIZE}, 'a'); + + assert.strictEqual(buf.toString().length, ${SIZE}); + `, done); + }); + + it('should implement Buffer.compare', function (done) { + context.execute(` + const assert = require('assert'), + + buf1 = Buffer.from('abc'), + buf2 = Buffer.from('abc'), + buf3 = Buffer.from('abd'); + + assert.strictEqual(Buffer.compare(buf1, buf2), 0); + assert.strictEqual(Buffer.compare(buf1, buf3), -1); + assert.strictEqual(Buffer.compare(buf3, buf1), 1); + `, done); + }); + + it('should implement Buffer.byteLength', function (done) { + context.execute(` + const assert = require('assert'), + buf = Buffer.from('abc'); + + assert.strictEqual(Buffer.byteLength(buf), 3); + `, done); + }); + + it('should implement Buffer.concat', function (done) { + context.execute(` + const assert = require('assert'), + + buf1 = Buffer.from('abc'), + buf2 = Buffer.from('def'); + + assert.strictEqual(Buffer.concat([buf1, buf2]).toString(), 'abcdef'); + `, done); + }); + + it('should implement Buffer.isEncoding', function (done) { + context.execute(` + const assert = require('assert'); + + assert.strictEqual(Buffer.isEncoding('utf8'), true); + assert.strictEqual(Buffer.isEncoding('hex'), true); + assert.strictEqual(Buffer.isEncoding('ascii'), true); + assert.strictEqual(Buffer.isEncoding('utf16le'), true); + assert.strictEqual(Buffer.isEncoding('ucs2'), true); + assert.strictEqual(Buffer.isEncoding('base64'), true); + assert.strictEqual(Buffer.isEncoding('binary'), true); + + assert.strictEqual(Buffer.isEncoding('utf-8'), true); + assert.strictEqual(Buffer.isEncoding('utf/8'), false); + assert.strictEqual(Buffer.isEncoding(''), false); + `, done); + }); + + it('should expose Buffer.poolSize', function (done) { + context.execute(` + const assert = require('assert'); + + assert.strictEqual(typeof Buffer.poolSize, 'number'); + `, done); + }); + + it('should expose SlowBuffer', function (done) { + context.execute(` + const assert = require('assert'), + buffer = require('buffer'); + + const buf = new buffer.SlowBuffer(10); + assert.strictEqual(buf.length, 10); + `, done); + }); + + it('should expose constants', function (done) { + context.execute(` + const assert = require('assert'), + buffer = require('buffer'); + + assert.strictEqual(typeof buffer.kMaxLength, 'number'); + assert.strictEqual(typeof buffer.INSPECT_MAX_BYTES, 'number'); + + `, done); + }); }); From 4f4d73e728e845df5f0ccd167f253ab04428206f Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Thu, 29 Aug 2024 19:14:03 +0530 Subject: [PATCH 03/12] Add test for checking bootcode dependencies on browser --- test/system/bootcode-dependencies.test.js | 389 ++++++++++++++-------- 1 file changed, 259 insertions(+), 130 deletions(-) diff --git a/test/system/bootcode-dependencies.test.js b/test/system/bootcode-dependencies.test.js index abbc84a1..2c5b93d3 100644 --- a/test/system/bootcode-dependencies.test.js +++ b/test/system/bootcode-dependencies.test.js @@ -1,139 +1,268 @@ -describe('bootcode dependencies', function () { - this.timeout(60 * 1000); +const expect = require('chai').expect, + env = require('../../lib/environment'), + Bundle = require('../../lib/bundle'), - var expect = require('chai').expect, - env = require('../../lib/environment'), - Bundle = require('../../lib/bundle'), - currentDependencies; + expectedDependenciesBrowser = [ + '@faker-js/faker', + '@postman/tough-cookie', + 'ajv', + 'array-filter', + 'assert', + 'assertion-error', + 'atob', + 'available-typed-arrays', + 'backbone', + 'base64-js', + 'boolbase', + 'browserify', + 'btoa', + 'buffer', + 'call-bind', + 'chai', + 'chai-postman', + 'charset', + 'check-error', + 'cheerio', + 'core-util-is', + 'crypto-js', + 'css-select', + 'css-what', + 'csv-parse', + 'deep-eql', + 'define-properties', + 'dom-serializer', + 'domelementtype', + 'domhandler', + 'domutils', + 'entities', + 'es-abstract', + 'es6-object-assign', + 'events', + 'fast-deep-equal', + 'fast-json-stable-stringify', + 'file-type', + 'foreach', + 'function-bind', + 'get-func-name', + 'get-intrinsic', + 'has', + 'has-symbols', + 'htmlparser2', + 'http-reasons', + 'iconv-lite', + 'ieee754', + 'inherits', + 'is-arguments', + 'is-buffer', + 'is-generator-function', + 'is-nan', + 'is-typed-array', + 'isarray', + 'jquery', + 'json-schema-traverse', + 'liquid-json', + 'lodash', + 'lodash.assignin', + 'lodash.bind', + 'lodash.defaults', + 'lodash.filter', + 'lodash.flatten', + 'lodash.foreach', + 'lodash.map', + 'lodash.merge', + 'lodash.pick', + 'lodash.reduce', + 'lodash.reject', + 'lodash.some', + 'lodash3', + 'loupe', + 'mime-db', + 'mime-format', + 'mime-types', + 'moment', + 'nth-check', + 'object-is', + 'object-keys', + 'os-browserify', + 'path-browserify', + 'pathval', + 'postman-collection', + 'postman-sandbox', + 'postman-url-encoder', + 'process', + 'process-nextick-args', + 'psl', + 'punycode', + 'querystring-es3', + 'querystringify', + 'readable-stream', + 'requires-port', + 'safe-buffer', + 'safer-buffer', + 'sax', + 'semver', + 'stream-browserify', + 'string_decoder', + 'teleport-javascript', + 'timers-browserify', + 'tv4', + 'type-detect', + 'underscore', + 'uniscope', + 'universalify', + 'uri-js', + 'url', + 'url-parse', + 'util', + 'util-deprecate', + 'uuid', + 'which-typed-array', + 'xml2js', + 'xmlbuilder' + ], + expectedDependenciesNode = [ + '@faker-js/faker', + '@postman/tough-cookie', + 'ajv', + 'array-filter', + 'assert', + 'assertion-error', + 'atob', + 'available-typed-arrays', + 'backbone', + 'boolbase', + 'browserify', + 'btoa', + 'call-bind', + 'chai', + 'chai-postman', + 'charset', + 'check-error', + 'cheerio', + 'core-util-is', + 'crypto-js', + 'css-select', + 'css-what', + 'csv-parse', + 'deep-eql', + 'define-properties', + 'dom-serializer', + 'domelementtype', + 'domhandler', + 'domutils', + 'entities', + 'es-abstract', + 'es6-object-assign', + 'events', + 'fast-deep-equal', + 'fast-json-stable-stringify', + 'file-type', + 'foreach', + 'function-bind', + 'get-func-name', + 'get-intrinsic', + 'has', + 'has-symbols', + 'htmlparser2', + 'http-reasons', + 'iconv-lite', + 'inherits', + 'is-arguments', + 'is-buffer', + 'is-generator-function', + 'is-nan', + 'is-typed-array', + 'isarray', + 'jquery', + 'json-schema-traverse', + 'liquid-json', + 'lodash', + 'lodash.assignin', + 'lodash.bind', + 'lodash.defaults', + 'lodash.filter', + 'lodash.flatten', + 'lodash.foreach', + 'lodash.map', + 'lodash.merge', + 'lodash.pick', + 'lodash.reduce', + 'lodash.reject', + 'lodash.some', + 'lodash3', + 'loupe', + 'mime-db', + 'mime-format', + 'mime-types', + 'moment', + 'nth-check', + 'object-is', + 'object-keys', + 'os-browserify', + 'path-browserify', + 'pathval', + 'postman-collection', + 'postman-sandbox', + 'postman-url-encoder', + 'process', + 'process-nextick-args', + 'psl', + 'punycode', + 'querystring-es3', + 'querystringify', + 'readable-stream', + 'requires-port', + 'safe-buffer', + 'safer-buffer', + 'sax', + 'semver', + 'stream-browserify', + 'string_decoder', + 'teleport-javascript', + 'timers-browserify', + 'tv4', + 'type-detect', + 'underscore', + 'uniscope', + 'universalify', + 'uri-js', + 'url', + 'url-parse', + 'util', + 'util-deprecate', + 'uuid', + 'which-typed-array', + 'xml2js', + 'xmlbuilder' + ]; - before(function (done) { - process && process.stdout.write(' -- building dependencies, please wait... '); - Bundle.load(env).listDependencies(function (err, dependencies) { - currentDependencies = dependencies; +function getCurrentDependencies (isBrowser, cb) { + Bundle.load({ ...env, preferBrowserResolver: isBrowser }) + .listDependencies(function (err, dependencies) { console.info(err ? 'failed' : 'done'); - return done(err); + return cb(err, dependencies); + }); +} + +describe('bootcode dependencies', function () { + this.timeout(60 * 1000); + + it('should not change on Node', function (done) { + getCurrentDependencies(false, function (err, currentDependencies) { + if (err) { return done(err); } + + expect(currentDependencies).to.eql(expectedDependenciesNode); + done(); }); }); - it('should not change', function () { - expect(currentDependencies).to.eql([ - '@faker-js/faker', - '@postman/tough-cookie', - 'ajv', - 'array-filter', - 'assert', - 'assertion-error', - 'atob', - 'available-typed-arrays', - 'backbone', - 'base64-js', - 'boolbase', - 'browserify', - 'btoa', - 'buffer', - 'call-bind', - 'chai', - 'chai-postman', - 'charset', - 'check-error', - 'cheerio', - 'core-util-is', - 'crypto-js', - 'css-select', - 'css-what', - 'csv-parse', - 'deep-eql', - 'define-properties', - 'dom-serializer', - 'domelementtype', - 'domhandler', - 'domutils', - 'entities', - 'es-abstract', - 'es6-object-assign', - 'events', - 'fast-deep-equal', - 'fast-json-stable-stringify', - 'file-type', - 'foreach', - 'function-bind', - 'get-func-name', - 'get-intrinsic', - 'has', - 'has-symbols', - 'htmlparser2', - 'http-reasons', - 'iconv-lite', - 'ieee754', - 'inherits', - 'is-arguments', - 'is-buffer', - 'is-generator-function', - 'is-nan', - 'is-typed-array', - 'isarray', - 'jquery', - 'json-schema-traverse', - 'liquid-json', - 'lodash', - 'lodash.assignin', - 'lodash.bind', - 'lodash.defaults', - 'lodash.filter', - 'lodash.flatten', - 'lodash.foreach', - 'lodash.map', - 'lodash.merge', - 'lodash.pick', - 'lodash.reduce', - 'lodash.reject', - 'lodash.some', - 'lodash3', - 'loupe', - 'mime-db', - 'mime-format', - 'mime-types', - 'moment', - 'nth-check', - 'object-is', - 'object-keys', - 'os-browserify', - 'path-browserify', - 'pathval', - 'postman-collection', - 'postman-sandbox', - 'postman-url-encoder', - 'process', - 'process-nextick-args', - 'psl', - 'punycode', - 'querystring-es3', - 'querystringify', - 'readable-stream', - 'requires-port', - 'safe-buffer', - 'safer-buffer', - 'sax', - 'semver', - 'stream-browserify', - 'string_decoder', - 'teleport-javascript', - 'timers-browserify', - 'tv4', - 'type-detect', - 'underscore', - 'uniscope', - 'universalify', - 'uri-js', - 'url', - 'url-parse', - 'util', - 'util-deprecate', - 'uuid', - 'which-typed-array', - 'xml2js', - 'xmlbuilder' - ]); + it('should not change on Browser', function (done) { + getCurrentDependencies(true, function (err, currentDependencies) { + if (err) { return done(err); } + + expect(currentDependencies).to.eql(expectedDependenciesBrowser); + done(); + }); }); }); From c76fa3daa18414358c9db3fbc318c1eb7f50161e Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Mon, 23 Sep 2024 22:32:32 +0530 Subject: [PATCH 04/12] Update CHANGELOG.yaml --- CHANGELOG.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 04bbb424..88bc26d6 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -1,8 +1,8 @@ unreleased: chores: - - Add support for configuring module resolver based on environment + - GH-1032 Add support for configuring module resolver based on environment new features: - - Enhanced performance when operating on buffers in Node environment + - GH-1032 Enhanced performance when operating on buffers in Node environment 5.1.1: date: 2024-08-01 From 925106399bd9e4c6ee78b871fb65b6033bdb56df Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Wed, 25 Sep 2024 01:03:44 +0530 Subject: [PATCH 05/12] Unify buffer module --- lib/vendor/buffer/buffer.js | 61 ++++------------------------ lib/vendor/buffer/index.browser.js | 13 +++--- lib/vendor/buffer/index.js | 11 +++-- lib/vendor/buffer/specific-buffer.js | 57 ++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 67 deletions(-) create mode 100644 lib/vendor/buffer/specific-buffer.js diff --git a/lib/vendor/buffer/buffer.js b/lib/vendor/buffer/buffer.js index bbe05078..41ea6da8 100644 --- a/lib/vendor/buffer/buffer.js +++ b/lib/vendor/buffer/buffer.js @@ -1,57 +1,10 @@ -function SpecificBuffer (_Buffer) { - const Buffer = function () { - if (typeof arguments[0] === 'number') { - return _Buffer.alloc(...arguments); - } - - return _Buffer.from(...arguments); - } - - Buffer.poolSize = _Buffer.poolSize; - - Object.defineProperty(Buffer, Symbol.hasInstance, { - value: function (instance) { - return instance instanceof _Buffer; - } - }); - - Buffer.isBuffer = function () { - return _Buffer.isBuffer(...arguments); - } - - Buffer.alloc = function () { - return _Buffer.alloc(...arguments); - } - - Buffer.allocUnsafe = function () { - return _Buffer.allocUnsafe(...arguments); - } - - Buffer.allocUnsafeSlow = function () { - return _Buffer.allocUnsafeSlow(...arguments); +function getBufferModule (buffer) { + return { + Buffer: buffer.Buffer, + SlowBuffer: buffer.SlowBuffer, + INSPECT_MAX_BYTES: buffer.INSPECT_MAX_BYTES, + kMaxLength: buffer.kMaxLength } - - Buffer.from = function () { - return _Buffer.from(...arguments); - } - - Buffer.compare = function () { - return _Buffer.compare(...arguments); - } - - Buffer.isEncoding = function () { - return _Buffer.isEncoding(...arguments); - } - - Buffer.concat = function () { - return _Buffer.concat(...arguments); - } - - Buffer.byteLength = function () { - return _Buffer.byteLength(...arguments); - } - - return Buffer; } -module.exports = SpecificBuffer; +module.exports = getBufferModule; diff --git a/lib/vendor/buffer/index.browser.js b/lib/vendor/buffer/index.browser.js index 96f052b5..f07c967a 100644 --- a/lib/vendor/buffer/index.browser.js +++ b/lib/vendor/buffer/index.browser.js @@ -1,9 +1,8 @@ -const SpecificBuffer = require('./buffer'); +const getBufferModule = require('./buffer'); +const SpecificBuffer = require('./specific-buffer'); const buffer = require('buffer/'); -module.exports = { - Buffer: SpecificBuffer(buffer.Buffer), - SlowBuffer: buffer.SlowBuffer, - INSPECT_MAX_BYTES: buffer.INSPECT_MAX_BYTES, - kMaxLength: buffer.kMaxLength -} +module.exports = getBufferModule({ + ...buffer, + Buffer: SpecificBuffer(buffer.Buffer) +}) diff --git a/lib/vendor/buffer/index.js b/lib/vendor/buffer/index.js index eed3ce6e..9accc807 100644 --- a/lib/vendor/buffer/index.js +++ b/lib/vendor/buffer/index.js @@ -1,9 +1,8 @@ -const SpecificBuffer = require('./buffer'); +const getBufferModule = require('./buffer'); +const SpecificBuffer = require('./specific-buffer'); const buffer = globalThis._nodeRequires.buffer; -module.exports = { +module.exports = getBufferModule({ + ...buffer, Buffer: SpecificBuffer(globalThis.Buffer), - SlowBuffer: buffer.SlowBuffer, - INSPECT_MAX_BYTES: buffer.INSPECT_MAX_BYTES, - kMaxLength: buffer.kMaxLength -} +}); diff --git a/lib/vendor/buffer/specific-buffer.js b/lib/vendor/buffer/specific-buffer.js new file mode 100644 index 00000000..d2968066 --- /dev/null +++ b/lib/vendor/buffer/specific-buffer.js @@ -0,0 +1,57 @@ +function SpecificBuffer (_Buffer) { + const Buffer = function () { + if (typeof arguments[0] === 'number') { + return _Buffer.alloc(...arguments); + } + + return _Buffer.from(...arguments); + } + + Buffer.poolSize = _Buffer.poolSize; + + Object.defineProperty(Buffer, Symbol.hasInstance, { + value: function (instance) { + return instance instanceof _Buffer; + } + }); + + Buffer.isBuffer = function () { + return _Buffer.isBuffer(...arguments); + }; + + Buffer.alloc = function () { + return _Buffer.alloc(...arguments); + }; + + Buffer.allocUnsafe = function () { + return _Buffer.allocUnsafe(...arguments); + }; + + Buffer.allocUnsafeSlow = function () { + return _Buffer.allocUnsafeSlow(...arguments); + }; + + Buffer.from = function () { + return _Buffer.from(...arguments); + }; + + Buffer.compare = function () { + return _Buffer.compare(...arguments); + }; + + Buffer.isEncoding = function () { + return _Buffer.isEncoding(...arguments); + }; + + Buffer.concat = function () { + return _Buffer.concat(...arguments); + }; + + Buffer.byteLength = function () { + return _Buffer.byteLength(...arguments); + }; + + return Buffer; +} + +module.exports = SpecificBuffer; From 6ac754060670cc0aedb6cb29c24078a139ef7637 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Thu, 29 Aug 2024 14:50:21 +0530 Subject: [PATCH 06/12] Add missing buffer APIs --- CHANGELOG.yaml | 1 + lib/vendor/buffer/buffer.js | 14 ++++++++++++- lib/vendor/buffer/index.browser.js | 15 ++++++++++++-- lib/vendor/buffer/specific-buffer.js | 8 ++++++++ test/unit/sandbox-libraries/buffer.test.js | 23 ++++++++++++++++++++++ 5 files changed, 58 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 88bc26d6..7d0b9bd8 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -3,6 +3,7 @@ unreleased: - GH-1032 Add support for configuring module resolver based on environment new features: - GH-1032 Enhanced performance when operating on buffers in Node environment + - GH-1035 Added missing buffer APIs to expose a uniform interface across environments 5.1.1: date: 2024-08-01 diff --git a/lib/vendor/buffer/buffer.js b/lib/vendor/buffer/buffer.js index 41ea6da8..ee4306cf 100644 --- a/lib/vendor/buffer/buffer.js +++ b/lib/vendor/buffer/buffer.js @@ -1,9 +1,21 @@ +const NOT_IMPLEMENTED = function () { + throw new Error('Not implemented'); +}; + function getBufferModule (buffer) { return { Buffer: buffer.Buffer, SlowBuffer: buffer.SlowBuffer, INSPECT_MAX_BYTES: buffer.INSPECT_MAX_BYTES, - kMaxLength: buffer.kMaxLength + kMaxLength: buffer.kMaxLength, + kStringMaxLength: buffer.kStringMaxLength, + constants: buffer.constants, + File: buffer.File, + Blob: buffer.Blob, + isAscii: NOT_IMPLEMENTED, + isUtf8: NOT_IMPLEMENTED, + resolveObjectURL: NOT_IMPLEMENTED, + transcode: NOT_IMPLEMENTED } } diff --git a/lib/vendor/buffer/index.browser.js b/lib/vendor/buffer/index.browser.js index f07c967a..0bddc8d7 100644 --- a/lib/vendor/buffer/index.browser.js +++ b/lib/vendor/buffer/index.browser.js @@ -2,7 +2,18 @@ const getBufferModule = require('./buffer'); const SpecificBuffer = require('./specific-buffer'); const buffer = require('buffer/'); +// Using 32-bit implementation value from Node +// https://github.com/nodejs/node/blob/main/deps/v8/include/v8-primitive.h#L126 +const K_STRING_MAX_LENGTH = (1 << 28) - 16; + module.exports = getBufferModule({ ...buffer, - Buffer: SpecificBuffer(buffer.Buffer) -}) + Buffer: SpecificBuffer(buffer.Buffer), + kStringMaxLength: K_STRING_MAX_LENGTH, + constants: { + MAX_LENGTH: buffer.kMaxLength, + MAX_STRING_LENGTH: K_STRING_MAX_LENGTH + }, + File: File, + Blob: Blob +}); diff --git a/lib/vendor/buffer/specific-buffer.js b/lib/vendor/buffer/specific-buffer.js index d2968066..13202589 100644 --- a/lib/vendor/buffer/specific-buffer.js +++ b/lib/vendor/buffer/specific-buffer.js @@ -1,3 +1,7 @@ +const NOT_IMPLEMENTED = function () { + throw new Error('Not implemented'); +}; + function SpecificBuffer (_Buffer) { const Buffer = function () { if (typeof arguments[0] === 'number') { @@ -51,6 +55,10 @@ function SpecificBuffer (_Buffer) { return _Buffer.byteLength(...arguments); }; + Buffer.copyBytesFrom = NOT_IMPLEMENTED; + + Buffer.of = NOT_IMPLEMENTED; + return Buffer; } diff --git a/test/unit/sandbox-libraries/buffer.test.js b/test/unit/sandbox-libraries/buffer.test.js index 07599d47..2f4d08eb 100644 --- a/test/unit/sandbox-libraries/buffer.test.js +++ b/test/unit/sandbox-libraries/buffer.test.js @@ -243,8 +243,31 @@ describe('sandbox library - buffer', function () { buffer = require('buffer'); assert.strictEqual(typeof buffer.kMaxLength, 'number'); + assert.strictEqual(typeof buffer.kStringMaxLength, 'number'); + assert.strictEqual(typeof buffer.constants.MAX_LENGTH, 'number'); + assert.strictEqual(typeof buffer.constants.MAX_STRING_LENGTH, 'number'); assert.strictEqual(typeof buffer.INSPECT_MAX_BYTES, 'number'); `, done); }); + + it('should expose File class', function (done) { + context.execute(` + const assert = require('assert'), + buffer = require('buffer'); + const lastModified = Date.now(); + const file = new buffer.File([], 'filename.txt', { type: 'text/plain', lastModified }); + assert.strictEqual(file.name, 'filename.txt'); + assert.strictEqual(file.lastModified, lastModified); + `, done); + }); + + it('should expose Blob class', function (done) { + context.execute(` + const assert = require('assert'), + buffer = require('buffer'); + const blob = new buffer.Blob(['hello world'], { type: 'text/plain' }); + assert.strictEqual(blob.size, 11); + `, done); + }); }); From 9a1acca8b6949422730e1588a21cc562d55491d9 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Wed, 25 Sep 2024 01:40:12 +0530 Subject: [PATCH 07/12] Expose `File` class globally --- CHANGELOG.yaml | 1 + lib/sandbox/execute-context.js | 2 ++ test/unit/sandbox-libraries/buffer.test.js | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 7d0b9bd8..92ef0b3a 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -4,6 +4,7 @@ unreleased: new features: - GH-1032 Enhanced performance when operating on buffers in Node environment - GH-1035 Added missing buffer APIs to expose a uniform interface across environments + - GH-1051 Exposed `File` globally 5.1.1: date: 2024-08-01 diff --git a/lib/sandbox/execute-context.js b/lib/sandbox/execute-context.js index 0932091c..f58e2490 100644 --- a/lib/sandbox/execute-context.js +++ b/lib/sandbox/execute-context.js @@ -25,6 +25,8 @@ module.exports = function (scope, code, execution, console, timers, pmapi, onAss // prepare the scope's environment variables scope.import({ Buffer: require('buffer').Buffer, + // TODO: Remove this once it is added to Uniscope (node>=v20) + File: require('buffer').File, // forward console console: console, // forward pm-api instance diff --git a/test/unit/sandbox-libraries/buffer.test.js b/test/unit/sandbox-libraries/buffer.test.js index 2f4d08eb..899bea1f 100644 --- a/test/unit/sandbox-libraries/buffer.test.js +++ b/test/unit/sandbox-libraries/buffer.test.js @@ -262,6 +262,14 @@ describe('sandbox library - buffer', function () { `, done); }); + it('should have same File implementation as global', function (done) { + context.execute(` + const assert = require('assert'), + bufferFile = require('buffer').File; + assert.strictEqual(File === bufferFile, true); + `, done); + }); + it('should expose Blob class', function (done) { context.execute(` const assert = require('assert'), @@ -270,4 +278,12 @@ describe('sandbox library - buffer', function () { assert.strictEqual(blob.size, 11); `, done); }); + + it('should have same Blob implementation as global', function (done) { + context.execute(` + const assert = require('assert'), + bufferBlob = require('buffer').Blob; + assert.strictEqual(Blob === bufferBlob, true); + `, done); + }); }); From 0c30e177e25d443a33b2f4ab7ed630b65019cc1a Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Wed, 25 Sep 2024 12:19:13 +0530 Subject: [PATCH 08/12] Remove comment from cache.js --- npm/cache.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/npm/cache.js b/npm/cache.js index a4b58c8c..1e5b93d7 100755 --- a/npm/cache.js +++ b/npm/cache.js @@ -18,9 +18,6 @@ function createBundle (options, file, done) { }, function (codeString, next) { - // @note: we are appending "require=null;" here to avoid access to - // node's require function when running sandbox in worker_threads. - // This does not affect the require function injected by browserify. fs.writeFile(file, `module.exports=c=>c(null,${JSON.stringify(codeString)})`, next); }, From 4505c79f775aabc26f0f4b7ea7a2a17603490169 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Wed, 25 Sep 2024 01:18:28 +0530 Subject: [PATCH 09/12] Use native atob and btoa --- CHANGELOG.yaml | 1 + lib/bundle/bundling-options.js | 7 ++- lib/environment.js | 4 +- lib/sandbox/postman-legacy-interface.js | 6 +-- lib/vendor/atob.js | 1 + lib/vendor/btoa.js | 1 + lib/vendor/buffer/buffer.js | 2 + lib/vendor/buffer/index.browser.js | 4 +- package-lock.json | 38 -------------- package.json | 2 - test/system/bootcode-dependencies.test.js | 4 -- test/system/repository.test.js | 2 +- test/unit/sandbox-libraries/legacy.test.js | 4 +- .../unit/sandbox-libraries/pm-require.test.js | 2 - test/unit/vendors/atob.test.js | 50 +++++++++++++++++++ test/unit/vendors/btoa.test.js | 50 +++++++++++++++++++ .../buffer.test.js | 35 ++++++++++++- 17 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 lib/vendor/atob.js create mode 100644 lib/vendor/btoa.js create mode 100644 test/unit/vendors/atob.test.js create mode 100644 test/unit/vendors/btoa.test.js rename test/unit/{sandbox-libraries => vendors}/buffer.test.js (88%) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 83b28a33..53a6398a 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -5,6 +5,7 @@ unreleased: - GH-1032 Enhanced performance when operating on buffers in Node environment - 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 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/bundle/bundling-options.js b/lib/bundle/bundling-options.js index 27b671be..4e8922b6 100644 --- a/lib/bundle/bundling-options.js +++ b/lib/bundle/bundling-options.js @@ -4,5 +4,10 @@ module.exports = { browserField: false, bare: true, builtins: false, - commondir: true + commondir: true, + + // This is to prevent bundling errors for modules that + // are not in node_modules but are instead imported from a + // vendor and should be exposed via `require` inside the bundle. + ignoreMissing: true }; diff --git a/lib/environment.js b/lib/environment.js index 756937ed..af9a82ba 100644 --- a/lib/environment.js +++ b/lib/environment.js @@ -24,8 +24,8 @@ module.exports = { os: { preferBuiltin: true }, 'liquid-json': { expose: 'json', glob: true }, 'crypto-js': { glob: true }, - atob: { glob: true }, - btoa: { glob: true }, + atob: { resolve: '../vendor/atob.js', expose: 'atob', glob: true }, + btoa: { resolve: '../vendor/btoa.js', expose: 'btoa', glob: true }, ajv: { glob: true }, tv4: { glob: true }, xml2js: { glob: true }, diff --git a/lib/sandbox/postman-legacy-interface.js b/lib/sandbox/postman-legacy-interface.js index cf8f3d64..a3a7d98f 100644 --- a/lib/sandbox/postman-legacy-interface.js +++ b/lib/sandbox/postman-legacy-interface.js @@ -5,8 +5,6 @@ const _ = require('lodash'), JSON: require('liquid-json'), _: require('lodash3').noConflict(), CryptoJS: require('crypto-js'), - atob: require('atob'), - btoa: require('btoa'), tv4: require('tv4'), xml2Json: require('./xml2Json'), Backbone: require('backbone'), @@ -17,7 +15,7 @@ const _ = require('lodash'), 'tests', 'globals', 'environment', 'data', 'request', 'responseCookies', 'responseHeaders', 'responseTime', 'responseCode', 'responseBody', 'iteration', 'postman', // scope libraries - '_', 'CryptoJS', 'atob', 'btoa', 'tv4', 'xml2Json', 'Backbone', 'cheerio' + '_', 'CryptoJS', 'tv4', 'xml2Json', 'Backbone', 'cheerio' // 'JSON', // removing JSON from the list since it is a standard JS object ], @@ -35,8 +33,6 @@ const _ = require('lodash'), iteration: 'pm.info.iteration', _: 'require(\'lodash\')', CryptoJS: 'require(\'crypto-js\')', - atob: 'require(\'atob\')', - btoa: 'require(\'btoa\')', tv4: 'require(\'ajv\')', xml2Json: 'require(\'xml2js\')', Backbone: 'require(\'backbone\')', diff --git a/lib/vendor/atob.js b/lib/vendor/atob.js new file mode 100644 index 00000000..a179a1ca --- /dev/null +++ b/lib/vendor/atob.js @@ -0,0 +1 @@ +module.exports = require('buffer').atob; diff --git a/lib/vendor/btoa.js b/lib/vendor/btoa.js new file mode 100644 index 00000000..f0517f39 --- /dev/null +++ b/lib/vendor/btoa.js @@ -0,0 +1 @@ +module.exports = require('buffer').btoa; diff --git a/lib/vendor/buffer/buffer.js b/lib/vendor/buffer/buffer.js index ee4306cf..e17ecdac 100644 --- a/lib/vendor/buffer/buffer.js +++ b/lib/vendor/buffer/buffer.js @@ -12,6 +12,8 @@ function getBufferModule (buffer) { constants: buffer.constants, File: buffer.File, Blob: buffer.Blob, + atob: buffer.atob, + btoa: buffer.btoa, isAscii: NOT_IMPLEMENTED, isUtf8: NOT_IMPLEMENTED, resolveObjectURL: NOT_IMPLEMENTED, diff --git a/lib/vendor/buffer/index.browser.js b/lib/vendor/buffer/index.browser.js index 0bddc8d7..6a5b4ca4 100644 --- a/lib/vendor/buffer/index.browser.js +++ b/lib/vendor/buffer/index.browser.js @@ -15,5 +15,7 @@ module.exports = getBufferModule({ MAX_STRING_LENGTH: K_STRING_MAX_LENGTH }, File: File, - Blob: Blob + Blob: Blob, + atob: atob, + btoa: btoa }); diff --git a/package-lock.json b/package-lock.json index 4675e1f0..f769fd5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,10 +21,8 @@ "ajv": "6.12.5", "assert": "2.0.0", "async": "^3.2.6", - "atob": "2.1.2", "backbone": "1.6.0", "browserify": "^16.5.2", - "btoa": "1.2.1", "buffer": "6.0.3", "chai": "4.4.1", "chai-postman": "2.0.1", @@ -1591,18 +1589,6 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, "node_modules/available-typed-arrays": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", @@ -2002,18 +1988,6 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "node_modules/btoa": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", - "dev": true, - "bin": { - "btoa": "bin/btoa.js" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -10159,12 +10133,6 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "available-typed-arrays": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", @@ -10526,12 +10494,6 @@ "pako": "~1.0.5" } }, - "btoa": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", - "dev": true - }, "buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", diff --git a/package.json b/package.json index 72e15854..07a5e294 100644 --- a/package.json +++ b/package.json @@ -54,10 +54,8 @@ "ajv": "6.12.5", "assert": "2.0.0", "async": "^3.2.6", - "atob": "2.1.2", "backbone": "1.6.0", "browserify": "^16.5.2", - "btoa": "1.2.1", "buffer": "6.0.3", "chai": "4.4.1", "chai-postman": "2.0.1", diff --git a/test/system/bootcode-dependencies.test.js b/test/system/bootcode-dependencies.test.js index 2c5b93d3..d397e894 100644 --- a/test/system/bootcode-dependencies.test.js +++ b/test/system/bootcode-dependencies.test.js @@ -9,13 +9,11 @@ const expect = require('chai').expect, 'array-filter', 'assert', 'assertion-error', - 'atob', 'available-typed-arrays', 'backbone', 'base64-js', 'boolbase', 'browserify', - 'btoa', 'buffer', 'call-bind', 'chai', @@ -127,12 +125,10 @@ const expect = require('chai').expect, 'array-filter', 'assert', 'assertion-error', - 'atob', 'available-typed-arrays', 'backbone', 'boolbase', 'browserify', - 'btoa', 'call-bind', 'chai', 'chai-postman', diff --git a/test/system/repository.test.js b/test/system/repository.test.js index 97a96543..9ff5d00b 100644 --- a/test/system/repository.test.js +++ b/test/system/repository.test.js @@ -75,7 +75,7 @@ describe('project repository', function () { it('should point to specific package version for bundled packages; (*, ^, ~) not expected', function () { [ - 'ajv', 'assert', 'atob', 'backbone', 'btoa', 'buffer', 'chai', + 'ajv', 'assert', 'backbone', 'buffer', 'chai', 'chai-postman', 'cheerio', 'crypto-js', 'csv-parse', 'liquid-json', 'lodash3', 'moment', '@postman/tough-cookie', 'tv4', 'uniscope', 'xml2js' diff --git a/test/unit/sandbox-libraries/legacy.test.js b/test/unit/sandbox-libraries/legacy.test.js index 3b3c5b3f..bd5870a9 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(` - atob('a'); + CryptoJS.AES.encrypt('my message', 'secret key 123') `, 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 "atob" is deprecated. Use "require(\'atob\')" instead.'); + .to.equal('Using "CryptoJS" is deprecated. Use "require(\'crypto-js\')" instead.'); done(); }); }); diff --git a/test/unit/sandbox-libraries/pm-require.test.js b/test/unit/sandbox-libraries/pm-require.test.js index de9bc273..56c48795 100644 --- a/test/unit/sandbox-libraries/pm-require.test.js +++ b/test/unit/sandbox-libraries/pm-require.test.js @@ -536,8 +536,6 @@ describe('sandbox library - pm.require api', function () { // scope libraries '_', 'CryptoJS', - 'atob', - 'btoa', 'tv4', 'xml2Json', 'Backbone', diff --git a/test/unit/vendors/atob.test.js b/test/unit/vendors/atob.test.js new file mode 100644 index 00000000..1c56f112 --- /dev/null +++ b/test/unit/vendors/atob.test.js @@ -0,0 +1,50 @@ +describe('sandbox vendor - atob', function () { + this.timeout(1000 * 60); + var Sandbox = require('../../../'), + context; + + beforeEach(function (done) { + Sandbox.createContext({ debug: true }, function (err, ctx) { + context = ctx; + done(err); + }); + }); + + afterEach(function () { + context.dispose(); + context = null; + }); + + it('should exist in global', function (done) { + context.execute(` + const assert = require('assert'); + assert.strictEqual(typeof atob, 'function', 'typeof atob must be function'); + `, done); + }); + + it('should be exposed via require', function (done) { + context.execute(` + const assert = require('assert'); + const atob = require('atob'); + assert.strictEqual(typeof atob, 'function', 'typeof atob must be function'); + `, done); + }); + + it('should have same implementation exposed via global, require and buffer', function (done) { + context.execute(` + const assert = require('assert'); + const requiredAtob = require('atob'); + const bufferAtob = require('buffer').atob; + assert.strictEqual(atob === requiredAtob, true); + assert.strictEqual(atob === bufferAtob, true); + `, done); + }); + + it('should decode base64 encoded string', function (done) { + context.execute(` + const assert = require('assert'); + const decoded = atob('cG9zdG1hbi1zYW5kYm94'); + assert.strictEqual(decoded, 'postman-sandbox'); + `, done); + }); +}); diff --git a/test/unit/vendors/btoa.test.js b/test/unit/vendors/btoa.test.js new file mode 100644 index 00000000..e6b58272 --- /dev/null +++ b/test/unit/vendors/btoa.test.js @@ -0,0 +1,50 @@ +describe('sandbox vendor - btoa', function () { + this.timeout(1000 * 60); + var Sandbox = require('../../../'), + context; + + beforeEach(function (done) { + Sandbox.createContext({ debug: true }, function (err, ctx) { + context = ctx; + done(err); + }); + }); + + afterEach(function () { + context.dispose(); + context = null; + }); + + it('should exist in global', function (done) { + context.execute(` + const assert = require('assert'); + assert.strictEqual(typeof btoa, 'function', 'typeof btoa must be function'); + `, done); + }); + + it('should be exposed via require', function (done) { + context.execute(` + const assert = require('assert'); + const btoa = require('btoa'); + assert.strictEqual(typeof btoa, 'function', 'typeof btoa must be function'); + `, done); + }); + + it('should have same implementation exposed via global, require and buffer', function (done) { + context.execute(` + const assert = require('assert'); + const requiredBtoa = require('btoa'); + const bufferBtoa = require('buffer').btoa; + assert.strictEqual(btoa === requiredBtoa, true); + assert.strictEqual(btoa === bufferBtoa, true); + `, done); + }); + + it('should encode a string to base64', function (done) { + context.execute(` + const assert = require('assert'); + const decoded = btoa('postman-sandbox'); + assert.strictEqual(decoded, 'cG9zdG1hbi1zYW5kYm94'); + `, done); + }); +}); diff --git a/test/unit/sandbox-libraries/buffer.test.js b/test/unit/vendors/buffer.test.js similarity index 88% rename from test/unit/sandbox-libraries/buffer.test.js rename to test/unit/vendors/buffer.test.js index 899bea1f..622c2327 100644 --- a/test/unit/sandbox-libraries/buffer.test.js +++ b/test/unit/vendors/buffer.test.js @@ -1,4 +1,6 @@ -describe('sandbox library - buffer', function () { +const isNode = typeof window === 'undefined'; + +describe('sandbox vendor - buffer', function () { this.timeout(1000 * 60); var Sandbox = require('../../../'), context; @@ -157,7 +159,7 @@ describe('sandbox library - buffer', function () { it('should be able to convert large buffer to string', function (done) { // For native buffer, the max string length is ~512MB // For browser buffer, the max string length is ~100MB - const SIZE = (typeof window === 'undefined' ? 511 : 100) * 1024 * 1024; + const SIZE = (isNode ? 511 : 100) * 1024 * 1024; context.execute(` const assert = require('assert'), @@ -286,4 +288,33 @@ describe('sandbox library - buffer', function () { assert.strictEqual(Blob === bufferBlob, true); `, done); }); + + (isNode ? it : it.skip)('should be in sync with latest available `buffer` module', function (done) { + const buffer = require('buffer'), + expectedProps = Object.getOwnPropertyNames(buffer).sort(); + + context.execute(` + const assert = require('assert'); + const buffer = require('buffer'); + const actualProps = Object.getOwnPropertyNames(buffer).sort(); + + assert.deepStrictEqual(actualProps, ${JSON.stringify(expectedProps)}); + `, done); + }); + + (isNode ? it : it.skip)('should be in sync with latest available `Buffer` class', function (done) { + const fnProps = Object.getOwnPropertyNames(function () { return 0; }).sort(), + expectedProps = Object.getOwnPropertyNames(Buffer).sort().filter((prop) => { + return !fnProps.includes(prop); + }); + + context.execute(` + const assert = require('assert'); + const actualProps = Object.getOwnPropertyNames(Buffer).sort().filter((prop) => { + return !${JSON.stringify(fnProps)}.includes(prop); + }); + + assert.deepStrictEqual(actualProps, ${JSON.stringify(expectedProps)}); + `, done); + }); }); From 4d1e196992f53124d974e39b3b5ac973aa7815a4 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Wed, 25 Sep 2024 01:23:29 +0530 Subject: [PATCH 10/12] Deprecate atob, btoa, backbone, crypto-js and tv4 libs. --- CHANGELOG.yaml | 1 + lib/sandbox/execute-context.js | 23 ++- lib/sandbox/postman-legacy-interface.js | 57 +++--- npm/utils/templates.js | 8 +- .../sandbox-libraries/deprecation.test.js | 164 ++++++++++++++++++ test/unit/sandbox-libraries/legacy.test.js | 4 +- types/sandbox/prerequest.d.ts | 8 +- types/sandbox/test.d.ts | 8 +- 8 files changed, 228 insertions(+), 45 deletions(-) create mode 100644 test/unit/sandbox-libraries/deprecation.test.js 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; From 61e0d70dd4a0d230c3dfa981be97a5440e4020b3 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Fri, 7 Feb 2025 11:41:52 +0530 Subject: [PATCH 11/12] Remove atob and btoa from jsdocs for legacy globals --- npm/utils/templates.js | 10 ---------- types/index.d.ts | 2 +- types/sandbox/prerequest.d.ts | 12 +----------- types/sandbox/test.d.ts | 12 +----------- 4 files changed, 3 insertions(+), 33 deletions(-) diff --git a/npm/utils/templates.js b/npm/utils/templates.js index 2f824501..b9b44ea8 100644 --- a/npm/utils/templates.js +++ b/npm/utils/templates.js @@ -97,16 +97,6 @@ declare var _; */ declare var CryptoJS; -/** - * @deprecated Use global "atob" function instead - */ -declare var atob; - -/** - * @deprecated Use global "btoa" function instead - */ -declare var btoa; - /** * @deprecated Use require('ajv') instead */ diff --git a/types/index.d.ts b/types/index.d.ts index c248b0af..69e94f45 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for postman-sandbox 5.1.1 +// Type definitions for postman-sandbox 5.1.2 // Project: https://github.com/postmanlabs/postman-sandbox // Definitions by: PostmanLabs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped diff --git a/types/sandbox/prerequest.d.ts b/types/sandbox/prerequest.d.ts index 44fc9391..68f591c8 100644 --- a/types/sandbox/prerequest.d.ts +++ b/types/sandbox/prerequest.d.ts @@ -1,4 +1,4 @@ -// Type definitions for postman-sandbox 5.1.1 +// Type definitions for postman-sandbox 5.1.2 // Project: https://github.com/postmanlabs/postman-sandbox // Definitions by: PostmanLabs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -59,16 +59,6 @@ declare var _; */ declare var CryptoJS; -/** - * @deprecated Use global "atob" function instead - */ -declare var atob; - -/** - * @deprecated Use global "btoa" function instead - */ -declare var btoa; - /** * @deprecated Use require('ajv') instead */ diff --git a/types/sandbox/test.d.ts b/types/sandbox/test.d.ts index 64d89d9d..cbaca03c 100644 --- a/types/sandbox/test.d.ts +++ b/types/sandbox/test.d.ts @@ -1,4 +1,4 @@ -// Type definitions for postman-sandbox 5.1.1 +// Type definitions for postman-sandbox 5.1.2 // Project: https://github.com/postmanlabs/postman-sandbox // Definitions by: PostmanLabs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -89,16 +89,6 @@ declare var _; */ declare var CryptoJS; -/** - * @deprecated Use global "atob" function instead - */ -declare var atob; - -/** - * @deprecated Use global "btoa" function instead - */ -declare var btoa; - /** * @deprecated Use require('ajv') instead */ From d691227c37557e1f308d6becedd0a3de6462f309 Mon Sep 17 00:00:00 2001 From: Appurva Murawat Date: Fri, 21 Feb 2025 18:04:23 +0530 Subject: [PATCH 12/12] Merge branch 'develop' of github.com:postmanlabs/postman-sandbox into feature/deprecate-redundant-libs --- CHANGELOG.yaml | 1 + lib/vendor/buffer/index.js | 2 +- lib/vendor/buffer/specific-buffer.js | 35 +++++++++++++++------------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 650bc825..bd2f93ae 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-1051 Added support for File global - GH-1050 Deprecated `atob`, `btoa`, `backbone`, 'crypto-js' and `tv4` libraries fixed bugs: - GH-1036 Fixed `uncaughtException` event listener not being removed diff --git a/lib/vendor/buffer/index.js b/lib/vendor/buffer/index.js index 9accc807..a8363fc3 100644 --- a/lib/vendor/buffer/index.js +++ b/lib/vendor/buffer/index.js @@ -4,5 +4,5 @@ const buffer = globalThis._nodeRequires.buffer; module.exports = getBufferModule({ ...buffer, - Buffer: SpecificBuffer(globalThis.Buffer), + Buffer: SpecificBuffer(buffer.Buffer), }); diff --git a/lib/vendor/buffer/specific-buffer.js b/lib/vendor/buffer/specific-buffer.js index 13202589..6a39ee39 100644 --- a/lib/vendor/buffer/specific-buffer.js +++ b/lib/vendor/buffer/specific-buffer.js @@ -3,7 +3,7 @@ const NOT_IMPLEMENTED = function () { }; function SpecificBuffer (_Buffer) { - const Buffer = function () { + function Buffer () { if (typeof arguments[0] === 'number') { return _Buffer.alloc(...arguments); } @@ -11,6 +11,9 @@ function SpecificBuffer (_Buffer) { return _Buffer.from(...arguments); } + // Add the static properties from the original Buffer + Object.setPrototypeOf(Buffer, _Buffer); + Buffer.poolSize = _Buffer.poolSize; Object.defineProperty(Buffer, Symbol.hasInstance, { @@ -19,46 +22,46 @@ function SpecificBuffer (_Buffer) { } }); - Buffer.isBuffer = function () { - return _Buffer.isBuffer(...arguments); + Buffer.from = function from () { + return _Buffer.from(...arguments); }; - Buffer.alloc = function () { + Buffer.copyBytesFrom = NOT_IMPLEMENTED; + + Buffer.of = NOT_IMPLEMENTED; + + Buffer.alloc = function alloc () { return _Buffer.alloc(...arguments); }; - Buffer.allocUnsafe = function () { + Buffer.allocUnsafe = function allocUnsafe () { return _Buffer.allocUnsafe(...arguments); }; - Buffer.allocUnsafeSlow = function () { + Buffer.allocUnsafeSlow = function allocUnsafeSlow () { return _Buffer.allocUnsafeSlow(...arguments); }; - Buffer.from = function () { - return _Buffer.from(...arguments); + Buffer.isBuffer = function isBuffer () { + return _Buffer.isBuffer(...arguments); }; - Buffer.compare = function () { + Buffer.compare = function compare () { return _Buffer.compare(...arguments); }; - Buffer.isEncoding = function () { + Buffer.isEncoding = function isEncoding () { return _Buffer.isEncoding(...arguments); }; - Buffer.concat = function () { + Buffer.concat = function concat () { return _Buffer.concat(...arguments); }; - Buffer.byteLength = function () { + Buffer.byteLength = function byteLength () { return _Buffer.byteLength(...arguments); }; - Buffer.copyBytesFrom = NOT_IMPLEMENTED; - - Buffer.of = NOT_IMPLEMENTED; - return Buffer; }