From 67ccac94e30ceb9063dd4db6edf469b55988c0a4 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 09:34:48 -0500 Subject: [PATCH 1/9] Revert trace changes --- src/traces/heatmap/xyz_defaults.js | 16 +++++----------- src/traces/isosurface/defaults.js | 18 ++++++------------ src/traces/scatter/xy_defaults.js | 11 ++++------- src/traces/scatter3d/defaults.js | 6 +----- 4 files changed, 16 insertions(+), 35 deletions(-) diff --git a/src/traces/heatmap/xyz_defaults.js b/src/traces/heatmap/xyz_defaults.js index 5618b4a35b3..8be45ca87f0 100644 --- a/src/traces/heatmap/xyz_defaults.js +++ b/src/traces/heatmap/xyz_defaults.js @@ -19,25 +19,19 @@ module.exports = function handleXYZDefaults(traceIn, traceOut, coerce, layout, x yName = yName || 'y'; var x, y; - var shapeX = x ? (x.shape ? x.shape[0] : x.length) || 0 : 0; - var shapeY = y ? (y.shape ? y.shape[0] : y.length) || 0 : 0; - var shapeZ = z ? (z.shape ? z.shape[0] : z.length) || 0 : 0; + if(z === undefined || !z.length) return 0; - var zlen = shapeZ || (z && z.length) || 0; - - if(z === undefined || !zlen) return 0; - - if(Lib.isArray1D(traceIn.z) || (z && z.shape && z.shape.length === 1)) { + if(Lib.isArray1D(traceIn.z)) { x = coerce(xName); y = coerce(yName); - var xlen = shapeX || Lib.minRowLength(x); - var ylen = shapeY || Lib.minRowLength(y); + var xlen = Lib.minRowLength(x); + var ylen = Lib.minRowLength(y); // column z must be accompanied by xName and yName arrays if(xlen === 0 || ylen === 0) return 0; - traceOut._length = Math.min(xlen, ylen, zlen); + traceOut._length = Math.min(xlen, ylen, z.length); } else { x = coordDefaults(xName, coerce); y = coordDefaults(yName, coerce); diff --git a/src/traces/isosurface/defaults.js b/src/traces/isosurface/defaults.js index 0ce5fc342b8..c8b9916c86e 100644 --- a/src/traces/isosurface/defaults.js +++ b/src/traces/isosurface/defaults.js @@ -38,18 +38,12 @@ function supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce) { var z = coerce('z'); var value = coerce('value'); - var len = 0; - - if(x && y && z && value) { - len = Math.min( - (x.shape ? x.shape[0] : x.length) || 0, - (y.shape ? y.shape[0] : y.length) || 0, - (z.shape ? z.shape[0] : z.length) || 0, - (value.shape ? value.shape[0] : value.length) || 0 - ); - } - - if(!len) { + if( + !x || !x.length || + !y || !y.length || + !z || !z.length || + !value || !value.length + ) { traceOut.visible = false; return; } diff --git a/src/traces/scatter/xy_defaults.js b/src/traces/scatter/xy_defaults.js index 697472f2d21..5c8f7ace4ef 100644 --- a/src/traces/scatter/xy_defaults.js +++ b/src/traces/scatter/xy_defaults.js @@ -19,22 +19,19 @@ module.exports = function handleXYDefaults(traceIn, traceOut, layout, coerce) { var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); - var shapeX = x && x.shape ? x.shape[0] : 0; - var shapeY = y && y.shape ? y.shape[0] : 0; - if(x) { - var xlen = shapeX || Lib.minRowLength(x); + var xlen = Lib.minRowLength(x); if(y) { - len = shapeY || Math.min(xlen, Lib.minRowLength(y)); + len = Math.min(xlen, Lib.minRowLength(y)); } else { - len = shapeX || xlen; + len = xlen; coerce('y0'); coerce('dy'); } } else { if(!y) return 0; - len = shapeY || Lib.minRowLength(y); + len = Lib.minRowLength(y); coerce('x0'); coerce('dx'); } diff --git a/src/traces/scatter3d/defaults.js b/src/traces/scatter3d/defaults.js index 5be93835de4..0c1b1cf8274 100644 --- a/src/traces/scatter3d/defaults.js +++ b/src/traces/scatter3d/defaults.js @@ -78,12 +78,8 @@ function handleXYZDefaults(traceIn, traceOut, coerce, layout) { handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); if(x && y && z) { - var shapeX = (x.shape ? x.shape[0] : x.length) || 0; - var shapeY = (y.shape ? y.shape[0] : y.length) || 0; - var shapeZ = (z.shape ? z.shape[0] : z.length) || 0; - // TODO: what happens if one is missing? - len = Math.min(shapeX, shapeY, shapeZ); + len = Math.min(x.length, y.length, z.length); traceOut._length = traceOut._xlength = traceOut._ylength = traceOut._zlength = len; } From 712a124ea14702629ae6aecbcbf32c8cb5d6dcbb Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 13:23:40 -0500 Subject: [PATCH 2/9] WIP of decoding in calc. Works for initial render, but typed array is overwritten when supplyDefaults is run again. --- src/lib/array.js | 113 +++++++++++++++++++++++++++++- src/lib/coerce.js | 25 ++----- src/plots/plots.js | 33 +++------ src/traces/isosurface/defaults.js | 2 + 4 files changed, 129 insertions(+), 44 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index bda12db0795..a5121b943af 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -7,6 +7,8 @@ */ 'use strict'; +var b64 = require('base64-arraybuffer'); +var isPlainObject = require('./is_plain_object'); var isArray = Array.isArray; @@ -39,7 +41,7 @@ exports.isArrayOrTypedArray = isArrayOrTypedArray; * not consistent we won't figure that out here. */ function isArray1D(a) { - return !isArrayOrTypedArray(a[0]); + return !(isArrayOrTypedArray(a[0]) || (isTypedArraySpec(a) && a.ndims === 1)); } exports.isArray1D = isArray1D; @@ -63,6 +65,113 @@ exports.ensureArray = function(out, n) { return out; }; +var typedArrays = { + int8: typeof Int8Array !== 'undefined' ? Int8Array : null, + uint8: typeof Uint8Array !== 'undefined' ? Uint8Array : null, + uint8clamped: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : null, + int16: typeof Int16Array !== 'undefined' ? Int16Array : null, + uint16: typeof Uint16Array !== 'undefined' ? Uint16Array : null, + int32: typeof Int32Array !== 'undefined' ? Int32Array : null, + uint32: typeof Uint32Array !== 'undefined' ? Uint32Array : null, + float32: typeof Float32Array !== 'undefined' ? Float32Array : null, + float64: typeof Float64Array !== 'undefined' ? Float64Array : null, + bigint64: typeof BigInt64Array !== 'undefined' ? BigInt64Array : null, + biguint64: typeof BigUint64Array !== 'undefined' ? BigUint64Array : null +}; +exports.typedArrays = typedArrays; + + +exports.decodeTypedArraySpec = function(v) { + // Assume processed by coerceTypedArraySpec + var T = typedArrays[v.dtype]; + var buffer; + if(v.bvals.constructor === ArrayBuffer) { + // Already an ArrayBuffer + buffer = v.bvals; + } else { + // Decode, assuming a string + buffer = b64.decode(v.bvals); + } + + // Check if 1d shape. If so, we're done + if(v.ndims === 1) { + // Construct single Typed array over entire buffer + return new T(buffer); + } else { + // Reshape into nested plain arrays with innermost + // level containing typed arrays + // We could eventually adopt an ndarray library + + // Build cumulative product of dimensions + var cumulativeShape = v.shape.map(function(a, i) { + return a * (v.shape[i - 1] || 1); + }); + + // Loop of dimensions in reverse order + var nestedArray = []; + for(var dimInd = v.ndims - 1; dimInd > 0; dimInd--) { + var subArrayLength = v.shape[dimInd]; + var numSubArrays = cumulativeShape[dimInd - 1]; + var nextArray = []; + + if(dimInd === v.ndims - 1) { + // First time through, we build the + // inner most typed arrays + for(var typedInd = 0; typedInd < numSubArrays; typedInd++) { + var typedOffset = typedInd * subArrayLength; + nextArray.push( + new T(buffer, typedOffset * T.BYTES_PER_ELEMENT, subArrayLength) + ); + } + } else { + // Following times through, build + // next layer of nested arrays + for(var i = 0; i < numSubArrays; i++) { + var offset = i * subArrayLength; + nextArray.push(nextArray.slice(offset, offset + subArrayLength - 1)); + } + } + + // Update nested array with next nesting level + nestedArray = nextArray; + } + + return nestedArray; + } +}; + +function isTypedArraySpec(v) { + // Assume v has not passed through + return isPlainObject(v) && typedArrays[v.dtype] && v.bvals && ( + Number.isInteger(v.shape) || + (isArrayOrTypedArray(v.shape) && + v.shape.length > 0 && + v.shape.every(function(d) { return Number.isInteger(d); })) + ); +} +exports.isTypedArraySpec = isTypedArraySpec; + +function coerceTypedArraySpec(v) { + // Assume isTypedArraySpec passed + var coerced = {dtype: v.dtype, bvals: v.bvals}; + + // Normalize shape to a list + if(Number.isInteger(v.shape)) { + coerced.shape = [v.shape]; + } else { + coerced.shape = v.shape; + } + + // Add length property + coerced.length = v.shape.reduce(function(a, b) { return a * b; }); + + // Add ndims + coerced.ndims = v.shape.length; + + return coerced; +} +exports.coerceTypedArraySpec = coerceTypedArraySpec; + /* * TypedArray-compatible concatenation of n arrays * if all arrays are the same type it will preserve that type, @@ -150,6 +259,8 @@ function _rowLength(z, fn, len0) { } else { return z.length; } + } else if(isTypedArraySpec(z)) { + return z.shape[z.shape.length - 1]; } return 0; } diff --git a/src/lib/coerce.js b/src/lib/coerce.js index 4ff5465d3cd..60229d6f19e 100644 --- a/src/lib/coerce.js +++ b/src/lib/coerce.js @@ -18,22 +18,10 @@ var DESELECTDIM = require('../constants/interactions').DESELECTDIM; var nestedProperty = require('./nested_property'); var counterRegex = require('./regex').counter; var modHalf = require('./mod').modHalf; -var isPlainObject = require('./is_plain_object'); var isArrayOrTypedArray = require('./array').isArrayOrTypedArray; +var isTypedArraySpec = require('./array').isTypedArraySpec; +var coerceTypedArraySpec = require('./array').coerceTypedArraySpec; -var typedArrays = { - int8: typeof Int8Array !== 'undefined' ? 1 : 0, - uint8: typeof Uint8Array !== 'undefined' ? 1 : 0, - uint8clamped: typeof Uint8ClampedArray !== 'undefined' ? 1 : 0, - int16: typeof Int16Array !== 'undefined' ? 1 : 0, - uint16: typeof Uint16Array !== 'undefined' ? 1 : 0, - int32: typeof Int32Array !== 'undefined' ? 1 : 0, - uint32: typeof Uint32Array !== 'undefined' ? 1 : 0, - float32: typeof Float32Array !== 'undefined' ? 1 : 0, - float64: typeof Float64Array !== 'undefined' ? 1 : 0, - bigint64: typeof BigInt64Array !== 'undefined' ? 1 : 0, - biguint64: typeof BigUint64Array !== 'undefined' ? 1 : 0 -}; exports.valObjectMeta = { data_array: { @@ -53,12 +41,9 @@ exports.valObjectMeta = { if(isArrayOrTypedArray(v)) { propOut.set(v); wasSet = true; - } else if(isPlainObject(v)) { - var T = typedArrays[v.dtype]; - if(T) { - propOut.set(v); - wasSet = true; - } + } else if(isTypedArraySpec(v)) { + propOut.set(coerceTypedArraySpec(v)); + wasSet = true; } if(!wasSet && dflt !== undefined) propOut.set(dflt); } diff --git a/src/plots/plots.js b/src/plots/plots.js index 9c10b2cf1e9..2643ff778b7 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -11,7 +11,8 @@ var d3 = require('d3'); var timeFormatLocale = require('d3-time-format').timeFormatLocale; var isNumeric = require('fast-isnumeric'); -var b64 = require('base64-arraybuffer'); +var decodeTypedArraySpec = require('../lib/array').decodeTypedArraySpec; +var isTypedArraySpec = require('../lib/array').isTypedArraySpec; var Registry = require('../registry'); var PlotSchema = require('../plot_api/plot_schema'); @@ -2849,40 +2850,26 @@ function _transition(gd, transitionOpts, opts) { return transitionStarting.then(function() { return gd; }); } -var typedArrays = { - int8: typeof Int8Array !== 'undefined' ? Int8Array : null, - uint8: typeof Uint8Array !== 'undefined' ? Uint8Array : null, - uint8clamped: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : null, - int16: typeof Int16Array !== 'undefined' ? Int16Array : null, - uint16: typeof Uint16Array !== 'undefined' ? Uint16Array : null, - int32: typeof Int32Array !== 'undefined' ? Int32Array : null, - uint32: typeof Uint32Array !== 'undefined' ? Uint32Array : null, - float32: typeof Float32Array !== 'undefined' ? Float32Array : null, - float64: typeof Float64Array !== 'undefined' ? Float64Array : null, - bigint64: typeof BigInt64Array !== 'undefined' ? BigInt64Array : null, - biguint64: typeof BigUint64Array !== 'undefined' ? BigUint64Array : null -}; - function _decode(cont) { - if(cont.dtype && cont.bvals) { - var T = typedArrays[cont.dtype]; - if(T) { - return new T(b64.decode(cont.bvals)); - } + if(isTypedArraySpec(cont)) { + return decodeTypedArraySpec(cont); } - for(var prop in cont) { if(prop[0] !== '_' && cont.hasOwnProperty(prop)) { var item = cont[prop]; if(Lib.isPlainObject(item)) { var r = _decode(item); if(r !== undefined) cont[prop] = r; + } else if(Array.isArray(cont) && cont.length > 0 && Lib.isPlainObject(cont[0])) { + for(var i = 0; i < cont.length; i++) { + _decode(cont[i]); + } } } } } -function decodeB64Arrays(gd) { +function decodeTypedArrays(gd) { for(var i = 0; i < gd._fullData.length; i++) { _decode(gd._fullData[i]); } @@ -2891,7 +2878,7 @@ function decodeB64Arrays(gd) { } plots.doCalcdata = function(gd, traces) { - decodeB64Arrays(gd); + decodeTypedArrays(gd); var axList = axisIDs.list(gd); var fullData = gd._fullData; diff --git a/src/traces/isosurface/defaults.js b/src/traces/isosurface/defaults.js index c8b9916c86e..b8283d42424 100644 --- a/src/traces/isosurface/defaults.js +++ b/src/traces/isosurface/defaults.js @@ -38,6 +38,8 @@ function supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce) { var z = coerce('z'); var value = coerce('value'); + console.log(["x", x]); + if( !x || !x.length || !y || !y.length || From 4d5b3820f191a4b8a2e80d5d3659d76b3c7d2feb Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 13:53:15 -0500 Subject: [PATCH 3/9] Back to decoding in coerce --- src/lib/array.js | 5 ++--- src/lib/coerce.js | 4 ++-- src/plots/plots.js | 31 ------------------------------- src/traces/isosurface/defaults.js | 2 -- 4 files changed, 4 insertions(+), 38 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index a5121b943af..0eb0cd65289 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -41,7 +41,7 @@ exports.isArrayOrTypedArray = isArrayOrTypedArray; * not consistent we won't figure that out here. */ function isArray1D(a) { - return !(isArrayOrTypedArray(a[0]) || (isTypedArraySpec(a) && a.ndims === 1)); + return !isArrayOrTypedArray(a[0]); } exports.isArray1D = isArray1D; @@ -83,6 +83,7 @@ exports.typedArrays = typedArrays; exports.decodeTypedArraySpec = function(v) { // Assume processed by coerceTypedArraySpec + v = coerceTypedArraySpec(v) var T = typedArrays[v.dtype]; var buffer; if(v.bvals.constructor === ArrayBuffer) { @@ -259,8 +260,6 @@ function _rowLength(z, fn, len0) { } else { return z.length; } - } else if(isTypedArraySpec(z)) { - return z.shape[z.shape.length - 1]; } return 0; } diff --git a/src/lib/coerce.js b/src/lib/coerce.js index 60229d6f19e..b137e1cad30 100644 --- a/src/lib/coerce.js +++ b/src/lib/coerce.js @@ -20,7 +20,7 @@ var counterRegex = require('./regex').counter; var modHalf = require('./mod').modHalf; var isArrayOrTypedArray = require('./array').isArrayOrTypedArray; var isTypedArraySpec = require('./array').isTypedArraySpec; -var coerceTypedArraySpec = require('./array').coerceTypedArraySpec; +var decodeTypedArraySpec = require('./array').decodeTypedArraySpec; exports.valObjectMeta = { @@ -42,7 +42,7 @@ exports.valObjectMeta = { propOut.set(v); wasSet = true; } else if(isTypedArraySpec(v)) { - propOut.set(coerceTypedArraySpec(v)); + propOut.set(decodeTypedArraySpec(v)); wasSet = true; } if(!wasSet && dflt !== undefined) propOut.set(dflt); diff --git a/src/plots/plots.js b/src/plots/plots.js index 2643ff778b7..c28b8f3df72 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -11,8 +11,6 @@ var d3 = require('d3'); var timeFormatLocale = require('d3-time-format').timeFormatLocale; var isNumeric = require('fast-isnumeric'); -var decodeTypedArraySpec = require('../lib/array').decodeTypedArraySpec; -var isTypedArraySpec = require('../lib/array').isTypedArraySpec; var Registry = require('../registry'); var PlotSchema = require('../plot_api/plot_schema'); @@ -2850,36 +2848,7 @@ function _transition(gd, transitionOpts, opts) { return transitionStarting.then(function() { return gd; }); } -function _decode(cont) { - if(isTypedArraySpec(cont)) { - return decodeTypedArraySpec(cont); - } - for(var prop in cont) { - if(prop[0] !== '_' && cont.hasOwnProperty(prop)) { - var item = cont[prop]; - if(Lib.isPlainObject(item)) { - var r = _decode(item); - if(r !== undefined) cont[prop] = r; - } else if(Array.isArray(cont) && cont.length > 0 && Lib.isPlainObject(cont[0])) { - for(var i = 0; i < cont.length; i++) { - _decode(cont[i]); - } - } - } - } -} - -function decodeTypedArrays(gd) { - for(var i = 0; i < gd._fullData.length; i++) { - _decode(gd._fullData[i]); - } - - _decode(gd._fullLayout); -} - plots.doCalcdata = function(gd, traces) { - decodeTypedArrays(gd); - var axList = axisIDs.list(gd); var fullData = gd._fullData; var fullLayout = gd._fullLayout; diff --git a/src/traces/isosurface/defaults.js b/src/traces/isosurface/defaults.js index b8283d42424..c8b9916c86e 100644 --- a/src/traces/isosurface/defaults.js +++ b/src/traces/isosurface/defaults.js @@ -38,8 +38,6 @@ function supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce) { var z = coerce('z'); var value = coerce('value'); - console.log(["x", x]); - if( !x || !x.length || !y || !y.length || From 7233f34e25735a7ab66d4d8271701f96e64dc5b0 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 14:35:14 -0500 Subject: [PATCH 4/9] Cache base64 decoded ArrayBuffers and keep decoding in coerce / supplyDefaults --- src/lib/array.js | 2 +- src/lib/coerce.js | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index 0eb0cd65289..bdd5bcf5f64 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -83,7 +83,7 @@ exports.typedArrays = typedArrays; exports.decodeTypedArraySpec = function(v) { // Assume processed by coerceTypedArraySpec - v = coerceTypedArraySpec(v) + v = coerceTypedArraySpec(v); var T = typedArrays[v.dtype]; var buffer; if(v.bvals.constructor === ArrayBuffer) { diff --git a/src/lib/coerce.js b/src/lib/coerce.js index b137e1cad30..c2d931f7b3a 100644 --- a/src/lib/coerce.js +++ b/src/lib/coerce.js @@ -21,6 +21,7 @@ var modHalf = require('./mod').modHalf; var isArrayOrTypedArray = require('./array').isArrayOrTypedArray; var isTypedArraySpec = require('./array').isTypedArraySpec; var decodeTypedArraySpec = require('./array').decodeTypedArraySpec; +var coerceTypedArraySpec = require('./array').coerceTypedArraySpec; exports.valObjectMeta = { @@ -42,7 +43,43 @@ exports.valObjectMeta = { propOut.set(v); wasSet = true; } else if(isTypedArraySpec(v)) { - propOut.set(decodeTypedArraySpec(v)); + // Copy and coerce spec + v = coerceTypedArraySpec(v); + + // See if caching location is available + var uid = propOut.obj.uid; + var module = propOut.obj._module; + + if(v.bvals.constructor === ArrayBuffer || !uid || !module) { + // Already an ArrayBuffer + // decoding is cheap + propOut.set(decodeTypedArraySpec(v)); + } else { + var prop = propOut.astr; + var cache = module._b64BufferCache || {}; + + // Check cache + var cachedBuffer = ((cache[uid] || {})[prop] || {})[v.bvals]; + if(cachedBuffer !== undefined) { + // Use cached array buffer instead of base64 encoded + // string + v.bvals = cachedBuffer; + propOut.set(decodeTypedArraySpec(v)); + } else { + // Not in so cache decode + var decoded = decodeTypedArraySpec(v); + propOut.set(decoded); + + // Update cache for next time + cache[uid] = (cache[uid] || {}); + + // Clear any prior cache value (only store one per + // trace property + cache[uid][prop] = {}; + cache[uid][prop][v.bvals] = decoded.buffer; + module._b64BufferCache = cache; + } + } wasSet = true; } if(!wasSet && dflt !== undefined) propOut.set(dflt); From 5079fc79aa9a3f573d910bd534b8cce70fe42ebf Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 15:09:17 -0500 Subject: [PATCH 5/9] bvals -> buffer --- src/lib/array.js | 10 +++++----- src/lib/coerce.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index bdd5bcf5f64..430e4c72aa0 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -86,12 +86,12 @@ exports.decodeTypedArraySpec = function(v) { v = coerceTypedArraySpec(v); var T = typedArrays[v.dtype]; var buffer; - if(v.bvals.constructor === ArrayBuffer) { + if(v.buffer.constructor === ArrayBuffer) { // Already an ArrayBuffer - buffer = v.bvals; + buffer = v.buffer; } else { // Decode, assuming a string - buffer = b64.decode(v.bvals); + buffer = b64.decode(v.buffer); } // Check if 1d shape. If so, we're done @@ -143,7 +143,7 @@ exports.decodeTypedArraySpec = function(v) { function isTypedArraySpec(v) { // Assume v has not passed through - return isPlainObject(v) && typedArrays[v.dtype] && v.bvals && ( + return isPlainObject(v) && typedArrays[v.dtype] && v.buffer && ( Number.isInteger(v.shape) || (isArrayOrTypedArray(v.shape) && v.shape.length > 0 && @@ -154,7 +154,7 @@ exports.isTypedArraySpec = isTypedArraySpec; function coerceTypedArraySpec(v) { // Assume isTypedArraySpec passed - var coerced = {dtype: v.dtype, bvals: v.bvals}; + var coerced = {dtype: v.dtype, buffer: v.buffer}; // Normalize shape to a list if(Number.isInteger(v.shape)) { diff --git a/src/lib/coerce.js b/src/lib/coerce.js index c2d931f7b3a..c29baeee79a 100644 --- a/src/lib/coerce.js +++ b/src/lib/coerce.js @@ -32,7 +32,7 @@ exports.valObjectMeta = { 'The value could be an {array}', 'noting that typed arrays (e.g. Float32Array) are also supported.', 'It could also be an object in the form of', - 'v: {, dtype: \'float32\', bvals: [/* ... */]}, shape: [dim0 (, dim1, (dim3))]', + 'v: {, dtype: \'float32\', buffer: [/* ... */]}, shape: [dim0 (, dim1, (dim3))]', 'otherwise, it would be ignored.' ].join(' '), requiredOpts: [], @@ -50,7 +50,7 @@ exports.valObjectMeta = { var uid = propOut.obj.uid; var module = propOut.obj._module; - if(v.bvals.constructor === ArrayBuffer || !uid || !module) { + if(v.buffer.constructor === ArrayBuffer || !uid || !module) { // Already an ArrayBuffer // decoding is cheap propOut.set(decodeTypedArraySpec(v)); @@ -59,11 +59,11 @@ exports.valObjectMeta = { var cache = module._b64BufferCache || {}; // Check cache - var cachedBuffer = ((cache[uid] || {})[prop] || {})[v.bvals]; + var cachedBuffer = ((cache[uid] || {})[prop] || {})[v.buffer]; if(cachedBuffer !== undefined) { // Use cached array buffer instead of base64 encoded // string - v.bvals = cachedBuffer; + v.buffer = cachedBuffer; propOut.set(decodeTypedArraySpec(v)); } else { // Not in so cache decode @@ -76,7 +76,7 @@ exports.valObjectMeta = { // Clear any prior cache value (only store one per // trace property cache[uid][prop] = {}; - cache[uid][prop][v.bvals] = decoded.buffer; + cache[uid][prop][v.buffer] = decoded.buffer; module._b64BufferCache = cache; } } From 38e10bb6b313ca667a29dfd12e3bd6acbef4d6fe Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 15:28:23 -0500 Subject: [PATCH 6/9] remove big for consistency --- src/lib/array.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index 430e4c72aa0..65fe0583ef9 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -75,8 +75,8 @@ var typedArrays = { uint32: typeof Uint32Array !== 'undefined' ? Uint32Array : null, float32: typeof Float32Array !== 'undefined' ? Float32Array : null, float64: typeof Float64Array !== 'undefined' ? Float64Array : null, - bigint64: typeof BigInt64Array !== 'undefined' ? BigInt64Array : null, - biguint64: typeof BigUint64Array !== 'undefined' ? BigUint64Array : null + int64: typeof BigInt64Array !== 'undefined' ? BigInt64Array : null, + uint64: typeof BigUint64Array !== 'undefined' ? BigUint64Array : null }; exports.typedArrays = typedArrays; From 104382711ee192f4de488f3c3e4497901a5c6430 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 16:05:14 -0500 Subject: [PATCH 7/9] Revert "bvals -> buffer" This reverts commit 5079fc79 --- src/lib/array.js | 10 +++++----- src/lib/coerce.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index 65fe0583ef9..4cc7be0bb18 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -86,12 +86,12 @@ exports.decodeTypedArraySpec = function(v) { v = coerceTypedArraySpec(v); var T = typedArrays[v.dtype]; var buffer; - if(v.buffer.constructor === ArrayBuffer) { + if(v.bvals.constructor === ArrayBuffer) { // Already an ArrayBuffer - buffer = v.buffer; + buffer = v.bvals; } else { // Decode, assuming a string - buffer = b64.decode(v.buffer); + buffer = b64.decode(v.bvals); } // Check if 1d shape. If so, we're done @@ -143,7 +143,7 @@ exports.decodeTypedArraySpec = function(v) { function isTypedArraySpec(v) { // Assume v has not passed through - return isPlainObject(v) && typedArrays[v.dtype] && v.buffer && ( + return isPlainObject(v) && typedArrays[v.dtype] && v.bvals && ( Number.isInteger(v.shape) || (isArrayOrTypedArray(v.shape) && v.shape.length > 0 && @@ -154,7 +154,7 @@ exports.isTypedArraySpec = isTypedArraySpec; function coerceTypedArraySpec(v) { // Assume isTypedArraySpec passed - var coerced = {dtype: v.dtype, buffer: v.buffer}; + var coerced = {dtype: v.dtype, bvals: v.bvals}; // Normalize shape to a list if(Number.isInteger(v.shape)) { diff --git a/src/lib/coerce.js b/src/lib/coerce.js index c29baeee79a..c2d931f7b3a 100644 --- a/src/lib/coerce.js +++ b/src/lib/coerce.js @@ -32,7 +32,7 @@ exports.valObjectMeta = { 'The value could be an {array}', 'noting that typed arrays (e.g. Float32Array) are also supported.', 'It could also be an object in the form of', - 'v: {, dtype: \'float32\', buffer: [/* ... */]}, shape: [dim0 (, dim1, (dim3))]', + 'v: {, dtype: \'float32\', bvals: [/* ... */]}, shape: [dim0 (, dim1, (dim3))]', 'otherwise, it would be ignored.' ].join(' '), requiredOpts: [], @@ -50,7 +50,7 @@ exports.valObjectMeta = { var uid = propOut.obj.uid; var module = propOut.obj._module; - if(v.buffer.constructor === ArrayBuffer || !uid || !module) { + if(v.bvals.constructor === ArrayBuffer || !uid || !module) { // Already an ArrayBuffer // decoding is cheap propOut.set(decodeTypedArraySpec(v)); @@ -59,11 +59,11 @@ exports.valObjectMeta = { var cache = module._b64BufferCache || {}; // Check cache - var cachedBuffer = ((cache[uid] || {})[prop] || {})[v.buffer]; + var cachedBuffer = ((cache[uid] || {})[prop] || {})[v.bvals]; if(cachedBuffer !== undefined) { // Use cached array buffer instead of base64 encoded // string - v.buffer = cachedBuffer; + v.bvals = cachedBuffer; propOut.set(decodeTypedArraySpec(v)); } else { // Not in so cache decode @@ -76,7 +76,7 @@ exports.valObjectMeta = { // Clear any prior cache value (only store one per // trace property cache[uid][prop] = {}; - cache[uid][prop][v.buffer] = decoded.buffer; + cache[uid][prop][v.bvals] = decoded.buffer; module._b64BufferCache = cache; } } From 8d84f3e212c2203825a1a9ce4ca6d73f19520d58 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sat, 28 Nov 2020 16:15:32 -0500 Subject: [PATCH 8/9] Run isArray1D on decoded array not spec --- src/traces/heatmap/xyz_defaults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/heatmap/xyz_defaults.js b/src/traces/heatmap/xyz_defaults.js index 8be45ca87f0..cb0c912e965 100644 --- a/src/traces/heatmap/xyz_defaults.js +++ b/src/traces/heatmap/xyz_defaults.js @@ -21,7 +21,7 @@ module.exports = function handleXYZDefaults(traceIn, traceOut, coerce, layout, x if(z === undefined || !z.length) return 0; - if(Lib.isArray1D(traceIn.z)) { + if(Lib.isArray1D(z)) { x = coerce(xName); y = coerce(yName); From 2381debfb89d4e7e638165021b4577fe35935c13 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Sun, 29 Nov 2020 07:29:27 -0500 Subject: [PATCH 9/9] Plotly.js doesn't currently handle BigInt64/BigUint64 arrays. The fact that elements aren't regular numbers, and aren't compatible with the Math module functions would make this challenging. --- src/lib/array.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/array.js b/src/lib/array.js index 4cc7be0bb18..8c00c51c3fe 100644 --- a/src/lib/array.js +++ b/src/lib/array.js @@ -75,8 +75,6 @@ var typedArrays = { uint32: typeof Uint32Array !== 'undefined' ? Uint32Array : null, float32: typeof Float32Array !== 'undefined' ? Float32Array : null, float64: typeof Float64Array !== 'undefined' ? Float64Array : null, - int64: typeof BigInt64Array !== 'undefined' ? BigInt64Array : null, - uint64: typeof BigUint64Array !== 'undefined' ? BigUint64Array : null }; exports.typedArrays = typedArrays;