Skip to content

Commit

Permalink
Use native atob and btoa
Browse files Browse the repository at this point in the history
  • Loading branch information
appurva21 committed Sep 25, 2024
1 parent 83ab9ff commit 4505c79
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 60 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion lib/bundle/bundling-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
4 changes: 2 additions & 2 deletions lib/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
6 changes: 1 addition & 5 deletions lib/sandbox/postman-legacy-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -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
],

Expand All @@ -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\')',
Expand Down
1 change: 1 addition & 0 deletions lib/vendor/atob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('buffer').atob;
1 change: 1 addition & 0 deletions lib/vendor/btoa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('buffer').btoa;
2 changes: 2 additions & 0 deletions lib/vendor/buffer/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion lib/vendor/buffer/index.browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ module.exports = getBufferModule({
MAX_STRING_LENGTH: K_STRING_MAX_LENGTH
},
File: File,
Blob: Blob
Blob: Blob,
atob: atob,
btoa: btoa
});
38 changes: 0 additions & 38 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 0 additions & 4 deletions test/system/bootcode-dependencies.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion test/system/repository.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
4 changes: 2 additions & 2 deletions test/unit/sandbox-libraries/legacy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
});
});
Expand Down
2 changes: 0 additions & 2 deletions test/unit/sandbox-libraries/pm-require.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,6 @@ describe('sandbox library - pm.require api', function () {
// scope libraries
'_',
'CryptoJS',
'atob',
'btoa',
'tv4',
'xml2Json',
'Backbone',
Expand Down
50 changes: 50 additions & 0 deletions test/unit/vendors/atob.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
50 changes: 50 additions & 0 deletions test/unit/vendors/btoa.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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'),
Expand Down Expand Up @@ -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);
});
});

0 comments on commit 4505c79

Please sign in to comment.