Skip to content

Commit 3a3d54a

Browse files
committed
normalizes the calls to valueof to three arguments: *element*, *index*, and *data*
previously *data* was present in some cases (when going through the *arraytype*.map code path) but not others (e.g. when doing type conversion) Addresses this comment in #1665 (comment)
1 parent df3a3ad commit 3a3d54a

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

docs/features/transforms.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ Plot.valueof(aapl, "Close")
216216
Given an iterable *data* and some *value* accessor, returns an array (a column) of the specified *type* with the corresponding value of each element of the data. The *value* accessor may be one of the following types:
217217

218218
* a string - corresponding to the field accessor (`(d) => d[value]`)
219-
* an accessor function - called as *type*.from(*data*, *value*)
219+
* an accessor function - called on each element as *value*(*element, *index*, *data*)
220220
* a number, Date, or boolean — resulting in an array uniformly filled with the *value*
221221
* an object with a **transform** method — called as *value*.transform(*data*)
222222
* an array of values - returning the same

src/channel.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export type ChannelValue =
137137
| number // constant
138138
| boolean // constant
139139
| null // constant
140-
| ((d: any, i: number) => any) // function of data
140+
| ((d: any, i: number, values: any[]) => any) // function of data
141141
| ChannelTransform; // function of data
142142

143143
/**

src/options.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function maybeTypedArrayify(data, type) {
3535
}
3636

3737
function floater(f) {
38-
return (d, i) => coerceNumber(f(d, i));
38+
return (d, i, v) => coerceNumber(f(d, i, v));
3939
}
4040

4141
export const singleton = [null]; // for data-less decoration marks, e.g. frame
@@ -127,10 +127,18 @@ export function arrayify(data) {
127127
return data == null || data instanceof Array || data instanceof TypedArray ? data : Array.from(data);
128128
}
129129

130-
// An optimization of type.from(values, f): if the given values are already an
131-
// instanceof the desired array type, the faster values.map method is used.
130+
// A generalization of values.map(f) with type conversion: if the given values
131+
// are already an instanceof the desired array type, the faster values.map
132+
// method is used, otherwise type.from is used. If f accepts a third argument,
133+
// it receives the values.
132134
export function map(values, f, type = Array) {
133-
return values == null ? values : values instanceof type ? values.map(f) : type.from(values, f);
135+
return values == null
136+
? values
137+
: values instanceof type
138+
? values.map(f)
139+
: f.length === 3
140+
? type.from(values, (d, i) => f(d, i, values))
141+
: type.from(values, f);
134142
}
135143

136144
// An optimization of type.from(values): if the given values are already an

test/options-test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ it("valueof returns the given array value", () => {
122122
assert.strictEqual(valueof([], a), a);
123123
});
124124

125+
it("valueof passes the data as a third argument to function accessors", () => {
126+
const a = (d, i, e) => e.length;
127+
assert.deepStrictEqual(valueof([1, 2], a, Float64Array), Float64Array.of(2, 2));
128+
assert.deepStrictEqual(valueof(Float64Array.of(2, 2), a), [2, 2]);
129+
assert.deepStrictEqual(valueof(Float64Array.of(2, 2), a, Uint8Array), Uint8Array.of(2, 2));
130+
assert.deepStrictEqual(valueof([1, 2], a, Uint8Array), Uint8Array.of(2, 2));
131+
assert.deepStrictEqual(valueof([1, 2], a, Array), [2, 2]);
132+
});
133+
125134
it("valueof accepts complicated data with the proper accessor", () => {
126135
const m = [(d) => d, new Promise(() => {})];
127136
assert.deepStrictEqual(valueof(m, String), ["(d) => d", "[object Promise]"]);

0 commit comments

Comments
 (0)