Skip to content

Commit

Permalink
more defensive copy selectAll
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Jun 6, 2021
1 parent 473b3ba commit 55624ee
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 9 deletions.
6 changes: 2 additions & 4 deletions src/array.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export default function(x) {
return typeof x === "object" && "length" in x
? x // Array, TypedArray, NodeList, array-like
: Array.from(x); // Map, Set, iterable, string, or anything else
export default function array(x) {
return x == null ? [] : Array.isArray(x) ? x : Array.from(x);
}
2 changes: 1 addition & 1 deletion src/selectAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import {Selection, root} from "./selection/index.js";
export default function(selector) {
return typeof selector === "string"
? new Selection([document.querySelectorAll(selector)], [document.documentElement])
: new Selection([selector == null ? [] : array(selector)], root);
: new Selection([array(selector)], root);
}
15 changes: 13 additions & 2 deletions src/selection/data.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Selection} from "./index.js";
import {EnterNode} from "./enter.js";
import array from "../array.js";
import constant from "../constant.js";

function bindIndex(parent, group, enter, update, exit, data) {
Expand Down Expand Up @@ -90,7 +89,7 @@ export default function(value, key) {
var parent = parents[j],
group = groups[j],
groupLength = group.length,
data = array(value.call(parent, parent && parent.__data__, j, parents)),
data = arraylike(value.call(parent, parent && parent.__data__, j, parents)),
dataLength = data.length,
enterGroup = enter[j] = new Array(dataLength),
updateGroup = update[j] = new Array(dataLength),
Expand All @@ -115,3 +114,15 @@ export default function(value, key) {
update._exit = exit;
return update;
}

// Given some data, this returns an array-like view of it: an object that
// exposes a length property and allows numeric indexing. Note that unlike
// selectAll, this isn’t worried about “live” collections because the resulting
// array will only be used briefly while data is being bound. (It is possible to
// cause the data to change while iterating by using a key function, but please
// don’t; we’d rather avoid a gratuitous copy.)
function arraylike(data) {
return typeof data === "object" && "length" in data
? data // Array, TypedArray, NodeList, array-like
: Array.from(data); // Map, Set, iterable, string, or anything else
}
3 changes: 1 addition & 2 deletions src/selection/selectAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import selectorAll from "../selectorAll.js";

function arrayAll(select) {
return function() {
var group = select.apply(this, arguments);
return group == null ? [] : array(group);
return array(select.apply(this, arguments));
};
}

Expand Down

0 comments on commit 55624ee

Please sign in to comment.