diff --git a/tfjs-core/src/debug_mode_test.ts b/tfjs-core/src/debug_mode_test.ts index d79eca55c0d..6570dd44131 100644 --- a/tfjs-core/src/debug_mode_test.ts +++ b/tfjs-core/src/debug_mode_test.ts @@ -55,18 +55,38 @@ describeWithFlags('debug on', SYNC_BACKEND_ENVS, () => { expect(a).toThrowError(); }); - it('debug mode errors when infinities in op output', () => { + it('debug mode errors when infinities in op output', async () => { const a = tf.tensor1d([1, 2, 3, 4]); const b = tf.tensor1d([2, -1, 0, 3]); - const c = () => a.div(b); - expect(c).toThrowError(); + + spyOn(console, 'error'); + + const c = async () => { + const result = a.div(b); + // Must await result so we know exception would have happened by the + // time we call `expect`. + await result.data(); + }; + + await c(); + + expect(console.error).toHaveBeenCalled(); }); - it('debug mode errors when nans in op output', () => { + it('debug mode errors when nans in op output', async () => { const a = tf.tensor1d([-1, 2]); const b = tf.tensor1d([0.5, 1]); - const c = () => a.pow(b); - expect(c).toThrowError(); + + spyOn(console, 'error'); + + const c = async () => { + const result = a.pow(b); + await result.data(); + }; + + await c(); + + expect(console.error).toHaveBeenCalled(); }); it('debug mode errors when nans in oneHot op (tensorlike), int32', () => { diff --git a/tfjs-core/src/index.ts b/tfjs-core/src/index.ts index 453925df6f9..4a67212d042 100644 --- a/tfjs-core/src/index.ts +++ b/tfjs-core/src/index.ts @@ -55,7 +55,7 @@ export {RMSPropOptimizer} from './optimizers/rmsprop_optimizer'; export {SGDOptimizer} from './optimizers/sgd_optimizer'; export {Scalar, Tensor, Tensor1D, Tensor2D, Tensor3D, Tensor4D, Tensor5D, TensorBuffer, variable, Variable} from './tensor'; export {GradSaveFunc, NamedTensorMap, TensorContainer, TensorContainerArray, TensorContainerObject} from './tensor_types'; -export {DataType, DataTypeMap, DataValues, Rank, ShapeMap, TensorLike} from './types'; +export {DataType, DataTypeMap, DataValues, Rank, RecursiveArray, ShapeMap, TensorLike} from './types'; export * from './ops/ops'; export {LSTMCellFunc} from './ops/lstm'; @@ -65,7 +65,7 @@ export * from './train'; export * from './globals'; export {customGrad, grad, grads, valueAndGrad, valueAndGrads, variableGrads} from './gradients'; -export {TimingInfo} from './engine'; +export {TimingInfo, MemoryInfo} from './engine'; export {ENV, Environment} from './environment'; export {Platform} from './platforms/platform'; diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index bfaa9d80950..17cb5831eac 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -18,7 +18,7 @@ import {BackendTimer} from './backends/backend'; import {Tensor} from './tensor'; import {NamedTensorMap} from './tensor_types'; -import {TypedArray} from './types'; +import {DataType, DataTypeMap, TypedArray} from './types'; import * as util from './util'; export class Profiler { @@ -39,17 +39,20 @@ export class Profiler { const results: Tensor[] = Array.isArray(result) ? result : [result] as Tensor[]; results.forEach(r => { - const vals = r.dataSync(); - util.checkComputationForErrors(vals, r.dtype, name); + // Dangling promise here because we don't want to propagate up + // asynchronicity. + r.data().then(vals => { + checkComputationForErrors(vals, r.dtype, name); - timer.then(timing => { - let extraInfo = ''; - if (timing.getExtraProfileInfo != null) { - extraInfo = timing.getExtraProfileInfo(); - } + timer.then(timing => { + let extraInfo = ''; + if (timing.getExtraProfileInfo != null) { + extraInfo = timing.getExtraProfileInfo(); + } - this.logger.logKernelProfile( - name, r, vals, timing.kernelMs, inputs, extraInfo); + this.logger.logKernelProfile( + name, r, vals, timing.kernelMs, inputs, extraInfo); + }); }); }); @@ -57,6 +60,26 @@ export class Profiler { } } +// Create a custom exception class so it can be stubbed in tests. +export function ProfilerException(msg: string) { + console.error(msg); +} + +export function checkComputationForErrors( + vals: DataTypeMap[D], dtype: D, name: string): void { + if (dtype !== 'float32') { + // Only floating point computations will generate NaN values + return; + } + for (let i = 0; i < vals.length; i++) { + const num = vals[i] as number; + if (isNaN(num) || !isFinite(num)) { + // Throwing custom exception so behavior is testable. + throw ProfilerException(`The result of the '${name}' is ${num}.`); + } + } +} + export class Logger { logKernelProfile( name: string, result: Tensor, vals: TypedArray, timeMs: number, diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 445a3c54789..3a7f6545bb1 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -18,7 +18,7 @@ import {BackendTimer, BackendTimingInfo} from './backends/backend'; import * as tf from './index'; import {describeWithFlags, SYNC_BACKEND_ENVS} from './jasmine_util'; -import {Logger, Profiler} from './profiler'; +import {checkComputationForErrors, Logger, Profiler} from './profiler'; import {Tensor} from './tensor'; import {TypedArray} from './types'; @@ -129,3 +129,27 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { }, delayMs * 2); }); }); + +describe('profiler.checkComputationForErrors', () => { + it('Float32Array has NaN', () => { + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', '')) + .toThrow(); + }); + + it('Float32Array has Infinity', () => { + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', '')) + .toThrow(); + }); + + it('Float32Array no NaN', () => { + // Int32 and Bool NaNs should not trigger an error. + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, -1, 4, 255]), 'float32', '')) + .not.toThrow(); + }); +}); diff --git a/tfjs-core/src/util.ts b/tfjs-core/src/util.ts index f9817c417cc..e36cbd0e5b9 100644 --- a/tfjs-core/src/util.ts +++ b/tfjs-core/src/util.ts @@ -405,20 +405,6 @@ export function getArrayFromDType( return values as DataTypeMap[D]; } -export function checkComputationForErrors( - vals: DataTypeMap[D], dtype: D, name: string): void { - if (dtype !== 'float32') { - // Only floating point computations will generate NaN values - return; - } - for (let i = 0; i < vals.length; i++) { - const num = vals[i] as number; - if (isNaN(num) || !isFinite(num)) { - throw Error(`The result of the '${name}' is ${num}.`); - } - } -} - export function checkConversionForErrors( vals: DataTypeMap[D]|number[], dtype: D): void { for (let i = 0; i < vals.length; i++) { diff --git a/tfjs-core/src/util_test.ts b/tfjs-core/src/util_test.ts index 7ac5ab1821b..65a1b230f6a 100644 --- a/tfjs-core/src/util_test.ts +++ b/tfjs-core/src/util_test.ts @@ -407,30 +407,6 @@ describe('util.squeezeShape', () => { }); }); -describe('util.checkComputationForErrors', () => { - it('Float32Array has NaN', () => { - expect( - () => util.checkComputationForErrors( - new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', '')) - .toThrowError(); - }); - - it('Float32Array has Infinity', () => { - expect( - () => util.checkComputationForErrors( - new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', '')) - .toThrowError(); - }); - - it('Float32Array no NaN', () => { - // Int32 and Bool NaNs should not trigger an error. - expect( - () => util.checkComputationForErrors( - new Float32Array([1, 2, 3, 4, -1, 255]), 'float32', '')) - .not.toThrowError(); - }); -}); - describe('util.checkConversionForErrors', () => { it('Float32Array has NaN', () => { expect( diff --git a/tfjs-webgpu/package.json b/tfjs-webgpu/package.json index f257f356207..69e8cd80d19 100644 --- a/tfjs-webgpu/package.json +++ b/tfjs-webgpu/package.json @@ -18,7 +18,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@tensorflow/tfjs-core": "1.2.1", + "@tensorflow/tfjs-core": "1.2.7", "@types/jasmine": "~2.5.53", "clang-format": "~1.2.2", "http-server": "~0.10.0", @@ -34,6 +34,7 @@ "rollup-plugin-commonjs": "9.1.3", "rollup-plugin-node-resolve": "3.3.0", "rollup-plugin-typescript2": "0.13.0", + "rollup-plugin-terser": "^5.1.1", "rollup-plugin-uglify": "~3.0.0", "tslint": "~5.11.0", "tslint-no-circular-imports": "^0.5.0", @@ -47,4 +48,4 @@ "peerDependencies": { "@tensorflow/tfjs-core": "1.2.1" } -} \ No newline at end of file +} diff --git a/tfjs-webgpu/rollup.config.js b/tfjs-webgpu/rollup.config.js index aa763590c67..8ff5d41bb34 100644 --- a/tfjs-webgpu/rollup.config.js +++ b/tfjs-webgpu/rollup.config.js @@ -26,9 +26,7 @@ function config({plugins = [], output = {}, external = []}) { return { input: 'src/index.ts', plugins: [ - typescript({ - tsconfigOverride: {compilerOptions: {module: 'ES2015'}} - }), + typescript({tsconfigOverride: {compilerOptions: {module: 'ES2015'}}}), node(), // Polyfill require() from dependencies. commonjs({ diff --git a/tfjs-webgpu/src/backend_webgpu.ts b/tfjs-webgpu/src/backend_webgpu.ts index 19fe0055db7..7253798938c 100644 --- a/tfjs-webgpu/src/backend_webgpu.ts +++ b/tfjs-webgpu/src/backend_webgpu.ts @@ -19,7 +19,7 @@ import './flags_webgpu'; -import {backend_util, DataMover, DataType, ENV, KernelBackend, Rank, ShapeMap, Tensor, Tensor2D, Tensor3D, Tensor4D, util} from '@tensorflow/tfjs-core'; +import {backend_util, DataMover, DataType, ENV, KernelBackend, Rank, ShapeMap, Tensor, Tensor2D, Tensor3D, Tensor4D, TimingInfo, util} from '@tensorflow/tfjs-core'; import * as shaderc from '@webgpu/shaderc'; import {BufferManager} from './buffer_manager'; @@ -40,12 +40,20 @@ import {UnaryOpProgram} from './kernels/unary_op_webgpu'; import * as webgpu_program from './kernels/webgpu_program'; import {WebGPUBinary} from './kernels/webgpu_program'; -// TODO: Delete this and import from core once new release is published. +// START TO-IMPORT-FROM-CORE ============================ +// TODO(annyuan): Delete definitions in this section and import from core once +// new release is published. type MemoryInfo = { numTensors: number; numDataBuffers: number; numBytes: number; unreliable?: boolean; reasons: string[]; }; +// tslint:disable-next-line:no-any +interface RecursiveArray { + [index: number]: T|RecursiveArray; +} +// END TO-IMPORT-FROM-CORE ============================== + export interface WebGPUMemoryInfo extends MemoryInfo { numBytesInGPU: number; unreliable: boolean; @@ -66,6 +74,22 @@ type TensorInfo = { interface DataId {} +export interface CPUTimerQuery { + startMs: number; + endMs: number; +} + +export type WebGPUKernelInfo = { + name: string; query: Promise; +}; + +export type TimerNode = RecursiveArray|WebGPUKernelInfo; + +export interface WebGPUTimingInfo extends TimingInfo { + uploadWaitMs: number; + downloadWaitMs: number; +} + const DEFAULT_GPUBUFFER_USAGE = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST; @@ -86,6 +110,11 @@ export class WebGPUBackend extends KernelBackend { private disposed = false; + private programTimersStack: TimerNode[]; + private activeTimers: TimerNode[]; + private uploadWaitMs = 0; + private downloadWaitMs = 0; + constructor(device: GPUDevice, shaderc: shaderc.Shaderc) { super(); this.binaryCache = {}; @@ -244,6 +273,51 @@ export class WebGPUBackend extends KernelBackend { return dataAsTypedArray; } + async time(f: () => void): Promise { + const oldActiveTimers = this.activeTimers; + const newActiveTimers: TimerNode[] = []; + + let outerMostTime = false; + if (this.programTimersStack == null) { + this.programTimersStack = newActiveTimers; + outerMostTime = true; + } else { + this.activeTimers.push(newActiveTimers); + } + this.activeTimers = newActiveTimers; + + f(); + + const flattenedActiveTimerQueries = + util.flatten(this.activeTimers.map((d: WebGPUKernelInfo) => d.query)) + .filter(d => d != null); + const flattenedActiveTimerNames = + util.flatten(this.activeTimers.map((d: WebGPUKernelInfo) => d.name)) + .filter(d => d != null); + + this.activeTimers = oldActiveTimers; + + if (outerMostTime) { + this.programTimersStack = null; + } + + const kernelMs = await Promise.all(flattenedActiveTimerQueries); + + const res: WebGPUTimingInfo = { + uploadWaitMs: this.uploadWaitMs, + downloadWaitMs: this.downloadWaitMs, + kernelMs: util.sum(kernelMs), + getExtraProfileInfo: () => + kernelMs.map((d, i) => ({name: flattenedActiveTimerNames[i], ms: d})) + .map(d => `${d.name}: ${d.ms}`) + .join(', '), + wallMs: null + }; + this.uploadWaitMs = 0; + this.downloadWaitMs = 0; + return res; + } + private getAndSavePipeline( key: string, getBinary: () => webgpu_program.WebGPUBinary) { if (!(key in this.binaryCache)) { @@ -273,6 +347,20 @@ export class WebGPUBackend extends KernelBackend { }; } + startTimer() { + return {startMs: util.now(), endMs: 0}; + } + + endTimer(query: CPUTimerQuery) { + query.endMs = util.now(); + return query; + } + + async getQueryTime(query: CPUTimerQuery): Promise { + const timerQuery = query; + return timerQuery.endMs - timerQuery.startMs; + } + private compileAndRun< K extends {dtype: DataType, size: number, dataId: {}, shape: number[]}>( program: webgpu_program.WebGPUProgram, inputs: Tensor[], output?: Tensor, @@ -345,6 +433,12 @@ export class WebGPUBackend extends KernelBackend { this.device, program, inputsData, output, uniforms); }); + const shouldTimeProgram = this.activeTimers != null; + let query: CPUTimerQuery; + if (shouldTimeProgram) { + query = this.startTimer(); + } + // Creating bind groups on the fly should never be a bottleneck. const bg = webgpu_program.makeBindGroup( this.device, bindGroupLayout, inputs.map(t => this.tensorToBinding(t)), @@ -370,6 +464,12 @@ export class WebGPUBackend extends KernelBackend { this.releaseBuffer( uniforms.resource.buffer, uniformData.byteLength, GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM); + + if (shouldTimeProgram) { + query = this.endTimer(query); + this.activeTimers.push( + {name: program.constructor.name, query: this.getQueryTime(query)}); + } return output as {} as K; } diff --git a/tfjs-webgpu/tsconfig.json b/tfjs-webgpu/tsconfig.json index ecb732e2195..1dd0670aac9 100644 --- a/tfjs-webgpu/tsconfig.json +++ b/tfjs-webgpu/tsconfig.json @@ -7,6 +7,7 @@ "node_modules/" ], "compilerOptions": { - "outDir": "./dist" + "outDir": "./dist", + "target": "es2017" } } diff --git a/tfjs-webgpu/yarn.lock b/tfjs-webgpu/yarn.lock index cb989bf7df9..d4bcd6e9fed 100644 --- a/tfjs-webgpu/yarn.lock +++ b/tfjs-webgpu/yarn.lock @@ -2,18 +2,33 @@ # yarn lockfile v1 -"@tensorflow/tfjs-core@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.2.1.tgz#0ff54aa7fd412b8c17e39f6ec5a97bf032e8f530" - integrity sha512-cpSHl+tP7cketq0cAyJPbIGxNlPV7mR6lkMLLDvZAmZUTBSyBufCdJg/KwgjHMZksE/KqjL4/RyccOGBAQcb7g== +"@babel/code-frame@^7.0.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@tensorflow/tfjs-core@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.2.7.tgz#522328de16470aa9f7c15b91e4b68616f425002a" + integrity sha512-RsXavYKMc0MOcCmOyD7HE8am1tWlDGXl0nJbsdib7ubmvMuH6KnrZ302eTYV7k1RMq+/ukkioJmCcw13hopuHQ== + dependencies: + "@types/offscreencanvas" "~2019.3.0" "@types/seedrandom" "2.4.27" "@types/webgl-ext" "0.0.30" "@types/webgl2" "0.0.4" node-fetch "~2.1.2" seedrandom "2.4.3" - optionalDependencies: - rollup-plugin-visualizer "~1.1.1" "@types/estree@0.0.38": version "0.0.38" @@ -30,6 +45,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.4.tgz#f83ec3c3e05b174b7241fadeb6688267fe5b22ca" integrity sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ== +"@types/offscreencanvas@~2019.3.0": + version "2019.3.0" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553" + integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== + "@types/seedrandom@2.4.27": version "2.4.27" resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41" @@ -501,6 +521,11 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + buffer-indexof-polyfill@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz#a9fb806ce8145d5428510ce72f278bb363a638bf" @@ -600,7 +625,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.3.0: +chalk@^2.0.0, chalk@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -719,7 +744,7 @@ combine-source-map@^0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" -commander@^2.12.1, commander@~2.20.0: +commander@^2.12.1, commander@^2.20.0, commander@~2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -1974,11 +1999,6 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2038,11 +2058,24 @@ jasmine-core@~3.1.0: resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.1.0.tgz#a4785e135d5df65024dfc9224953df585bd2766c" integrity sha1-pHheE11d9lAk38kiSVPfWFvSdmw= +jest-worker@^24.6.0: + version "24.6.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3" + integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ== + dependencies: + merge-stream "^1.0.1" + supports-color "^6.1.0" + js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@3.x, js-yaml@^3.7.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" @@ -2338,6 +2371,13 @@ meow@^3.3.0: redent "^1.0.0" trim-newlines "^1.0.0" +merge-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= + dependencies: + readable-stream "^2.0.1" + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -2671,13 +2711,6 @@ opener@~1.4.0: resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg= -opn@^5.4.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - optimist@0.6.x, optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -3014,7 +3047,7 @@ read-pkg@^1.0.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -3168,6 +3201,17 @@ rollup-plugin-node-resolve@3.3.0: is-module "^1.0.0" resolve "^1.1.6" +rollup-plugin-terser@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.1.1.tgz#e9d2545ec8d467f96ba99b9216d2285aad8d5b66" + integrity sha512-McIMCDEY8EU6Y839C09UopeRR56wXHGdvKKjlfiZG/GrP6wvZQ62u2ko/Xh1MNH2M9WDL+obAAHySljIZYCuPQ== + dependencies: + "@babel/code-frame" "^7.0.0" + jest-worker "^24.6.0" + rollup-pluginutils "^2.8.1" + serialize-javascript "^1.7.0" + terser "^4.1.0" + rollup-plugin-typescript2@0.13.0: version "0.13.0" resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.13.0.tgz#5fc838657d05af82e04554832cadf06cdb32f657" @@ -3185,17 +3229,7 @@ rollup-plugin-uglify@~3.0.0: dependencies: uglify-es "^3.3.7" -rollup-plugin-visualizer@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-1.1.1.tgz#454ae0aed23845407ebfb81cc52114af308d6d90" - integrity sha512-7xkSKp+dyJmSC7jg2LXqViaHuOnF1VvIFCnsZEKjrgT5ZVyiLLSbeszxFcQSfNJILphqgAEmWAUz0Z4xYScrRw== - dependencies: - mkdirp "^0.5.1" - opn "^5.4.0" - source-map "^0.7.3" - typeface-oswald "0.0.54" - -rollup-pluginutils@^2.0.1: +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz#8fa6dd0697344938ef26c2c09d2488ce9e33ce97" integrity sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg== @@ -3247,6 +3281,11 @@ seedrandom@2.4.3: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +serialize-javascript@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" + integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -3372,12 +3411,20 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@~0.5.12: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@0.6.1, source-map@^0.6.1, source-map@~0.6.1: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -3567,6 +3614,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" @@ -3580,6 +3634,15 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +terser@^4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.1.4.tgz#4478b6a08bb096a61e793fea1a4434408bab936c" + integrity sha512-+ZwXJvdSwbd60jG0Illav0F06GDJF0R4ydZ21Q3wGAFKoBGyJGo34F63vzJHgvYxc1ukOtIjvwEvl9MkjzM6Pg== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + through2@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.0.tgz#468b461df9cd9fcc170f22ebf6852e467e578ff2" @@ -3709,11 +3772,6 @@ type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" -typeface-oswald@0.0.54: - version "0.0.54" - resolved "https://registry.yarnpkg.com/typeface-oswald/-/typeface-oswald-0.0.54.tgz#1e253011622cdd50f580c04e7d625e7f449763d7" - integrity sha512-U1WMNp4qfy4/3khIfHMVAIKnNu941MXUfs3+H9R8PFgnoz42Hh9pboSFztWr86zut0eXC8byalmVhfkiKON/8Q== - typescript@3.3.3333: version "3.3.3333" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6"