Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for encoding TypedArrays as primitive objects for serialization #2911

Closed
wants to merge 11 commits into from
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 15 additions & 15 deletions src/lib/coerce.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ var DESELECTDIM = require('../constants/interactions').DESELECTDIM;
var wrap180 = require('./angles').wrap180;
var isArray = require('./is_array');
var isArrayOrTypedArray = isArray.isArrayOrTypedArray;
var isTypedArray = isArray.isTypedArray;
var isPrimitiveTypedArrayRepr = isArray.isPrimitiveTypedArrayRepr;
var b64 = require('base64-arraybuffer');

Expand Down Expand Up @@ -545,6 +544,7 @@ var dtypeStringToTypedarrayType = {
int16: Int16Array,
int32: Int32Array,
uint8: Uint8Array,
uint8_clamped: Uint8ClampedArray,
uint16: Uint16Array,
uint32: Uint32Array,
float32: Float32Array,
Expand All @@ -566,20 +566,20 @@ function primitiveTypedArrayReprToTypedArray(v) {

// Process data
var coercedV;
var data = v.data;
if(data instanceof ArrayBuffer) {
// data is an ArrayBuffer
coercedV = new TypeArrayType(data);
} else if(data.constructor === DataView) {
// data has a buffer property, where the buffer is an ArrayBuffer
coercedV = new TypeArrayType(data.buffer);
} else if(Array.isArray(data)) {
// data is a primitive array
coercedV = new TypeArrayType(data);
} else if(typeof data === 'string' ||
data instanceof String) {
// data is a base64 encoded string
var buffer = b64.decode(data);
var value = v.value;
if(value instanceof ArrayBuffer) {
// value is an ArrayBuffer
coercedV = new TypeArrayType(value);
} else if(value.constructor === DataView) {
// value has a buffer property, where the buffer is an ArrayBuffer
coercedV = new TypeArrayType(value.buffer);
} else if(Array.isArray(value)) {
// value is a primitive array
coercedV = new TypeArrayType(value);
} else if(typeof value === 'string' ||
value instanceof String) {
// value is a base64 encoded string
var buffer = b64.decode(value);
coercedV = new TypeArrayType(buffer);
}
return coercedV;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/is_array.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var Lib = require('../lib');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to require './is_plain_object.js to avoid a circular dependency pattern

lib/index -> lib/is_plain_object -> lib/index -> lib/is_array -> lib/index -> lib/is_plain_object


'use strict';

Expand Down Expand Up @@ -39,9 +40,8 @@ function isArray1D(a) {
}

function isPrimitiveTypedArrayRepr(a) {
return (a !== undefined && a !== null &&
typeof a === 'object' &&
a.hasOwnProperty('dtype') && a.hasOwnProperty('data'));
return (Lib.isPlainObject(a) &&
a.hasOwnProperty('dtype') && a.hasOwnProperty('value'));
}

module.exports = {
Expand Down
6 changes: 3 additions & 3 deletions test/image/mocks/typed_array_repr_scatter.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"data": [{
"type": "scatter",
"x": {"dtype": "float64", "data": [3, 2, 1]},
"y": {"dtype": "float32", "data": "AABAQAAAAEAAAIA/"},
"x": {"dtype": "float64", "value": [3, 2, 1]},
"y": {"dtype": "float32", "value": "AABAQAAAAEAAAIA/"},
"marker": {
"color": {
"dtype": "uint16",
"data": "AwACAAEA",
"value": "AwACAAEA",
},
}
}]
Expand Down
40 changes: 20 additions & 20 deletions test/jasmine/tests/primitive_typed_array_repr_test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
var Lib = require('@src/lib');
var supplyDefaults = require('../assets/supply_defaults');
var isTypedArray = require('../../../src/lib/is_array').isTypedArray;
var b64 = require('base64-arraybuffer');
var mock1 = require('@mocks/typed_array_repr_scatter.json');

var typedArraySpecs = [
['int8', new Int8Array([-128, -34, 1, 127])],
['uint8', new Uint8Array([0, 1, 127, 255])],
['uint8_clamped', new Uint8ClampedArray([0, 1, 127, 255])],
['int16', new Int16Array([-32768, -123, 345, 32767])],
['uint16', new Uint16Array([0, 345, 32767, 65535])],
['int32', new Int32Array([-2147483648, -123, 345, 32767, 2147483647])],
Expand All @@ -21,13 +21,13 @@ describe('Test TypedArray representations', function() {
describe('ArrayBuffer', function() {
it('should accept representation as ArrayBuffer', function() {
typedArraySpecs.forEach(function(arraySpec) {
// Build data and confirm its type
var data = arraySpec[1].buffer;
expect(data.constructor).toEqual(ArrayBuffer);
// Build value and confirm its type
var value = arraySpec[1].buffer;
expect(value.constructor).toEqual(ArrayBuffer);

var repr = {
dtype: arraySpec[0],
data: data
value: value
};
var gd = {
data: [{
Expand All @@ -46,13 +46,13 @@ describe('Test TypedArray representations', function() {
describe('Array', function() {
it('should accept representation as Array', function() {
typedArraySpecs.forEach(function(arraySpec) {
// Build data and confirm its type
var data = Array.prototype.slice.call(arraySpec[1]);
expect(Array.isArray(data)).toEqual(true);
// Build value and confirm its type
var value = Array.prototype.slice.call(arraySpec[1]);
expect(Array.isArray(value)).toEqual(true);

var repr = {
dtype: arraySpec[0],
data: data
value: value
};
var gd = {
data: [{
Expand All @@ -71,13 +71,13 @@ describe('Test TypedArray representations', function() {
describe('DataView', function() {
it('should accept representation as DataView', function() {
typedArraySpecs.forEach(function(arraySpec) {
// Build data and confirm its type
var data = new DataView(arraySpec[1].buffer);
expect(data.constructor).toEqual(DataView);
// Build value and confirm its type
var value = new DataView(arraySpec[1].buffer);
expect(value.constructor).toEqual(DataView);

var repr = {
dtype: arraySpec[0],
data: data
value: value
};
var gd = {
data: [{
Expand All @@ -96,13 +96,13 @@ describe('Test TypedArray representations', function() {
describe('base64', function() {
it('should accept representation as base 64 string', function() {
typedArraySpecs.forEach(function(arraySpec) {
// Build data and confirm its type
var data = b64.encode(arraySpec[1].buffer);
expect(typeof data).toEqual('string');
// Build value and confirm its type
var value = b64.encode(arraySpec[1].buffer);
expect(typeof value).toEqual('string');

var repr = {
dtype: arraySpec[0],
data: data
value: value
};
var gd = {
data: [{
Expand All @@ -127,21 +127,21 @@ describe('Test TypedArray representations', function() {
// data_array property
expect(gd.data[0].x).toEqual({
'dtype': 'float64',
'data': [3, 2, 1]});
'value': [3, 2, 1]});
expect(gd._fullData[0].x).toEqual(new Float64Array([3, 2, 1]));

// Check y
// data_array property
expect(gd.data[0].y).toEqual({
'dtype': 'float32',
'data': 'AABAQAAAAEAAAIA/'});
'value': 'AABAQAAAAEAAAIA/'});
expect(gd._fullData[0].y).toEqual(new Float32Array([3, 2, 1]));

// Check marker.color
// This is an arrayOk property not a data_array property
expect(gd.data[0].marker.color).toEqual({
'dtype': 'uint16',
'data': 'AwACAAEA'});
'value': 'AwACAAEA'});
expect(gd._fullData[0].marker.color).toEqual(new Uint16Array([3, 2, 1]));
});
});
Expand Down