Skip to content

Commit 68f2009

Browse files
authored
Merge pull request #4023 from plotly/command-observer-mutate-fix
Command observer (bad) mutation fix
2 parents 8d4ab24 + f2a03be commit 68f2009

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

src/plot_api/plot_api.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3620,7 +3620,7 @@ function deleteFrames(gd, frameList) {
36203620
}
36213621
}
36223622

3623-
frameList = frameList.slice(0);
3623+
frameList = frameList.slice();
36243624
frameList.sort();
36253625

36263626
for(i = frameList.length - 1; i >= 0; i--) {

src/plots/command.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,13 @@ function computeDataBindings(gd, args) {
360360
traces = null;
361361
}
362362

363-
crawl(aobj, function(path, attrName, attr) {
363+
crawl(aobj, function(path, attrName, _attr) {
364364
var thisTraces;
365-
if(Array.isArray(attr)) {
365+
var attr;
366+
367+
if(Array.isArray(_attr)) {
368+
attr = _attr.slice();
369+
366370
var nAttr = Math.min(attr.length, gd.data.length);
367371
if(traces) {
368372
nAttr = Math.min(nAttr, traces.length);
@@ -372,7 +376,8 @@ function computeDataBindings(gd, args) {
372376
thisTraces[j] = traces ? traces[j] : j;
373377
}
374378
} else {
375-
thisTraces = traces ? traces.slice(0) : null;
379+
attr = _attr;
380+
thisTraces = traces ? traces.slice() : null;
376381
}
377382

378383
// Convert [7] to just 7 when traces is null:

src/plots/plots.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2737,7 +2737,7 @@ plots.doCalcdata = function(gd, traces) {
27372737
// XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without
27382738
// *all* needing doCalcdata:
27392739
var calcdata = new Array(fullData.length);
2740-
var oldCalcdata = (gd.calcdata || []).slice(0);
2740+
var oldCalcdata = (gd.calcdata || []).slice();
27412741
gd.calcdata = calcdata;
27422742

27432743
// extra helper variables

test/jasmine/tests/command_test.js

+33-5
Original file line numberDiff line numberDiff line change
@@ -240,28 +240,56 @@ describe('Plots.computeAPICommandBindings', function() {
240240
});
241241

242242
it('with an array value', function() {
243-
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7], [1]]);
243+
var value = [7];
244+
var traces = [1];
245+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', value, traces]);
244246
expect(result).toEqual([{prop: 'marker.size', traces: [1], type: 'data', value: [7]}]);
247+
expect(result[0].value).not.toBe(value, 'should not mutate value array');
248+
expect(result[0].traces).not.toBe(traces, 'should not mutate traces array');
245249
});
246250

247251
it('with two array values and two traces specified', function() {
248-
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [0, 1]]);
252+
var value = [7, 5];
253+
var traces = [0, 1];
254+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', value, traces]);
249255
expect(result).toEqual([{prop: 'marker.size', traces: [0, 1], type: 'data', value: [7, 5]}]);
256+
expect(result[0].value).not.toBe(value, 'should not mutate value array');
257+
expect(result[0].traces).not.toBe(traces, 'should not mutate traces array');
250258
});
251259

252260
it('with traces specified in reverse order', function() {
253-
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [1, 0]]);
261+
var value = [7, 5];
262+
var traces = [1, 0];
263+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', value, traces]);
254264
expect(result).toEqual([{prop: 'marker.size', traces: [1, 0], type: 'data', value: [7, 5]}]);
265+
expect(result[0].value).not.toBe(value, 'should not mutate value array');
266+
expect(result[0].traces).not.toBe(traces, 'should not mutate traces array');
255267
});
256268

257269
it('with two values and a single trace specified', function() {
258-
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [0]]);
270+
var value = [7, 5];
271+
var traces = [0];
272+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', value, traces]);
259273
expect(result).toEqual([{prop: 'marker.size', traces: [0], type: 'data', value: [7]}]);
274+
expect(result[0].value).not.toBe(value, 'should not mutate value array');
275+
expect(result[0].traces).not.toBe(traces, 'should not mutate traces array');
260276
});
261277

262278
it('with two values and a different trace specified', function() {
263-
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', [7, 5], [1]]);
279+
var value = [7, 5];
280+
var traces = [1];
281+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['marker.size', value, traces]);
264282
expect(result).toEqual([{prop: 'marker.size', traces: [1], type: 'data', value: [7]}]);
283+
expect(result[0].value).not.toBe(value, 'should not mutate value array');
284+
expect(result[0].traces).not.toBe(traces, 'should not mutate traces array');
285+
});
286+
287+
it('with two values and no trace specified', function() {
288+
gd.data.length = 0;
289+
var value = [false, true];
290+
var result = Plots.computeAPICommandBindings(gd, 'restyle', ['visible', value]);
291+
expect(result).toEqual([{prop: 'visible', traces: [], type: 'data', value: []}]);
292+
expect(result[0].value).not.toBe(value, 'should not mutate value array');
265293
});
266294
});
267295
});

0 commit comments

Comments
 (0)