1. BUG1.1 Bug Trigger condition
When using the Vis.js drawing, there is an edge between two nodes A and b that has a point from a to B, and a side that points from B to a, and the drawing library crashes.
1.2 Bug resolution
Vis.js is the dynamic calculation of the position between two nodes, and then display it on the page, and in the case described above, in the calculation of the distance between A and B, the code will appear in addition to the 0 bug, causing the program to crash.
2. Solution
The source has more than 30,000 lines, in order to find this bug took a week to determine the final function of the problem.
In the Vis.js source code line 12,258th (after the version update location may be different), there is a _calculatenodeforces () function, the source code is as follows:
/** * Calculate the forces the nodes apply on eachother based on a repulsion field. * This field is linearly approximated. * * @private*/_calculatenodeforces:function () { vardx, dy, angle, distance, FX, FY, combinedclustersize, Repulsingforce, Node1, Node2, I, J; varnodes = This. Calculationnodes; varNodeindices = This. calculationnodeindices; //Approximation Constants varA_base = -2/3; varb = 4/3; //repulsing forces between nodes varNodedistance = This. constants.physics.repulsion.nodeDistance; varMinimumdistance =nodedistance; //we loop from I through all and the last entree in the array //J Loops from I+1 to the last. This is the We do not double count any of the indices, nor i = = J for(i = 0; i < nodeindices.length-1; i++) {Node1=Nodes[nodeindices[i]]; for(j = i + 1; j < Nodeindices.length; J + +) {Node2=Nodes[nodeindices[j]]; Combinedclustersize= Node1.clustersize + node2.clustersize-2; DX= node2.x-node1.x; Dy= Node2.y-node1.y; Distance = math.sqrt (DX * dx + dy *dy); Minimumdistance= (Combinedclustersize = = 0)? Nodedistance: (Nodedistance * (1 + combinedclustersize * This. constants.clustering.distanceAmplification)); varA = a_base/minimumdistance; if(Distance < 2 *minimumdistance) { if(Distance < 0.5 *minimumdistance) {Repulsingforce= 1.0; } Else{Repulsingforce= A * distance + B;//linear approx of 1/(1 + math.exp ((distance/minimumdistance-1) * steepness)) } //amplify the repulsion for clusters.Repulsingforce *= (Combinedclustersize = = 0)? 1:1 + combinedclustersize * This. constants.clustering.forceAmplification; Repulsingforce = Repulsingforce/ distance; FX= DX *Repulsingforce; FY= Dy *Repulsingforce; Node1.fx-=FX; Node1.fy-=fy; Node2.fx+=FX; Node2.fy+=fy; } } } }};
There is a distance variable, marked red, that is, this variable in the case we introduced will be 0, and then it as a divisor, so the program crashes.
The modified code is as follows:
/** * Calculate the forces the nodes apply on eachother based on a repulsion field. * This field is linearly approximated. * * @private*/_calculatenodeforces:function () { vardx, dy, angle, distance, FX, FY, combinedclustersize, Repulsingforce, Node1, Node2, I, J; varnodes = This. Calculationnodes; varNodeindices = This. calculationnodeindices; //Approximation Constants varA_base = -2/3; varb = 4/3; //repulsing forces between nodes varNodedistance = This. constants.physics.repulsion.nodeDistance; varMinimumdistance =nodedistance; //we loop from I through all and the last entree in the array //J Loops from I+1 to the last. This is the We do not double count any of the indices, nor i = = J for(i = 0; i < nodeindices.length-1; i++) {Node1=Nodes[nodeindices[i]]; for(j = i + 1; j < Nodeindices.length; J + +) {Node2=Nodes[nodeindices[j]]; Combinedclustersize= Node1.clustersize + node2.clustersize-2; DX= node2.x-node1.x; Dy= Node2.y-node1.y; Distance= math.sqrt (DX * dx + dy *dy); if (distance = = 0) {distance = 0.001; } minimumdistance= (Combinedclustersize = = 0)? Nodedistance: (Nodedistance * (1 + combinedclustersize * This. constants.clustering.distanceAmplification)); varA = a_base/minimumdistance; if(Distance < 2 *minimumdistance) { if(Distance < 0.5 *minimumdistance) {Repulsingforce= 1.0; } Else{Repulsingforce= A * distance + B;//linear approx of 1/(1 + math.exp ((distance/minimumdistance-1) * steepness)) } //amplify the repulsion for clusters.Repulsingforce *= (Combinedclustersize = = 0)? 1:1 + combinedclustersize * This. constants.clustering.forceAmplification; Repulsingforce= Repulsingforce/distance; FX= DX *Repulsingforce; FY= Dy *Repulsingforce; Node1.fx-=FX; Node1.fy-=fy; Node2.fx+=FX; Node2.fy+=fy; } } } }};
Add a judgment and let it not be 0.
A bug in the Vis.js drawing library and source code correction