diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2c81e0a1..635d56fd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,10 +2,10 @@ name: Rollbar.js CI on: push: - branches: [ master ] - tags: [ v* ] + branches: [master] + tags: [v*] pull_request: - branches: [ master ] + branches: [master] jobs: build: @@ -15,15 +15,15 @@ jobs: matrix: include: - node: 14 - npm: 8 + npm: ^8 - node: 16 - npm: 8 + npm: ^8 - node: 18 - npm: 9 + npm: ^9 - node: 20 - npm: 10 - - node: 21 - npm: 10 + npm: ^10 + - node: latest + npm: latest steps: - name: Checkout @@ -37,7 +37,7 @@ jobs: node-version: ${{ matrix.node }} - name: Update npm - run: npm install -g npm@^${{ matrix.npm }} + run: npm install -g npm@${{ matrix.npm }} - name: npm install run: npm install diff --git a/src/browser/telemetry.js b/src/browser/telemetry.js index ea1532c5b..ea115b58e 100644 --- a/src/browser/telemetry.js +++ b/src/browser/telemetry.js @@ -1,5 +1,6 @@ var _ = require('../utility'); var headers = require('../utility/headers'); +var replace = require('../utility/replace'); var scrub = require('../scrub'); var urlparser = require('./url'); var domUtil = require('./domUtility'); @@ -21,14 +22,6 @@ var defaults = { errorOnContentSecurityPolicy: false, }; -function replace(obj, name, replacement, replacements, type) { - var orig = obj[name]; - obj[name] = replacement(orig); - if (replacements) { - replacements[type].push([obj, name, orig]); - } -} - function restore(replacements, type) { var b; while (replacements[type].length) { diff --git a/src/server/telemetry.js b/src/server/telemetry.js index f5a19cda8..0e614c344 100644 --- a/src/server/telemetry.js +++ b/src/server/telemetry.js @@ -1,6 +1,7 @@ var http = require('http'); var https = require('https'); var _ = require('../utility'); +var replace = require('../utility/replace'); var urlHelpers = require('./telemetry/urlHelpers'); var defaults = { @@ -185,20 +186,6 @@ Instrumenter.prototype.instrumentConsole = function () { ); }; -// TODO: These helpers are duplicated in src/browser/telemetry.js, -// and may be candidates for extraction into a shared module. -// It is recommended that before doing so, the author should allow -// for more telemetry types to be implemented for the Node target -// to ensure that the implementations of these helpers don't diverge. -// If they do diverge, there's little point in the shared module. -function replace(obj, name, replacement, replacements, type) { - var orig = obj[name]; - obj[name] = replacement(orig); - if (replacements) { - replacements[type].push([obj, name, orig]); - } -} - function restore(replacements, type) { var b; while (replacements[type].length) { diff --git a/src/utility/replace.js b/src/utility/replace.js new file mode 100644 index 000000000..892bcc25b --- /dev/null +++ b/src/utility/replace.js @@ -0,0 +1,9 @@ +function replace(obj, name, replacement, replacements, type) { + var orig = obj[name]; + obj[name] = replacement(orig); + if (replacements) { + replacements[type].push([obj, name, orig]); + } + } + +module.exports = replace; diff --git a/test/server.locals.test.js b/test/server.locals.test.js index 2900db609..509d5c1b4 100644 --- a/test/server.locals.test.js +++ b/test/server.locals.test.js @@ -130,22 +130,21 @@ function verifyThrownError(r) { assert.isTrue(addItemStub.called); var data = addItemStub.getCall(0).args[3].data; assert.equal(data.body.trace_chain[0].exception.message, 'node error'); - if (nodeMajorVersion >= 10) { - // Node 10+; locals enabled - var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals.error, - '', - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals.timer, - '', - ); + var length = data.body.trace_chain[0].frames.length; + assert.ok(length > 1); + + if (nodeMajorVersion >= 18) { + // Node >=18; locals only in top frame + assert.equal(data.body.trace_chain[0].frames[length-1].locals.error, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); + } else if (nodeMajorVersion >= 10) { + // Node >=10; locals enabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals.error, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals.timer, ''); } else { - // Node 8; locals disabled - var length = data.body.trace_chain[0].frames.length; - assert.equal(data.body.trace_chain[0].frames[length - 1].locals, undefined); - assert.equal(data.body.trace_chain[0].frames[length - 2].locals, undefined); + // Node <=8; locals disabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); } addItemStub.restore(); } @@ -156,21 +155,20 @@ function verifyCaughtError(r) { assert.isTrue(addItemStub.called); var data = addItemStub.getCall(0).args[3].data; assert.equal(data.body.trace_chain[0].exception.message, 'caught error'); - if (nodeMajorVersion >= 10) { - // Node 10+; locals enabled - var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals.error, - '', - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals.timer, - '', - ); + var length = data.body.trace_chain[0].frames.length; + assert.ok(length > 1); + + if (nodeMajorVersion >= 18) { + // Node >=18; locals only in top frame + assert.equal(data.body.trace_chain[0].frames[length-1].locals.error, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); + } else if (nodeMajorVersion >= 10) { + // Node 10..<18; locals enabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals.error, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals.timer, ''); } else { - var length = data.body.trace_chain[0].frames.length; - assert.equal(data.body.trace_chain[0].frames[length - 1].locals, undefined); - assert.equal(data.body.trace_chain[0].frames[length - 2].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); } addItemStub.restore(); } @@ -182,48 +180,40 @@ function verifyNestedError(r) { var data = addItemStub.getCall(0).args[3].data; assert.equal(data.body.trace_chain[0].exception.message, 'test error'); assert.equal(data.body.trace_chain[1].exception.message, 'nested test error'); - if (nodeMajorVersion >= 10) { - // Node 10+; locals enabled - var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals.err, - '', - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals.timer, - '', - ); + var length = data.body.trace_chain[0].frames.length; + assert.ok(length > 1); + + if (nodeMajorVersion >= 18) { + // Node >=18; locals only in top frame + assert.equal(data.body.trace_chain[0].frames[length-1].locals.message, 'test error'); + assert.equal(data.body.trace_chain[0].frames[length-1].locals.password, '********'); + assert.equal(data.body.trace_chain[0].frames[length-1].locals.err, ''); + assert.equal(data.body.trace_chain[0].frames[length-1].locals.newMessage, 'nested test error'); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); + + length = data.body.trace_chain[1].frames.length; + assert.ok(length > 1); + assert.equal(data.body.trace_chain[1].frames[length-1].locals.nestedMessage, 'nested test error'); + assert.equal(data.body.trace_chain[1].frames[length-1].locals._password, '123456'); + assert.equal(data.body.trace_chain[1].frames[length-1].locals.nestedError, ''); + assert.equal(data.body.trace_chain[1].frames[length-2].locals, undefined); + } else if (nodeMajorVersion >= 10) { + // Node >=10; locals enabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals.err, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals.timer, ''); length = data.body.trace_chain[1].frames.length; - assert.equal( - data.body.trace_chain[1].frames[length - 1].locals.nestedMessage, - 'nested test error', - ); - assert.equal( - data.body.trace_chain[1].frames[length - 1].locals.nestedError, - '', - ); - assert.equal( - data.body.trace_chain[1].frames[length - 2].locals.message, - 'test error', - ); - assert.equal( - data.body.trace_chain[1].frames[length - 2].locals.password, - '********', - ); - assert.equal( - data.body.trace_chain[1].frames[length - 2].locals.err, - '', - ); - assert.equal( - data.body.trace_chain[1].frames[length - 2].locals.newMessage, - 'nested test error', - ); + assert.ok(length > 1); + assert.equal(data.body.trace_chain[1].frames[length-1].locals.nestedMessage, 'nested test error'); + assert.equal(data.body.trace_chain[1].frames[length-1].locals.nestedError, ''); + assert.equal(data.body.trace_chain[1].frames[length-2].locals.message, 'test error'); + assert.equal(data.body.trace_chain[1].frames[length-2].locals.password, '********'); + assert.equal(data.body.trace_chain[1].frames[length-2].locals.err, ''); + assert.equal(data.body.trace_chain[1].frames[length-2].locals.newMessage, 'nested test error'); } else { - // Node 8; locals disabled - var length = data.body.trace_chain[0].frames.length; - assert.equal(data.body.trace_chain[0].frames[length - 1].locals, undefined); - assert.equal(data.body.trace_chain[0].frames[length - 2].locals, undefined); + // Node <=8; locals disabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); } addItemStub.restore(); } @@ -234,30 +224,25 @@ function verifyRejectedPromise(r) { assert.isTrue(addItemStub.called); var data = addItemStub.getCall(0).args[3].data; assert.equal(data.body.trace_chain[0].exception.message, 'promise reject'); - if (nodeMajorVersion >= 10) { - // Node 10+; locals enabled - var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals.error, - '', - ); - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals.rollbar, - '', - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals.notifier, - '', - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals.r, - '', - ); + var length = data.body.trace_chain[0].frames.length; + assert.ok(length > 1); + + if (nodeMajorVersion >= 18) { + // Node >=18; locals only in top frame + assert.equal(data.body.trace_chain[0].frames[length-1].locals.error, ''); + assert.equal(data.body.trace_chain[0].frames[length-1].locals.callback, ''); + assert.equal(data.body.trace_chain[0].frames[length-1].locals.rollbar, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); + } else if (nodeMajorVersion >= 10) { + // Node >=10; locals enabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals.error, ''); + assert.equal(data.body.trace_chain[0].frames[length-1].locals.rollbar, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals.notifier, ''); + assert.equal(data.body.trace_chain[0].frames[length-2].locals.r, ''); } else { - // Node 8; locals disabled - var length = data.body.trace_chain[0].frames.length; - assert.equal(data.body.trace_chain[0].frames[length - 1].locals, undefined); - assert.equal(data.body.trace_chain[0].frames[length - 2].locals, undefined); + // Node <=8; locals disabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); } addItemStub.restore(); } @@ -293,12 +278,14 @@ vows topic: function (_err, r) { r.configure({ locals: { enabled: false } }); var notifier = r.client.notifier; + assert.ok(notifier); r.addItemStub = sinon.stub(notifier.queue, 'addItem'); nodeThrowNested(r, this.callback); }, 'should not include locals': function (_err, r) { var addItemStub = r.addItemStub; + assert.ok(addItemStub); assert.isTrue(addItemStub.called); var data = addItemStub.getCall(0).args[3].data; @@ -311,14 +298,9 @@ vows 'nested test error', ); var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals, - undefined, - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals, - undefined, - ); + assert.ok(length > 1); + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); addItemStub.restore(); }, 'then enabled': { @@ -362,14 +344,9 @@ vows 'caught error', ); var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals, - undefined, - ); - assert.equal( - data.body.trace_chain[0].frames[length - 2].locals, - undefined, - ); + assert.ok(length > 1); + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); addItemStub.restore(); }, @@ -542,31 +519,23 @@ vows assert.isTrue(addItemStub.called); var data = addItemStub.getCall(0).args[3].data; - assert.equal( - data.body.trace_chain[0].exception.message, - 'deep stack error, limit=3', - ); - if (nodeMajorVersion < 10) { - // Node 8; locals disabled - var length = data.body.trace_chain[0].frames.length; - assert.equal( - data.body.trace_chain[0].frames[length - 1].locals, - undefined, - ); + assert.equal(data.body.trace_chain[0].exception.message, 'deep stack error, limit=3'); + var length = data.body.trace_chain[0].frames.length; + assert.ok(length > 1); + + if (nodeMajorVersion >= 18) { + // Node >=18; locals only in top frame + assert.deepEqual(data.body.trace_chain[0].frames[length-1].locals, { curr: 3, limit: 3 }); + assert.equal(data.body.trace_chain[0].frames[length-2].locals, undefined); + assert.equal(data.body.trace_chain[0].frames[length-3].locals, undefined); + } else if (nodeMajorVersion >= 10) { + // Node >=10; locals enabled + assert.deepEqual(data.body.trace_chain[0].frames[length-1].locals, { curr: 3, limit: 3 }); + assert.deepEqual(data.body.trace_chain[0].frames[length-2].locals, { curr: 2, limit: 3 }); + assert.deepEqual(data.body.trace_chain[0].frames[length-3].locals, { curr: 1, limit: 3 }); } else { - var length = data.body.trace_chain[0].frames.length; - assert.deepEqual( - data.body.trace_chain[0].frames[length - 1].locals, - { curr: 3, limit: 3 }, - ); - assert.deepEqual( - data.body.trace_chain[0].frames[length - 2].locals, - { curr: 2, limit: 3 }, - ); - assert.deepEqual( - data.body.trace_chain[0].frames[length - 3].locals, - { curr: 1, limit: 3 }, - ); + // Node <=8; locals disabled + assert.equal(data.body.trace_chain[0].frames[length-1].locals, undefined); } addItemStub.reset(); Locals.session = undefined;