Skip to content
This repository was archived by the owner on Apr 3, 2024. It is now read-only.

Commit 54c8a97

Browse files
author
Matt Loring
committed
Don't repeat frame arguments in frame locals
It appears that function arguments captured in closures show up as both an argument and a local to v8. This patch stops us from double reporting in such cases. Fixes #59
1 parent 1c36ba5 commit 54c8a97

File tree

2 files changed

+96
-4
lines changed

2 files changed

+96
-4
lines changed

lib/state.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,12 @@ StateResolver.prototype.isPathInNodeModulesDirectory_ = function(path) {
237237

238238

239239
StateResolver.prototype.resolveFrame_ = function(frame) {
240+
var args = this.resolveArgumentList_(frame);
240241
return {
241242
function: this.resolveFunctionName_(frame.func()),
242243
location: this.resolveLocation_(frame),
243-
arguments: this.resolveArgumentList_(frame),
244-
locals: this.resolveLocalsList_(frame)
244+
arguments: args,
245+
locals: this.resolveLocalsList_(frame, args)
245246
};
246247
};
247248

@@ -277,11 +278,21 @@ StateResolver.prototype.resolveArgumentList_ = function(frame) {
277278
};
278279

279280

280-
StateResolver.prototype.resolveLocalsList_ = function(frame) {
281+
StateResolver.prototype.resolveLocalsList_ = function(frame,
282+
resolvedArguments) {
281283
var locals = [];
284+
// Arguments may have been captured as locals in a nested closure.
285+
// We filter them out here.
286+
var predicate = function(localEntry, argEntry) {
287+
return argEntry.varTableIndex === localEntry.varTableIndex;
288+
};
282289
for (var i = 0; i < frame.localCount(); i++) {
283-
locals.push(this.resolveVariable_(
290+
var localEntry = this.resolveVariable_(
291+
frame.localName(i), frame.localValue(i));
292+
if (!resolvedArguments.some(predicate.bind(null, localEntry))) {
293+
locals.push(this.resolveVariable_(
284294
frame.localName(i), frame.localValue(i)));
295+
}
285296
}
286297
return locals;
287298
};
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*1* KEEP THIS CODE AT THE TOP TO AVOID LINE NUMBER CHANGES */
2+
/*2*/'use strict';
3+
/*3*/function foo(a) {
4+
/*4*/ process.nextTick(function() {
5+
/*5*/ a = 0;
6+
/*6*/ });
7+
/*7*/}
8+
/**
9+
* Copyright 2015 Google Inc. All Rights Reserved.
10+
*
11+
* Licensed under the Apache License, Version 2.0 (the "License");
12+
* you may not use this file except in compliance with the License.
13+
* You may obtain a copy of the License at
14+
*
15+
* http://www.apache.org/licenses/LICENSE-2.0
16+
*
17+
* Unless required by applicable law or agreed to in writing, software
18+
* distributed under the License is distributed on an "AS IS" BASIS,
19+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20+
* See the License for the specific language governing permissions and
21+
* limitations under the License.
22+
*/
23+
24+
var breakpointInFoo = {
25+
id: 'fake-id-123',
26+
location: { path: 'test-duplicate-expressions.js', line: 4 }
27+
};
28+
29+
var assert = require('assert');
30+
var v8debugapi = require('../../lib/v8debugapi.js');
31+
var logModule = require('@google/cloud-diagnostics-common').logger;
32+
var config = require('../../config.js');
33+
var scanner = require('../../lib/scanner.js');
34+
35+
function stateIsClean(api) {
36+
assert.equal(api.numBreakpoints_(), 0,
37+
'there should be no breakpoints active');
38+
assert.equal(api.numListeners_(), 0,
39+
'there should be no listeners active');
40+
return true;
41+
}
42+
43+
describe('v8debugapi', function() {
44+
config.workingDirectory = process.cwd() + '/test/standalone';
45+
var logger = logModule.create(config.logLevel);
46+
var api = null;
47+
48+
beforeEach(function(done) {
49+
if (!api) {
50+
scanner.scan(config.workingDirectory, function(err, hash, fileStats) {
51+
assert(!err);
52+
api = v8debugapi.create(logger, config, fileStats);
53+
assert.ok(api, 'should be able to create the api');
54+
done();
55+
});
56+
} else {
57+
assert(stateIsClean(api));
58+
done();
59+
}
60+
});
61+
afterEach(function() { assert(stateIsClean(api)); });
62+
63+
it('should not duplicate expressions', function(done) {
64+
api.set(breakpointInFoo, function(err) {
65+
assert.ifError(err);
66+
api.wait(breakpointInFoo, function(err) {
67+
assert.ifError(err);
68+
var frames = breakpointInFoo.stackFrames[0];
69+
var exprs = frames.arguments.concat(frames.locals);
70+
var varTableIndicesSeen = [];
71+
exprs.forEach(function(expr) {
72+
assert.equal(varTableIndicesSeen.indexOf(expr.varTableIndex), -1);
73+
varTableIndicesSeen.push(expr.varTableIndex);
74+
});
75+
api.clear(breakpointInFoo);
76+
done();
77+
});
78+
process.nextTick(foo);
79+
});
80+
});
81+
});

0 commit comments

Comments
 (0)