Skip to content

Commit 552e471

Browse files
authored
Merge pull request #2375 from plotly/relink-less-stuff
Relink less stuff
2 parents 8a7ed36 + 62e54b7 commit 552e471

File tree

4 files changed

+120
-9
lines changed

4 files changed

+120
-9
lines changed

src/lib/relink_private.js

+14-8
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ var isPlainObject = require('./is_plain_object');
2020
* This prevents deepCopying massive structures like a webgl context.
2121
*/
2222
module.exports = function relinkPrivateKeys(toContainer, fromContainer) {
23-
var keys = Object.keys(fromContainer || {});
24-
25-
for(var i = 0; i < keys.length; i++) {
26-
var k = keys[i],
27-
fromVal = fromContainer[k],
28-
toVal = toContainer[k];
23+
for(var k in fromContainer) {
24+
var fromVal = fromContainer[k];
25+
var toVal = toContainer[k];
2926

27+
if(toVal === fromVal) {
28+
continue;
29+
}
3030
if(k.charAt(0) === '_' || typeof fromVal === 'function') {
3131

3232
// if it already exists at this point, it's something
@@ -37,9 +37,15 @@ module.exports = function relinkPrivateKeys(toContainer, fromContainer) {
3737
}
3838
else if(isArray(fromVal) && isArray(toVal) && isPlainObject(fromVal[0])) {
3939

40+
// filter out data_array items that can contain user objects
41+
// most of the time the toVal === fromVal check will catch these early
42+
// but if the user makes new ones we also don't want to recurse in.
43+
if(k === 'customdata' || k === 'ids') continue;
44+
4045
// recurse into arrays containers
41-
for(var j = 0; j < fromVal.length; j++) {
42-
if(isPlainObject(fromVal[j]) && isPlainObject(toVal[j])) {
46+
var minLen = Math.min(fromVal.length, toVal.length);
47+
for(var j = 0; j < minLen; j++) {
48+
if((toVal[j] !== fromVal[j]) && isPlainObject(fromVal[j]) && isPlainObject(toVal[j])) {
4349
relinkPrivateKeys(toVal[j], fromVal[j]);
4450
}
4551
}

src/plots/attributes.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ module.exports = {
8181
editType: 'calc',
8282
description: [
8383
'Assigns id labels to each datum.',
84-
'These ids for object constancy of data points during animation.'
84+
'These ids for object constancy of data points during animation.',
85+
'Should be an array of strings, not numbers or any other type.'
8586
].join(' ')
8687
},
8788
customdata: {

tasks/util/make_schema.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = function makeSchema(plotlyPath, schemaPath) {
1212
// package is annoying and platform-dependent.
1313
// see https://github.com/tmpvar/jsdom/issues/1782
1414
w.HTMLCanvasElement.prototype.getContext = function() { return null; };
15+
w.URL.createObjectURL = function() { return null; };
1516

1617
w.eval(plotlyjsCode);
1718

test/jasmine/tests/lib_test.js

+103
Original file line numberDiff line numberDiff line change
@@ -1984,6 +1984,109 @@ describe('Test lib.js:', function() {
19841984
});
19851985
});
19861986
});
1987+
1988+
describe('relinkPrivateKeys', function() {
1989+
it('ignores customdata and ids', function() {
1990+
var fromContainer = {
1991+
customdata: [{_x: 1, _y: 2, a: 3}],
1992+
ids: [{_i: 4, j: 5}]
1993+
};
1994+
var toContainer = {
1995+
customdata: [{a: 6}],
1996+
ids: [{j: 7}]
1997+
};
1998+
1999+
Lib.relinkPrivateKeys(toContainer, fromContainer);
2000+
2001+
expect(toContainer.customdata[0]._x).toBeUndefined();
2002+
expect(toContainer.customdata[0]._y).toBeUndefined();
2003+
expect(toContainer.ids[0]._i).toBeUndefined();
2004+
});
2005+
2006+
it('ignores any values that are ===', function() {
2007+
var accesses = 0;
2008+
2009+
var obj = {
2010+
get _x() { accesses++; return 1; },
2011+
set _x(v) { accesses++; }
2012+
};
2013+
var array = [obj];
2014+
var array2 = [obj];
2015+
2016+
var fromContainer = {
2017+
x: array,
2018+
y: array,
2019+
o: obj
2020+
};
2021+
var toContainer = {
2022+
x: array,
2023+
y: array2,
2024+
o: obj
2025+
};
2026+
2027+
Lib.relinkPrivateKeys(toContainer, fromContainer);
2028+
2029+
expect(accesses).toBe(0);
2030+
2031+
obj._x = 2;
2032+
expect(obj._x).toBe(1);
2033+
expect(accesses).toBe(2);
2034+
});
2035+
2036+
it('reinserts other private keys if they\'re not already there', function() {
2037+
var obj1 = {a: 10, _a: 11};
2038+
var obj2 = {a: 12, _a: 13};
2039+
function f1() { return 1; }
2040+
function f2() { return 2; }
2041+
2042+
var fromContainer = {
2043+
a: 1,
2044+
_a: 2,
2045+
_b: 3,
2046+
_c: obj1,
2047+
_d: obj1,
2048+
f: f1, // functions are private even without _
2049+
g: f1,
2050+
array: [{a: 3, _a: 4, _b: 5, f: f1, g: f1}],
2051+
o: {a: 6, _a: 7, _b: 8},
2052+
array2: [{a: 9, _a: 10}],
2053+
o2: {a: 11, _a: 12}
2054+
};
2055+
fromContainer._circular = fromContainer;
2056+
fromContainer._circular2 = fromContainer;
2057+
var toContainer = {
2058+
a: 21,
2059+
_a: 22,
2060+
_c: obj2,
2061+
f: f2,
2062+
array: [{a: 23, _a: 24, f: f2}],
2063+
o: {a: 26, _a: 27},
2064+
x: [28],
2065+
_x: 29
2066+
};
2067+
toContainer._circular = toContainer;
2068+
2069+
Lib.relinkPrivateKeys(toContainer, fromContainer);
2070+
2071+
var expected = {
2072+
a: 21,
2073+
_a: 22,
2074+
_b: 3,
2075+
_c: obj2,
2076+
_circular: toContainer,
2077+
_circular2: fromContainer,
2078+
_d: obj1,
2079+
f: f2,
2080+
g: f1,
2081+
array: [{a: 23, _a: 24, _b: 5, f: f2, g: f1}],
2082+
o: {a: 26, _a: 27, _b: 8},
2083+
x: [28],
2084+
_x: 29
2085+
};
2086+
2087+
expect(toContainer).toEqual(expected);
2088+
});
2089+
});
19872090
});
19882091

19892092
describe('Queue', function() {

0 commit comments

Comments
 (0)