This is an automated email from the ASF dual-hosted git repository.
domoritz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new eedf69540b ARROW-16209: [JS] Support setting arbitrary symbols on
Tables
eedf69540b is described below
commit eedf69540b6ac5ae6555dcffbf0d3320b4b7a89c
Author: Dominik Moritz <[email protected]>
AuthorDate: Mon Apr 18 21:13:33 2022 -0400
ARROW-16209: [JS] Support setting arbitrary symbols on Tables
Fixes https://github.com/vega/vega-lite/issues/8105
Similar to https://github.com/apache/arrow/pull/12906 but only allows
symbols and only allows them on structs.
Closes #12907 from domoritz/dom/set-symbol
Authored-by: Dominik Moritz <[email protected]>
Signed-off-by: Dominik Moritz <[email protected]>
---
js/src/Arrow.dom.ts | 2 +-
js/src/Arrow.ts | 1 +
js/src/builder/struct.ts | 8 +++----
js/src/row/struct.ts | 4 +++-
js/src/visitor/get.ts | 4 ++--
js/test/unit/row/struct-tests.ts | 49 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/js/src/Arrow.dom.ts b/js/src/Arrow.dom.ts
index 75efb3d22b..d2c44cfe44 100644
--- a/js/src/Arrow.dom.ts
+++ b/js/src/Arrow.dom.ts
@@ -34,7 +34,7 @@ RecordBatchFileWriter['throughDOM'] =
recordBatchWriterThroughDOMStream;
RecordBatchStreamWriter['throughDOM'] = recordBatchWriterThroughDOMStream;
export type {
- TypeMap,
+ TypeMap, StructRowProxy,
ReadableSource, WritableSink,
ArrowJSONLike, FileHandle, Readable, Writable, ReadableWritable,
ReadableDOMStreamOptions,
} from './Arrow.js';
diff --git a/js/src/Arrow.ts b/js/src/Arrow.ts
index bf87ed6177..4f41ede107 100644
--- a/js/src/Arrow.ts
+++ b/js/src/Arrow.ts
@@ -59,6 +59,7 @@ export { Schema, Field } from './schema.js';
export { MapRow } from './row/map.js';
export { StructRow } from './row/struct.js';
+export type { StructRowProxy } from './row/struct.js';
export { Builder } from './builder.js';
export { makeBuilder, vectorFromArray, builderThroughIterable,
builderThroughAsyncIterable } from './factories.js';
diff --git a/js/src/builder/struct.ts b/js/src/builder/struct.ts
index c645efdeae..e1beb3d380 100644
--- a/js/src/builder/struct.ts
+++ b/js/src/builder/struct.ts
@@ -24,11 +24,11 @@ import { Struct, TypeMap } from '../type.js';
/** @ignore */
export class StructBuilder<T extends TypeMap = any, TNull = any> extends
Builder<Struct<T>, TNull> {
public setValue(index: number, value: Struct<T>['TValue']) {
- const children = this.children;
+ const { children, type } = this;
switch (Array.isArray(value) || value.constructor) {
- case true: return this.type.children.forEach((_, i) =>
children[i].set(index, value[i]));
- case Map: return this.type.children.forEach((f, i) =>
children[i].set(index, value.get(f.name)));
- default: return this.type.children.forEach((f, i) =>
children[i].set(index, value[f.name]));
+ case true: return type.children.forEach((_, i) =>
children[i].set(index, value[i]));
+ case Map: return type.children.forEach((f, i) =>
children[i].set(index, value.get(f.name)));
+ default: return type.children.forEach((f, i) =>
children[i].set(index, value[f.name]));
}
}
diff --git a/js/src/row/struct.ts b/js/src/row/struct.ts
index 483a435670..094f6a4b11 100644
--- a/js/src/row/struct.ts
+++ b/js/src/row/struct.ts
@@ -27,6 +27,8 @@ import { instance as setVisitor } from '../visitor/set.js';
export type StructRowProxy<T extends TypeMap = any> = StructRow<T> & {
[P in keyof T]: T[P]['TValue'];
+} & {
+ [key: symbol]: any;
};
export class StructRow<T extends TypeMap = any> {
@@ -149,7 +151,7 @@ class StructRowProxyHandler<T extends TypeMap = any>
implements ProxyHandler<Str
setVisitor.visit(row[kParent].children[idx], row[kRowIndex], val);
// Cache key/val lookups
return Reflect.set(row, key, val);
- } else if (Reflect.has(row, key)) {
+ } else if (Reflect.has(row, key) || typeof key === 'symbol') {
return Reflect.set(row, key, val);
}
return false;
diff --git a/js/src/visitor/get.ts b/js/src/visitor/get.ts
index 8f6cd7fed2..12f8325470 100644
--- a/js/src/visitor/get.ts
+++ b/js/src/visitor/get.ts
@@ -20,7 +20,7 @@ import { BN } from '../util/bn.js';
import { Vector } from '../vector.js';
import { Visitor } from '../visitor.js';
import { MapRow } from '../row/map.js';
-import { StructRow } from '../row/struct.js';
+import { StructRow, StructRowProxy } from '../row/struct.js';
import { decodeUtf8 } from '../util/utf8.js';
import { TypeToDataType } from '../interfaces.js';
import { uint16ToFloat64 } from '../util/math.js';
@@ -228,7 +228,7 @@ const getMap = <T extends Map_>(data: Data<T>, index:
number): T['TValue'] => {
/** @ignore */
const getStruct = <T extends Struct>(data: Data<T>, index: number):
T['TValue'] => {
- return new StructRow(data, index);
+ return new StructRow(data, index) as StructRowProxy<T['TValue']>;
};
/* istanbul ignore next */
diff --git a/js/test/unit/row/struct-tests.ts b/js/test/unit/row/struct-tests.ts
new file mode 100644
index 0000000000..2ba6d34bbd
--- /dev/null
+++ b/js/test/unit/row/struct-tests.ts
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import { Field, Float32, makeData, Struct, StructRow, StructRowProxy } from
'apache-arrow';
+
+function makeStructRow() {
+ const struct = makeData({
+ type: new Struct<{ foo: Float32 }>([
+ new Field('foo', new Float32())
+ ]),
+ });
+ return new StructRow(struct, 0) as StructRowProxy<{ foo: Float32 }>;
+}
+
+describe('StructRow', () => {
+ test('Can set existing property', () => {
+ const row = makeStructRow();
+ row.foo = 42;
+ expect(row.foo).toBe(42);
+ });
+
+ test('Can set arbitrary symbols', () => {
+ const row = makeStructRow();
+ const s = Symbol.for('mySymbol');
+ row[s] = 42;
+ expect(row[s]).toBe(42);
+ });
+
+ test('Cannot set arbitrary property', () => {
+ const row = makeStructRow();
+ expect(() => {
+ (row as any).bar = 42;
+ }).toThrow();
+ });
+});