diff --git a/modules/core/src/lib/encode.js b/modules/core/src/lib/encode.js index 8a77d38308..cd233adb6e 100644 --- a/modules/core/src/lib/encode.js +++ b/modules/core/src/lib/encode.js @@ -1,9 +1,9 @@ -export function encode(data, writer, options, url) { +export async function encode(data, writer, options, url) { if (writer.encode) { - return writer.encode(data, options); + return await writer.encode(data, options); } if (writer.encodeSync) { - return Promise.resolve(writer.encodeSync(data, options)); + return writer.encodeSync(data, options); } // TODO - Use encodeToBatches? throw new Error('Writer could not encode data'); diff --git a/modules/core/src/lib/loader-utils/get-data.js b/modules/core/src/lib/loader-utils/get-data.js index de1fe9db1e..3ce8a9dd46 100644 --- a/modules/core/src/lib/loader-utils/get-data.js +++ b/modules/core/src/lib/loader-utils/get-data.js @@ -59,8 +59,9 @@ export async function getArrayBufferOrStringFromData(data, loader) { } if (isFetchResponse(data)) { - await checkFetchResponseStatus(data); - return loader.binary ? await data.arrayBuffer() : await data.text(); + const response = data; + await checkFetchResponseStatus(response); + return loader.binary ? await response.arrayBuffer() : await response.text(); } // if (isIterable(data) || isAsyncIterable(data)) { diff --git a/modules/core/src/lib/loader-utils/parse-with-worker.js b/modules/core/src/lib/loader-utils/parse-with-worker.js index 2cf9c496d0..b6b8497e00 100644 --- a/modules/core/src/lib/loader-utils/parse-with-worker.js +++ b/modules/core/src/lib/loader-utils/parse-with-worker.js @@ -4,6 +4,8 @@ import WorkerFarm from '../../worker-utils/worker-farm'; import {getTransferList} from '../../worker-utils/get-transfer-list'; import {parse} from '../parse'; +const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest'; + export function canParseWithWorker(loader, data, options, context) { if (!WorkerFarm.isSupported()) { return false; @@ -37,10 +39,12 @@ export default function parseWithWorker(loader, data, options, context) { // TODO - decide how to handle logging on workers options = JSON.parse(JSON.stringify(options)); - return workerFarm.process(workerSource, `loaders.gl-${workerName}`, { + const warning = loader.version !== VERSION ? `(core version ${VERSION})` : ''; + + return workerFarm.process(workerSource, `loaders.gl@${loader.version}${warning}:${workerName}`, { arraybuffer: toArrayBuffer(data), options, - source: `loaders.gl@${__VERSION__}`, // Lets worker ignore unrelated messages + source: `loaders.gl@${VERSION}`, // Lets worker ignore unrelated messages type: 'parse' // For future extension }); } diff --git a/modules/core/src/worker-utils/worker-pool.js b/modules/core/src/worker-utils/worker-pool.js index c2919dc540..b2324df9fe 100644 --- a/modules/core/src/worker-utils/worker-pool.js +++ b/modules/core/src/worker-utils/worker-pool.js @@ -85,7 +85,7 @@ export default class WorkerPool { // Create fresh worker if we haven't yet created the max amount of worker threads for this worker source if (this.count < this.maxConcurrency) { this.count++; - const name = `${this.name.toLowerCase()}-worker-${this.count}-of-${this.maxConcurrency}`; + const name = `${this.name.toLowerCase()}-worker (#${this.count} of ${this.maxConcurrency})`; return new WorkerThread({source: this.source, onMessage: this.onMessage, name}); } diff --git a/modules/core/test/core.bench.js b/modules/core/test/core.bench.js index ec5c16935a..19bfd657d9 100644 --- a/modules/core/test/core.bench.js +++ b/modules/core/test/core.bench.js @@ -1,26 +1,29 @@ -const LENGTH = 10000; +const LENGTH = 1e3; const ARRAY = new Array(LENGTH).fill(0); // TODO - Async benchmarks pending probe.gl update -// async function *asyncIterator(array) { -// for (const element of array) { -// yield Promise.resolve(element); -// } -// } +async function* asyncIterator(array) { + for (const element of array) { + yield Promise.resolve(element); + } +} export default function coreBench(bench) { - return bench.group('Core Module - Async Iteration').add('Normal Iteration 10K', () => { + bench.group('Core Module - Async Iteration'); + + bench.add('Sync Iteration over 1000 elements', () => { let sum = 0; for (const element of ARRAY) { sum += element; } return sum; }); - // .addAsync('Async Iteration 10K', async () => { - // let sum = 0; - // for await (const element of asyncIterator(ARRAY)) { - // sum += element; - // } - // return sum; - // }); + + bench.addAsync('Async Iteration over 1000 elements', async () => { + let sum = 0; + for await (const element of asyncIterator(ARRAY)) { + sum += element; + } + return sum; + }); } diff --git a/modules/csv/package.json b/modules/csv/package.json index 7096acb48d..8358a7d081 100644 --- a/modules/csv/package.json +++ b/modules/csv/package.json @@ -32,5 +32,8 @@ "dependencies": { "@loaders.gl/core": "2.0.0-beta.8", "@loaders.gl/tables": "2.0.0-beta.8" + }, + "devDependencies": { + "d3-dsv": "^1.2.0" } } diff --git a/modules/csv/test/csv.bench.js b/modules/csv/test/csv.bench.js index b459d97580..45e0ed0eae 100644 --- a/modules/csv/test/csv.bench.js +++ b/modules/csv/test/csv.bench.js @@ -3,25 +3,29 @@ import {CSVLoader} from '@loaders.gl/csv'; const SAMPLE_CSV_URL = '@loaders.gl/csv/test/data/sample-very-long.csv'; -/* // Comparison loader based on D3 import {csvParseRows} from 'd3-dsv'; const D3CSVLoader = { - name: 'CSV', + name: 'D3 CSV', extensions: ['csv'], testText: null, - parseTextSync: csvParseRows + text: true, + parseTextSync: text => csvParseRows(text) }; -*/ export default async function csvBench(bench) { - const sample = await fetchFile(SAMPLE_CSV_URL); + const response = await fetchFile(SAMPLE_CSV_URL); + const sample = await response.text(); bench = bench.group('CSV Decode'); - bench = bench.addAsync('CSVLoader#decode', async () => { - parse(sample, CSVLoader); + bench = bench.addAsync('CSVLoader#parse', async () => { + return await parse(sample, CSVLoader); + }); + + bench = bench.addAsync('d3-dsv#parse', async () => { + return await parse(sample, D3CSVLoader); }); return bench; diff --git a/modules/draco/src/draco-writer.js b/modules/draco/src/draco-writer.js index 0a1d989747..189c0cf258 100644 --- a/modules/draco/src/draco-writer.js +++ b/modules/draco/src/draco-writer.js @@ -6,22 +6,28 @@ export default { extensions: ['drc'], encode, options: { - pointcloud: false // Set to true if pointcloud (mode: 0, no indices) - // Draco Compression Parameters - // method: 'MESH_EDGEBREAKER_ENCODING', - // speed: [5, 5], - // quantization: { - // POSITION: 10 - // } + draco: { + pointcloud: false // Set to true if pointcloud (mode: 0, no indices) + // Draco Compression Parameters + // method: 'MESH_EDGEBREAKER_ENCODING', + // speed: [5, 5], + // quantization: { + // POSITION: 10 + // } + } } }; async function encode(data, options) { + // DEPRECATED - remove support for options + const dracoOptions = (options && options.draco) || options || {}; + // Dynamically load draco - const {draco} = await loadDracoEncoderModule(options); + const {draco} = await loadDracoEncoderModule(options || {}); const dracoBuilder = new DRACOBuilder(draco); + try { - return dracoBuilder.encodeSync(data, options); + return dracoBuilder.encodeSync(data, dracoOptions); } finally { dracoBuilder.destroy(); } diff --git a/modules/draco/test/draco-compression-ratio.spec.js b/modules/draco/test/draco-compression-ratio.spec.js index edf2ba762a..c4ad8a47ae 100644 --- a/modules/draco/test/draco-compression-ratio.spec.js +++ b/modules/draco/test/draco-compression-ratio.spec.js @@ -23,7 +23,7 @@ test('DracoWriter#compressRawBuffers', async t => { // Encode mesh // TODO - Replace with draco writer - const compressedMesh = await encode({attributes}, DracoWriter, {pointcloud: true}); + const compressedMesh = await encode({attributes}, DracoWriter, {draco: {pointcloud: true}}); const meshSize = _getMeshSize(attributes); const ratio = meshSize / compressedMesh.byteLength; t.comment(`Draco compression ${compressedMesh.byteLength} bytes, ratio ${ratio.toFixed(1)}`); diff --git a/modules/draco/test/draco-writer.spec.js b/modules/draco/test/draco-writer.spec.js index 26681efead..27c4e328e9 100644 --- a/modules/draco/test/draco-writer.spec.js +++ b/modules/draco/test/draco-writer.spec.js @@ -9,19 +9,23 @@ const TEST_CASES = [ { title: 'Encoding Draco Mesh: SEQUENTIAL', options: { - method: 'MESH_SEQUENTIAL_ENCODING' + draco: { + method: 'MESH_SEQUENTIAL_ENCODING' + } } }, { title: 'Encoding Draco Mesh: EDGEBREAKER', options: { - method: 'MESH_EDGEBREAKER_ENCODING' + draco: { + method: 'MESH_EDGEBREAKER_ENCODING' + } } }, { title: 'Encoding Draco PointCloud (no indices)', options: { - pointcloud: true + draco: {pointcloud: true} } } ]; @@ -57,7 +61,7 @@ test('DracoWriter#encode(bunny.drc)', async t => { }; for (const tc of TEST_CASES) { - const mesh = tc.options.pointcloud ? POINTCLOUD : MESH; + const mesh = tc.options.draco.pointcloud ? POINTCLOUD : MESH; const meshSize = _getMeshSize(mesh.attributes); const compressedMesh = await encode(mesh, DracoWriter, tc.options); @@ -95,7 +99,7 @@ test('DracoParser#encode(bunny.drc)', async t => { }; for (const tc of TEST_CASES) { - const attributes = tc.options.pointcloud ? pointCloudAttributes : meshAttributes; + const attributes = tc.options.draco.pointcloud ? pointCloudAttributes : meshAttributes; const meshSize = _getMeshSize(attributes); const compressedMesh = await encode(attributes, DracoWriter, tc.options); diff --git a/modules/draco/test/draco.bench.js b/modules/draco/test/draco.bench.js index a71eb1ca9d..ffa7a94a26 100644 --- a/modules/draco/test/draco.bench.js +++ b/modules/draco/test/draco.bench.js @@ -1,6 +1,5 @@ -import {fetchFile, parseSync, encode} from '@loaders.gl/core'; -import {_getMeshSize} from '@loaders.gl/loader-utils'; -import {DracoLoader, DracoWriter} from '@loaders.gl/draco'; +import {fetchFile, encode} from '@loaders.gl/core'; +import {DracoWriter} from '@loaders.gl/draco'; const OPTIONS = [ { @@ -29,23 +28,24 @@ export default async function dracoBench(bench) { POSITIONS: new Float32Array(POSITIONS), COLORS: new Uint8ClampedArray(COLORS) }; - const rawSize = _getMeshSize(attributes); - OPTIONS.forEach(options => { - const dracoEncoder = encode({attributes}, DracoWriter, options); - const compressedPointCloud = dracoEncoder.encodePointCloud(attributes); - // eslint-disable-next-line - console.log(`${options.name} compression rate: - ${((compressedPointCloud.byteLength / rawSize) * 100).toFixed(2)}%`); + for (const options of OPTIONS) { + bench.addAsync( + `DracoEncoder#pointcloud ${POSITIONS.byteLength / 12}#${options.name}`, + async () => { + return await encode(attributes, DracoWriter, {draco: {pointcloud: true}}); + } + ); - bench = bench - .add(`DracoEncoder#encode point cloud#${options.name}`, () => { - dracoEncoder.encodePointCloud(attributes); - }) - .add(`DracoDecoder#decode point cloud#${options.name}`, () => { - parseSync(compressedPointCloud, DracoLoader); - }); - }); + // TODO - COMMENT OUT until bench.addAsync is fixed (too many invocations) + // const compressedPointCloud = await encode(attributes, DracoWriter, {draco: {pointcloud: true}}); + // bench.addAsync( + // `DracoDecoder#pointcloud ${POSITIONS.byteLength / 12}#${options.name}`, + // async () => { + // return await parse(compressedPointCloud, DracoLoader, {worker: false}); + // } + // ); + } return bench; } diff --git a/modules/gltf/src/lib/deprecated/gltf-builder.js b/modules/gltf/src/lib/deprecated/gltf-builder.js index 2c041275ff..71e9e8cf20 100644 --- a/modules/gltf/src/lib/deprecated/gltf-builder.js +++ b/modules/gltf/src/lib/deprecated/gltf-builder.js @@ -171,7 +171,7 @@ export default class GLTFBuilder extends GLBBuilder { } attributes.mode = 0; - const compressedData = this.DracoWriter.encodeSync(attributes, {pointcloud: true}); + const compressedData = this.DracoWriter.encodeSync(attributes, {draco: {pointcloud: true}}); const bufferViewIndex = this.addBufferView(compressedData); diff --git a/modules/gltf/src/lib/extensions/UBER_draco_point_cloud_compression.js b/modules/gltf/src/lib/extensions/UBER_draco_point_cloud_compression.js index 973771bdc0..4191b7f764 100644 --- a/modules/gltf/src/lib/extensions/UBER_draco_point_cloud_compression.js +++ b/modules/gltf/src/lib/extensions/UBER_draco_point_cloud_compression.js @@ -8,7 +8,7 @@ function addCompressedPointCloud(attributes, options) { } attributes.mode = 0; - const compressedData = options.DracoWriter.encodeSync(attributes, {pointcloud: true}); + const compressedData = options.DracoWriter.encodeSync(attributes, {draco: {pointcloud: true}}); const bufferViewIndex = this.addBufferView(compressedData); diff --git a/modules/json/test/bench.js b/modules/json/test/bench.js deleted file mode 100644 index dbcc93dafd..0000000000 --- a/modules/json/test/bench.js +++ /dev/null @@ -1,5 +0,0 @@ -import clarinetBench from './clarinet/clarinet.bench'; - -export default async function jsonLoaderBench(suite) { - await clarinetBench(suite); -} diff --git a/modules/json/test/clarinet/clarinet.bench.js b/modules/json/test/clarinet/clarinet.bench.js index a4432eadf4..949a253f65 100644 --- a/modules/json/test/clarinet/clarinet.bench.js +++ b/modules/json/test/clarinet/clarinet.bench.js @@ -7,13 +7,13 @@ export default function clarinetBench(bench) { const parser = new ClarinetParser(); - bench.group('Clarinet - JSON parsing'); + bench.group('Clarinet - JSON parsing from string'); - bench.add('ClarinetParser(basic.json)', () => { - parser.write(STRING); + bench.add('JSON.parse (used by parseSync)', () => { + JSON.parse(STRING); }); - bench.add('JSON.parse(basic.json)', () => { - JSON.parse(STRING); + bench.add('ClarinetParser (used by parseInBatches)', () => { + parser.write(STRING); }); } diff --git a/modules/json/test/json-loader.bench.js b/modules/json/test/json-loader.bench.js new file mode 100644 index 0000000000..69b13f2857 --- /dev/null +++ b/modules/json/test/json-loader.bench.js @@ -0,0 +1,26 @@ +import {JSONLoader} from '@loaders.gl/json'; +import {load, loadInBatches} from '@loaders.gl/core'; + +import clarinetBench from './clarinet/clarinet.bench'; + +const GEOJSON_URL = '@loaders.gl/json/test/data/geojson-big.json'; + +export default async function jsonLoaderBench(suite) { + // Test underlying clarinet library + await clarinetBench(suite); + + suite.group('JSONLoader - loading from file'); + + suite.addAsync('load(JSONLoader) - Uses JSON.parse', async () => { + await load(GEOJSON_URL, JSONLoader); + }); + + suite.addAsync('loadInBatches(JSONLoader) - Uses Clarinet', async () => { + const asyncIterator = await loadInBatches(GEOJSON_URL, JSONLoader); + // const asyncIterator = await parseInBatches(STRING, JSONLoader); + const data = []; + for await (const batch of asyncIterator) { + data.push(...batch.data); + } + }); +} diff --git a/modules/json/test/json-loader.spec.js b/modules/json/test/json-loader.spec.js index ecd7a3aed7..36b376af9d 100644 --- a/modules/json/test/json-loader.spec.js +++ b/modules/json/test/json-loader.spec.js @@ -60,6 +60,7 @@ test('JSONLoader#loadInBatches(geojson.json, rows, batchSize = 10)', async t => t.end(); }); +// TODO - columnar table batch support not yet fixed /* test('JSONLoader#loadInBatches(geojson.json, columns, batchSize = auto)', async t => { const iterator = await loadInBatches(GEOJSON_PATH, JSONLoader, { @@ -72,7 +73,6 @@ test('JSONLoader#loadInBatches(geojson.json, columns, batchSize = auto)', async let batch; let batchCount = 0; let rowCount = 0; - for await (batch of iterator) { batchCount++; rowCount += batch.length; diff --git a/package.json b/package.json index 9a8a56e359..84f907e7de 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,6 @@ "publish": "ocular-publish", "prepare": "npm run build", "test": "ocular-test", - "test-fast": "ocular-test fast", - "test-browser": "ocular-test browser", - "bench": "ocular-test bench", - "bench-browser": "ocular-test bench-browser", "metrics": "./scripts/metrics.sh && ocular-metrics" }, "devDependencies": { @@ -43,7 +39,7 @@ "@luma.gl/core": "^8.0.0", "@luma.gl/debug": "^8.0.0", "@luma.gl/test-utils": "^8.0.0", - "@probe.gl/bench": "^3.1.1", + "@probe.gl/bench": "^3.2.0", "@probe.gl/test-utils": "^3.1.1", "arraybuffer-loader": "^1.0.7", "babel-loader": "^8.0.6", diff --git a/test/bench/bench-modules.js b/test/bench/bench-modules.js new file mode 100644 index 0000000000..2a75e69a65 --- /dev/null +++ b/test/bench/bench-modules.js @@ -0,0 +1,42 @@ +// Copyright (c) 2015 - 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +/* eslint-disable no-console, no-invalid-this */ +import {Bench} from '@probe.gl/bench'; + +import coreBench from '@loaders.gl/core/test/core.bench'; +import csvBench from '@loaders.gl/csv/test/csv.bench'; +import jsonBench from '@loaders.gl/json/test/json-loader.bench'; +import dracoBench from '@loaders.gl/draco/test/draco.bench'; + +const suite = new Bench({ + minIterations: 10 +}); + +(async function bench() { + // add tests + await coreBench(suite); + await csvBench(suite); + await jsonBench(suite); + await dracoBench(suite); + + // Run the suite + suite.run(); +})(); diff --git a/test/bench/index.js b/test/bench/index.js index f0a0a5ff90..89c53e7bbd 100644 --- a/test/bench/index.js +++ b/test/bench/index.js @@ -1,45 +1,11 @@ -// Copyright (c) 2015 - 2017 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - // Sets up aliases for file reader -require('.../aliases'); - -/* eslint-disable no-console, no-invalid-this */ -import {Bench} from '@probe.gl/bench'; +require('reify'); -import coreBench from '@loaders.gl/core/test/core.bench'; -import csvBench from '@loaders.gl/csv/test/csv.bench'; -import jsonBench from '@loaders.gl/json/test/json.bench'; -import dracoBench from '@loaders.gl/draco/test/draco.bench'; +require('@loaders.gl/polyfills'); -const suite = new Bench({ - minIterations: 10 -}); - -(async function bench() { - // add tests - await coreBench(suite); - await csvBench(suite); - await jsonBench(suite); - await dracoBench(suite); +// Sets up aliases for file reader +const ALIASES = require('../aliases'); +const {_addAliases} = require('@loaders.gl/loader-utils'); +_addAliases(ALIASES); - // Run the suite - suite.run(); -})(); +require('./bench-modules'); diff --git a/test/bench/node.js b/test/bench/node.js new file mode 100644 index 0000000000..68b05a0c8c --- /dev/null +++ b/test/bench/node.js @@ -0,0 +1,3 @@ +require('reify'); + +require('./index'); diff --git a/test/render/test-cases/point-cloud.js b/test/render/test-cases/point-cloud.js index 1433aa522e..6e13413c7d 100644 --- a/test/render/test-cases/point-cloud.js +++ b/test/render/test-cases/point-cloud.js @@ -81,9 +81,11 @@ export default [ const kittiPointCloudRaw = await loadKittiPointCloud(); // Encode/decode mesh with Draco const compressedMesh = await encode({attributes: kittiPointCloudRaw}, DracoWriter, { - pointcloud: true, - quantization: { - POSITION: 14 + draco: { + pointcloud: true, + quantization: { + POSITION: 14 + } } }); diff --git a/yarn.lock b/yarn.lock index 4b0f657ef8..8d50425037 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2929,16 +2929,16 @@ command-line-usage@5.0.5: table-layout "^0.4.3" typical "^2.6.1" +commander@2, commander@^2.18.0, commander@^2.20.0, commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.18.0, commander@^2.20.0, commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - commander@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.1.tgz#b67622721785993182e807f4883633e6401ba53c" @@ -3325,6 +3325,15 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= +d3-dsv@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.2.0.tgz#9d5f75c3a5f8abd611f74d3f5847b0d4338b885c" + integrity sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g== + dependencies: + commander "2" + iconv-lite "0.4" + rw "1" + dargs@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" @@ -5222,7 +5231,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -8403,6 +8412,11 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= + rxjs@^6.4.0, rxjs@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"