Skip to content

Commit

Permalink
Merge branch 'develop' into feature/fix-buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
appurva21 authored Sep 25, 2024
2 parents 0c30e17 + 8d5424d commit 3e044f0
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 208 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [16, 18]
node-version: [18, 20]
os: [ubuntu-latest, windows-latest]
include:
- coverage: true
node-version: 20
node-version: latest
os: ubuntu-latest

steps:
Expand Down
15 changes: 13 additions & 2 deletions CHANGELOG.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
unreleased:
chores:
- GH-1032 Add support for configuring module resolver based on environment
breaking changes:
- GH-1052 Dropped support for Node < v18
new features:
- GH-1032 Enhanced performance when operating on buffers in Node environment
fixed bugs:
- GH-1036 Fixed `uncaughtException` event listener not being removed
- GH-1034 Fixed an issue where sandbox crashes for large response body
chores:
- GH-1033 Update ci.yml to run coverage on latest node version
- GH-1032 Add support for configuring module resolver based on environment

5.1.2:
date: 2024-09-04
fixed bugs:
- GH-1040 Only allow `set`, `get` and `unset` operations on `pm.vault`

5.1.1:
date: 2024-08-01
Expand Down
41 changes: 18 additions & 23 deletions lib/sandbox/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const _ = require('lodash'),
PostmanAPI = require('./pmapi'),
PostmanCookieStore = require('./cookie-store'),
createPostmanRequire = require('./pm-require'),
{ Vault, getVaultInterface } = require('./vault'),
{ isNonLegacySandbox, getNonLegacyCodeMarker } = require('./non-legacy-codemarkers'),

EXECUTION_RESULT_EVENT_BASE = 'execution.result.',
Expand Down Expand Up @@ -166,6 +167,7 @@ module.exports = function (bridge, glob) {

let waiting,
timers,
vault,
skippedExecution = false;

execution.return.async = false;
Expand All @@ -187,31 +189,28 @@ module.exports = function (bridge, glob) {
timers.clearAll();
}

// remove listener of disconnection event
bridge.off(abortEventName);
bridge.off(responseEventName);
bridge.off(cookiesEventName);
bridge.off('uncaughtException', onError);

// fire extra execution error event
if (err) { onError(err); }

// @note delete response from the execution object to avoid dispatching
// the large response payload back due to performance reasons.
execution.response && (delete execution.response);
function complete () {
vault.dispose();
bridge.off(abortEventName);
bridge.off(responseEventName);
bridge.off(cookiesEventName);
bridge.off('uncaughtException', onError);

// @note delete response from the execution object to avoid dispatching
// the large response payload back due to performance reasons.
execution.response && (delete execution.response);
bridge.dispatch(executionEventName, err || null, execution);
}

if (dnd !== true) {
const dispatchExecutionResult = () => {
bridge.dispatch(executionEventName, err || null, execution);
};

// if execution is skipped, we dispatch execution completion
// event immediately to avoid any further processing else we
// dispatch it in next tick to allow any other pending events
// to be dispatched.
skippedExecution ?
dispatchExecutionResult() :
timers.wrapped.setImmediate(dispatchExecutionResult);
skippedExecution ? complete() : timers.wrapped.setImmediate(complete);
}
});

Expand Down Expand Up @@ -246,18 +245,13 @@ module.exports = function (bridge, glob) {
// and one of them throws an error, this handler will be triggered
// for all of them. This is a limitation of uvm as there is no way
// to isolate the uncaught exception handling for each execution.
bridge.on('uncaughtException', (err) => {
onError(err);
});
bridge.on('uncaughtException', onError);

if (!options.resolvedPackages) {
disabledAPIs.push('require');
}

// @todo: throw helpful error message if script access to vault is disabled
if (!context.vaultSecrets) {
disabledAPIs.push('vault');
}
vault = new Vault(id, bridge, timers);

// send control to the function that executes the context and prepares the scope
executeContext(scope, code, execution,
Expand All @@ -283,6 +277,7 @@ module.exports = function (bridge, glob) {
},
dispatchAssertions,
new PostmanCookieStore(id, bridge, timers),
getVaultInterface(vault.exec.bind(vault)),
createPostmanRequire(options.resolvedPackages, scope),
{ disabledAPIs })
),
Expand Down
2 changes: 1 addition & 1 deletion lib/sandbox/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const _ = require('lodash'),
test: true
},

CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals', 'vaultSecrets'],
CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals'],

trackingOptions = { autoCompact: true };

Expand Down
38 changes: 34 additions & 4 deletions lib/sandbox/pmapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ const _ = require('lodash'),
* @param {Function} onSkipRequest - callback to execute when pm.execution.skipRequest() called
* @param {Function} onAssertion - callback to execute when pm.expect() called
* @param {Object} cookieStore - cookie store
* @param {Vault} vault - vault
* @param {Function} requireFn - requireFn
* @param {Object} [options] - options
* @param {Array.<String>} [options.disabledAPIs] - list of disabled APIs
*/
function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, requireFn, options = {}) {
function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, vault, requireFn, options = {}) {
// @todo - ensure runtime passes data in a scope format
let iterationData = new VariableScope();

Expand All @@ -63,7 +64,6 @@ function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore,
execution._variables.addLayer(execution.environment.values);
execution._variables.addLayer(execution.collectionVariables.values);
execution._variables.addLayer(execution.globals.values);
execution._variables.addLayer(execution.vaultSecrets.values);

execution.cookies && (execution.cookies.jar = function () {
return new PostmanCookieJar(cookieStore);
Expand Down Expand Up @@ -126,9 +126,39 @@ function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore,
}),

/**
* @type {VariableScope}
* @interface Vault
*/

/**
* Get a value from the vault.
*
* @function
* @name Vault#get
* @param {string} key -
* @returns {Promise<string|undefined>}
*/
/**
* Set a value in the vault.
*
* @function
* @name Vault#set
* @param {string} key -
* @param {string} value -
* @returns {Promise<void>}
*/
/**
* Unset a value in the vault.
*
* @function
* @name Vault#unset
* @param {string} key -
* @returns {Promise<void>}
*/

/**
* @type {Vault}
*/
vault: execution.vaultSecrets,
vault: vault,

/**
* @type {VariableScope}
Expand Down
14 changes: 12 additions & 2 deletions lib/sandbox/postman-legacy-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ const _ = require('lodash'),
URLENCODED: 'urlencoded',
FORMDATA: 'formdata',
FILE: 'file'
};
},

MAX_RESPONSE_SIZE = 50 * 1024 * 1024; // 50MB

function getRequestBody (request) {
var mode = _.get(request, 'body.mode'),
Expand Down Expand Up @@ -416,7 +418,15 @@ module.exports = {
* @memberOf SandboxGlobals
* @type {String}
*/
globalvars.responseBody = execution.response ? execution.response.text() : undefined;
globalvars.responseBody = (() => {
// Truncating response body if it is too large to avoid negatively affecting
// the performance since this get calculated for every execution by default
if (!execution.response || execution.response.responseSize > MAX_RESPONSE_SIZE) {
return;
}

return execution.response.text();
})();
}

// 5. add the iteration information
Expand Down
52 changes: 52 additions & 0 deletions lib/sandbox/vault.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class Vault {
constructor (id, bridge, timers) {
this._bridge = bridge;
this._timers = timers;
this._event = `execution.vault.${id}`;

this._handler = (eventId, ...args) => {
this._timers.clearEvent(eventId, ...args);
};

this._bridge.on(this._event, this._handler);
}

exec (...args) {
return new Promise((resolve, reject) => {
const eventId = this._timers.setEvent((err, ...args) => {
if (err) {
return reject(err instanceof Error ? err : new Error(err.message || err));
}

resolve(...args);
});

this._bridge.dispatch(this._event, eventId, ...args);
});
}

dispose () {
this._bridge.off(this._event, this._handler);
}
}

const getVaultInterface = (vault) => {
return {
get: (key) => {
return vault('get', key);
},

set: (key, value) => {
return vault('set', key, value);
},

unset: (key) => {
return vault('unset', key);
}
};
};

module.exports = {
Vault,
getVaultInterface
};
Loading

0 comments on commit 3e044f0

Please sign in to comment.