Skip to content

Commit f2a03be

Browse files
committed
fix #4002 - don't mutate array 'attr'
.. as this can have erroneous repercussions e.g. when fullLayout.sliders[i].steps[j].args is linked to the same ref as in gd.layout.
1 parent fbbcd20 commit f2a03be

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

src/plots/command.js

+7-2
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,6 +376,7 @@ function computeDataBindings(gd, args) {
372376
thisTraces[j] = traces ? traces[j] : j;
373377
}
374378
} else {
379+
attr = _attr;
375380
thisTraces = traces ? traces.slice() : null;
376381
}
377382

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)