From 7a3e61a7b3d0cf00f438f25f624e0ea0f1e65391 Mon Sep 17 00:00:00 2001 From: Matthew Soulanille Date: Tue, 21 Mar 2023 10:40:14 -0700 Subject: [PATCH] Fix missing isTypedArray when mixing versions of @tensorflow packages (#7489) A new function, `isTypedArray` was added to the `platform` interface by #7181 and first published in tfjs-core 4.2.0. This made 4.2.0 incompatible with earlier versions of backends that implemented `platform`, such as node and react-native. This change adds a fallback to the use of `isTypedArray` so earlier versions of platforms that don't implement `isTypedArray` will not throw an error. Note that the fallback behavior may not be perfect, such as when running Jest tests in node. See #7175 for more details and upgrade all @tensorflow scoped packages to ^4.2.0 to avoid this. --- .../src/platforms/is_typed_array_browser.ts | 22 ++ tfjs-core/src/platforms/platform_browser.ts | 4 +- tfjs-core/src/util.ts | 8 +- tfjs-core/src/util_test.ts | 17 ++ tfjs-node-gpu/package.json | 6 +- tfjs-node/package.json | 6 +- tfjs-node/src/callbacks.ts | 3 +- tfjs-node/src/image_test.ts | 55 ++--- tfjs-node/src/io/file_system_test.ts | 193 +++++++----------- tfjs-node/src/nodejs_kernel_backend_test.ts | 19 +- tfjs-node/src/run_tests.ts | 35 ++-- tfjs-node/src/saved_model_test.ts | 99 +++------ tfjs-node/yarn.lock | 84 ++++---- tfjs/yarn.lock | 106 +++++++++- 14 files changed, 348 insertions(+), 309 deletions(-) create mode 100644 tfjs-core/src/platforms/is_typed_array_browser.ts diff --git a/tfjs-core/src/platforms/is_typed_array_browser.ts b/tfjs-core/src/platforms/is_typed_array_browser.ts new file mode 100644 index 0000000000..3469084084 --- /dev/null +++ b/tfjs-core/src/platforms/is_typed_array_browser.ts @@ -0,0 +1,22 @@ +/** + * @license + * Copyright 2023 Google LLC. + * Licensed 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. + * ============================================================================= + */ + +export function isTypedArrayBrowser(a: unknown): a is Uint8Array + | Float32Array | Int32Array | Uint8ClampedArray { + return a instanceof Float32Array || a instanceof Int32Array || + a instanceof Uint8Array || a instanceof Uint8ClampedArray; +} diff --git a/tfjs-core/src/platforms/platform_browser.ts b/tfjs-core/src/platforms/platform_browser.ts index 1a1c0d9943..d4b16ed220 100644 --- a/tfjs-core/src/platforms/platform_browser.ts +++ b/tfjs-core/src/platforms/platform_browser.ts @@ -23,6 +23,7 @@ import {BrowserLocalStorage, BrowserLocalStorageManager} from '../io/local_stora import {ModelStoreManagerRegistry} from '../io/model_management'; import {Platform} from './platform'; +import {isTypedArrayBrowser} from './is_typed_array_browser'; export class PlatformBrowser implements Platform { // According to the spec, the built-in encoder can do only UTF-8 encoding. @@ -93,8 +94,7 @@ export class PlatformBrowser implements Platform { isTypedArray(a: unknown): a is Uint8Array | Float32Array | Int32Array | Uint8ClampedArray { - return a instanceof Float32Array || a instanceof Int32Array || - a instanceof Uint8Array || a instanceof Uint8ClampedArray; + return isTypedArrayBrowser(a); } } diff --git a/tfjs-core/src/util.ts b/tfjs-core/src/util.ts index f60349b846..0a6cbbe632 100644 --- a/tfjs-core/src/util.ts +++ b/tfjs-core/src/util.ts @@ -16,6 +16,7 @@ */ import {env} from './environment'; +import {isTypedArrayBrowser} from './platforms/is_typed_array_browser'; import {BackendValues, DataType, RecursiveArray, TensorLike, TypedArray} from './types'; import * as base from './util_base'; export * from './util_base'; @@ -134,7 +135,12 @@ export function decodeString(bytes: Uint8Array, encoding = 'utf-8'): string { export function isTypedArray(a: {}): a is Float32Array|Int32Array|Uint8Array| Uint8ClampedArray { - return env().platform.isTypedArray(a); + // TODO(mattsoulanille): Remove this fallback in 5.0.0 + if (env().platform.isTypedArray != null) { + return env().platform.isTypedArray(a); + } else { + return isTypedArrayBrowser(a); + } } // NOTE: We explicitly type out what T extends instead of any so that diff --git a/tfjs-core/src/util_test.ts b/tfjs-core/src/util_test.ts index 9d9f0a229f..7e7ef6fbcb 100644 --- a/tfjs-core/src/util_test.ts +++ b/tfjs-core/src/util_test.ts @@ -20,6 +20,7 @@ import {ALL_ENVS, describeWithFlags} from './jasmine_util'; import {complex, scalar, tensor2d} from './ops/ops'; import {inferShape} from './tensor_util_env'; import * as util from './util'; +import {env} from './environment'; describe('Util', () => { it('Correctly gets size from shape', () => { @@ -133,6 +134,22 @@ describe('Util', () => { ]; expect(inferShape(a, 'string')).toEqual([2, 2, 1]); }); + describe('isTypedArray', () => { + it('checks if a value is a typed array', () => { + expect(util.isTypedArray(new Uint8Array([1,2,3]))).toBeTrue(); + expect(util.isTypedArray([1,2,3])).toBeFalse(); + }); + it('uses fallback if platform is missing isTypedArray', () => { + const tmpIsTypedArray = env().platform.isTypedArray; + try { + env().platform.isTypedArray = null; + expect(util.isTypedArray(new Uint8Array([1,2,3]))).toBeTrue(); + expect(util.isTypedArray([1,2,3])).toBeFalse(); + } finally { + env().platform.isTypedArray = tmpIsTypedArray; + } + }); + }); }); describe('util.flatten', () => { diff --git a/tfjs-node-gpu/package.json b/tfjs-node-gpu/package.json index 936f88bbe0..9e3557904c 100644 --- a/tfjs-node-gpu/package.json +++ b/tfjs-node-gpu/package.json @@ -45,17 +45,17 @@ }, "devDependencies": { "@tensorflow/tfjs-core": "link:../link-package/node_modules/@tensorflow/tfjs-core", - "@types/jasmine": "~2.8.6", + "@types/jasmine": "~4.0.3", "@types/node": "^10.5.1", "@types/progress": "^2.0.1", "@types/rimraf": "~2.0.2", "@types/yargs": "^13.0.3", "clang-format": "~1.8.0", - "jasmine": "~3.1.0", + "jasmine": "~4.2.1", "node-fetch": "~2.6.1", "nyc": "^15.1.0", "tmp": "^0.0.33", - "ts-node": "^5.0.1", + "ts-node": "~8.8.2", "tslint": "~6.1.3", "tslint-no-circular-imports": "^0.7.0", "typescript": "4.9.4", diff --git a/tfjs-node/package.json b/tfjs-node/package.json index a6cbf593d6..4ab0808f36 100644 --- a/tfjs-node/package.json +++ b/tfjs-node/package.json @@ -43,17 +43,17 @@ }, "devDependencies": { "@tensorflow/tfjs-core": "link:../link-package/node_modules/@tensorflow/tfjs-core", - "@types/jasmine": "~2.8.6", + "@types/jasmine": "~4.0.3", "@types/node": "^10.5.1", "@types/progress": "^2.0.1", "@types/rimraf": "~2.0.2", "@types/yargs": "^13.0.3", "clang-format": "~1.8.0", - "jasmine": "~3.1.0", + "jasmine": "~4.2.1", "node-fetch": "~2.6.1", "nyc": "^15.1.0", "tmp": "^0.0.33", - "ts-node": "^5.0.1", + "ts-node": "~8.8.2", "tslint": "~6.1.3", "tslint-no-circular-imports": "^0.7.0", "typescript": "4.9.4", diff --git a/tfjs-node/src/callbacks.ts b/tfjs-node/src/callbacks.ts index a674d8b41e..eabd3a3820 100644 --- a/tfjs-node/src/callbacks.ts +++ b/tfjs-node/src/callbacks.ts @@ -21,10 +21,11 @@ import * as ProgressBar from 'progress'; import {summaryFileWriter, SummaryFileWriter} from './tensorboard'; +type LogFunction = (message: string) => void; // A helper class created for testing with the jasmine `spyOn` method, which // operates only on member methods of objects. // tslint:disable-next-line:no-any -export const progressBarHelper: {ProgressBar: any, log: Function} = { +export const progressBarHelper: {ProgressBar: any, log: LogFunction} = { ProgressBar, log: console.log }; diff --git a/tfjs-node/src/image_test.ts b/tfjs-node/src/image_test.ts index 40f203313c..59889e32b5 100644 --- a/tfjs-node/src/image_test.ts +++ b/tfjs-node/src/image_test.ts @@ -273,50 +273,31 @@ describe('decode images', () => { .toBe(beforeNumTFTensors + 1); }); - it('throw error if request non int32 dtype', async done => { - try { - const uint8array = await getUint8ArrayFromImage( - 'test_objects/images/image_png_test.png'); - tf.node.decodeImage(uint8array, 0, 'uint8'); - done.fail(); - } catch (error) { - expect(error.message) - .toBe( - 'decodeImage could only return Tensor of type `int32` for now.'); - done(); - } + it('throw error if request non int32 dtype', async () => { + const uint8array = await getUint8ArrayFromImage( + 'test_objects/images/image_png_test.png'); + expect(() => tf.node.decodeImage(uint8array, 0, 'uint8')).toThrowError( + 'decodeImage could only return Tensor of type `int32` for now.'); }); - it('throw error if decode invalid image type', async done => { - try { - const uint8array = await getUint8ArrayFromImage('package.json'); - tf.node.decodeImage(uint8array); - done.fail(); - } catch (error) { - expect(error.message) - .toBe( - 'Expected image (BMP, JPEG, PNG, or GIF), ' + - 'but got unsupported image type'); - done(); - } + it('throw error if decode invalid image type', async () => { + const uint8array = await getUint8ArrayFromImage('package.json'); + expect(() => tf.node.decodeImage(uint8array)).toThrowError( + 'Expected image (BMP, JPEG, PNG, or GIF), ' + + 'but got unsupported image type'); }); - it('throw error if backend is not tensorflow', async done => { + it('throw error if backend is not tensorflow', async () => { + const testBackend = new TestKernelBackend(); + registerBackend('fake', () => testBackend); + setBackend('fake'); try { - const testBackend = new TestKernelBackend(); - registerBackend('fake', () => testBackend); - setBackend('fake'); - const uint8array = await getUint8ArrayFromImage( - 'test_objects/images/image_png_test.png'); - tf.node.decodeImage(uint8array); - done.fail(); - } catch (err) { - expect(err.message) - .toBe( - 'Expect the current backend to be "tensorflow", but got "fake"'); + 'test_objects/images/image_png_test.png'); + expect(() => tf.node.decodeImage(uint8array)).toThrowError( + 'Expect the current backend to be "tensorflow", but got "fake"'); + } finally { setBackend('tensorflow'); - done(); } }); }); diff --git a/tfjs-node/src/io/file_system_test.ts b/tfjs-node/src/io/file_system_test.ts index 3471e12e7d..7a918aa545 100644 --- a/tfjs-node/src/io/file_system_test.ts +++ b/tfjs-node/src/io/file_system_test.ts @@ -83,68 +83,53 @@ describe('File system IOHandler', () => { }; let testDir: string; - beforeEach(async done => { + beforeEach(async () => { testDir = await mkdtemp('tfjs_node_fs_test'); - done(); }); - afterEach(async done => { + afterEach(async () => { await rimrafPromise(testDir); - done(); }); - it('save succeeds with newly created directory', async done => { + it('save succeeds with newly created directory', async () => { const t0 = new Date(); const dir = path.join(testDir, 'save-destination'); const handler = tf.io.getSaveHandlers(`file://${dir}`)[0]; - handler - .save({ - modelTopology: modelTopology1, - weightSpecs: weightSpecs1, - weightData: weightData1, - }) - .then(async saveResult => { - expect(saveResult.modelArtifactsInfo.dateSaved.getTime()) - .toBeGreaterThanOrEqual(t0.getTime()); - expect(saveResult.modelArtifactsInfo.modelTopologyType) - .toEqual('JSON'); - - const modelJSONPath = path.join(dir, 'model.json'); - const weightsBinPath = path.join(dir, 'weights.bin'); - const modelJSON = JSON.parse(await readFile(modelJSONPath, 'utf8')); - expect(modelJSON.modelTopology).toEqual(modelTopology1); - expect(modelJSON.weightsManifest.length).toEqual(1); - expect(modelJSON.weightsManifest[0].paths).toEqual(['weights.bin']); - expect(modelJSON.weightsManifest[0].weights).toEqual(weightSpecs1); - - const weightData = new Uint8Array(await readFile(weightsBinPath)); - expect(weightData.length).toEqual(16); - weightData.forEach(value => expect(value).toEqual(0)); - - // Verify the content of the files. - done(); - }) - .catch(err => done.fail(err.stack)); + + const saveResult = await handler.save({ + modelTopology: modelTopology1, + weightSpecs: weightSpecs1, + weightData: weightData1, + }); + + expect(saveResult.modelArtifactsInfo.dateSaved.getTime()) + .toBeGreaterThanOrEqual(t0.getTime()); + expect(saveResult.modelArtifactsInfo.modelTopologyType) + .toEqual('JSON'); + + const modelJSONPath = path.join(dir, 'model.json'); + const weightsBinPath = path.join(dir, 'weights.bin'); + const modelJSON = JSON.parse(await readFile(modelJSONPath, 'utf8')); + expect(modelJSON.modelTopology).toEqual(modelTopology1); + expect(modelJSON.weightsManifest.length).toEqual(1); + expect(modelJSON.weightsManifest[0].paths).toEqual(['weights.bin']); + expect(modelJSON.weightsManifest[0].weights).toEqual(weightSpecs1); + + const weightData = new Uint8Array(await readFile(weightsBinPath)); + expect(weightData.length).toEqual(16); + weightData.forEach(value => expect(value).toEqual(0)); }); - it('save fails if path exists as a file', async done => { + it('save fails if path exists as a file', async () => { const dir = path.join(testDir, 'save-destination'); // Create a file at the locatin. await writeFile(dir, 'foo'); const handler = tf.io.getSaveHandlers(`file://${dir}`)[0]; - handler - .save({ - modelTopology: modelTopology1, - weightSpecs: weightSpecs1, - weightData: weightData1, - }) - .then(saveResult => { - done.fail('Saving to path of existing file succeeded unexpectedly.'); - }) - .catch(err => { - expect(err.message).toMatch(/.*exists as a file.*directory.*/); - done(); - }); + await expectAsync(handler.save({ + modelTopology: modelTopology1, + weightSpecs: weightSpecs1, + weightData: weightData1, + })).toBeRejectedWithError(/.*exists as a file.*directory.*/); }); it('save-load round trip: one weight file', done => { @@ -175,7 +160,7 @@ describe('File system IOHandler', () => { }); describe('load json model', () => { - it('load: two weight files', async done => { + it('load: two weight files', async () => { const weightsManifest: tf.io.WeightsManifestConfig = [ { paths: ['weights.1.bin'], @@ -216,27 +201,23 @@ describe('File system IOHandler', () => { // Load the artifacts consisting of a model.json and two binary weight // files. const handler = tf.io.getLoadHandlers(`file://${modelJSONPath}`)[0]; - handler.load() - .then(modelArtifacts => { - expect(modelArtifacts.modelTopology).toEqual(modelTopology1); - expect(modelArtifacts.weightSpecs).toEqual([ - { - name: 'dense/kernel', - shape: [3, 1], - dtype: 'float32', - }, - { - name: 'dense/bias', - shape: [1], - dtype: 'float32', - } - ]); - tf.test_util.expectArraysClose( - new Float32Array(modelArtifacts.weightData), - new Float32Array([-1.1, -3.3, -3.3, -7.7])); - done(); - }) - .catch(err => done.fail(err.stack)); + const modelArtifacts = await handler.load(); + expect(modelArtifacts.modelTopology).toEqual(modelTopology1); + expect(modelArtifacts.weightSpecs).toEqual([ + { + name: 'dense/kernel', + shape: [3, 1], + dtype: 'float32', + }, + { + name: 'dense/bias', + shape: [1], + dtype: 'float32', + } + ]); + tf.test_util.expectArraysClose( + new Float32Array(modelArtifacts.weightData), + new Float32Array([-1.1, -3.3, -3.3, -7.7])); }); it('loading from nonexistent model.json path fails', done => { @@ -255,7 +236,7 @@ describe('File system IOHandler', () => { }); }); - it('loading from missing weights path fails', async done => { + it('loading from missing weights path fails', async () => { const weightsManifest: tf.io.WeightsManifestConfig = [ { paths: ['weights.1.bin'], @@ -293,22 +274,13 @@ describe('File system IOHandler', () => { // Load the artifacts consisting of a model.json and two binary weight // files. const handler = tf.io.getLoadHandlers(`file://${modelJSONPath}`)[0]; - handler.load() - .then(modelArtifacts => { - done.fail( - 'Loading with missing weights file succeeded ' + - 'unexpectedly.'); - }) - .catch(err => { - expect(err.message) - .toMatch(/Weight file .*weights\.2\.bin does not exist/); - done(); - }); + await expectAsync(handler.load()).toBeRejectedWithError( + /Weight file .*weights\.2\.bin does not exist/); }); }); describe('load binary model', () => { - it('load: two weight files', async done => { + it('load: two weight files', async () => { const weightsManifest: tf.io.WeightsManifestConfig = [ { paths: ['weights.1.bin'], @@ -352,29 +324,25 @@ describe('File system IOHandler', () => { // binary weight files. const handler = new NodeFileSystem([`${modelPath}`, `${modelManifestJSONPath}`]); - handler.load() - .then(modelArtifacts => { - tf.test_util.expectArraysClose( - new Uint8Array(modelArtifacts.modelTopology as ArrayBuffer), - new Uint8Array(modelData)); - expect(modelArtifacts.weightSpecs).toEqual([ - { - name: 'dense/kernel', - shape: [3, 1], - dtype: 'float32', - }, - { - name: 'dense/bias', - shape: [1], - dtype: 'float32', - } - ]); - tf.test_util.expectArraysClose( - new Float32Array(modelArtifacts.weightData), - new Float32Array([-1.1, -3.3, -3.3, -7.7])); - done(); - }) - .catch(err => done.fail(err.stack)); + const modelArtifacts = await handler.load(); + tf.test_util.expectArraysClose( + new Uint8Array(modelArtifacts.modelTopology as ArrayBuffer), + new Uint8Array(modelData)); + expect(modelArtifacts.weightSpecs).toEqual([ + { + name: 'dense/kernel', + shape: [3, 1], + dtype: 'float32', + }, + { + name: 'dense/bias', + shape: [1], + dtype: 'float32', + } + ]); + tf.test_util.expectArraysClose( + new Float32Array(modelArtifacts.weightData), + new Float32Array([-1.1, -3.3, -3.3, -7.7])); }); it('path length does not equal 2 fails', () => { @@ -399,7 +367,7 @@ describe('File system IOHandler', () => { }); }); - it('loading from missing weights path fails', async done => { + it('loading from missing weights path fails', async () => { const weightsManifest: tf.io.WeightsManifestConfig = [ { paths: ['weights.1.bin'], @@ -439,17 +407,8 @@ describe('File system IOHandler', () => { // files. const handler = new NodeFileSystem([`${modelPath}`, `${modelManifestJSONPath}`]); - handler.load() - .then(modelArtifacts => { - done.fail( - 'Loading with missing weights file succeeded ' + - 'unexpectedly.'); - }) - .catch(err => { - expect(err.message) - .toMatch(/Weight file .*weights\.2\.bin does not exist/); - done(); - }); + await expectAsync(handler.load()).toBeRejectedWithError( + /Weight file .*weights\.2\.bin does not exist/); }); }); diff --git a/tfjs-node/src/nodejs_kernel_backend_test.ts b/tfjs-node/src/nodejs_kernel_backend_test.ts index fc2467cb80..19718cbe54 100644 --- a/tfjs-node/src/nodejs_kernel_backend_test.ts +++ b/tfjs-node/src/nodejs_kernel_backend_test.ts @@ -75,20 +75,15 @@ describe('Exposes Backend for internal Op execution.', () => { expect(nodeBackend().binding).toBeDefined(); }); - it('throw error if backend is not tensorflow', async done => { + it('throw error if backend is not tensorflow', async () => { + const testBackend = new TestKernelBackend(); + tf.registerBackend('fake', () => testBackend); + tf.setBackend('fake'); try { - const testBackend = new TestKernelBackend(); - tf.registerBackend('fake', () => testBackend); - tf.setBackend('fake'); - - ensureTensorflowBackend(); - done.fail(); - } catch (err) { - expect(err.message) - .toBe( - 'Expect the current backend to be "tensorflow", but got "fake"'); + expect(() => ensureTensorflowBackend()).toThrowError( + 'Expect the current backend to be "tensorflow", but got "fake"'); + } finally { tf.setBackend('tensorflow'); - done(); } }); }); diff --git a/tfjs-node/src/run_tests.ts b/tfjs-node/src/run_tests.ts index bddb4049b5..b75cc4059c 100644 --- a/tfjs-node/src/run_tests.ts +++ b/tfjs-node/src/run_tests.ts @@ -188,8 +188,13 @@ if (process.platform === 'win32') { 'maxPool test-tensorflow {} [x=[3,3,1] f=[2,2] s=1 ignores NaNs'); } +const grepRegex = new RegExp(argv.grep as string); const runner = new jasmineCtor(); -runner.loadConfig({spec_files: ['src/**/*_test.ts'], random: false}); +runner.loadConfig({ + spec_files: ['src/**/*_test.ts'], + random: false, + jsLoader: 'require', +}); // Also import tests from core. // tslint:disable-next-line: no-imports-from-dist import '@tensorflow/tfjs-core/dist/tests'; @@ -200,23 +205,23 @@ if (process.env.JASMINE_SEED) { const env = jasmine.getEnv(); -const grepRegex = new RegExp(argv.grep as string); - -// Filter method that returns boolean, if a given test should return. -env.specFilter = spec => { - // Filter based on the grep flag. - if (!grepRegex.test(spec.getFullName())) { - return false; - } - // Return false (skip the test) if the test is in the ignore list. - for (let i = 0; i < IGNORE_LIST.length; ++i) { - if (spec.getFullName().indexOf(IGNORE_LIST[i]) > -1) { +// // Filter method that returns boolean, if a given test should return. +env.configure({ + specFilter: (spec: jasmine.Spec) => { + // Filter based on the grep flag. + if (!grepRegex.test(spec.getFullName())) { return false; } + // Return false (skip the test) if the test is in the ignore list. + for (let i = 0; i < IGNORE_LIST.length; ++i) { + if (spec.getFullName().indexOf(IGNORE_LIST[i]) > -1) { + return false; + } + } + // Otherwise run the test. + return true; } - // Otherwise run the test. - return true; -}; +}); // TODO(kreeger): Consider moving to C-code. console.log(`Running tests against TensorFlow: ${ diff --git a/tfjs-node/src/saved_model_test.ts b/tfjs-node/src/saved_model_test.ts index c600f20a6b..e8719b9bd6 100644 --- a/tfjs-node/src/saved_model_test.ts +++ b/tfjs-node/src/saved_model_test.ts @@ -113,15 +113,10 @@ describe('SavedModel', () => { expect(enumKey2).toBe('DT_DOUBLE'); }); - it('read non-exist file', async done => { - try { - await readSavedModelProto('/not-exist'); - done.fail(); - } catch (err) { - expect(err.message) - .toBe(`There is no saved_model.pb file in the directory: /not-exist`); - done(); - } + it('read non-exist file', async () => { + await expectAsync(readSavedModelProto('/not-exist')) + .toBeRejectedWithError( + `There is no saved_model.pb file in the directory: /not-exist`); }); it('inspect SavedModel metagraphs', async () => { @@ -206,30 +201,21 @@ describe('SavedModel', () => { model.dispose(); }); - it('load TFSavedModel with wrong tags throw exception', async done => { - try { - await tf.node.loadSavedModel( - './test_objects/saved_model/times_three_float', ['serve', 'gpu'], - 'serving_default'); - done.fail(); - } catch (error) { - expect(error.message) - .toBe('The SavedModel does not have tags: serve,gpu'); - done(); - } + it('load TFSavedModel with wrong tags throw exception', async () => { + await expectAsync(tf.node.loadSavedModel( + './test_objects/saved_model/times_three_float', ['serve', 'gpu'], + 'serving_default')) + .toBeRejectedWithError('The SavedModel does not have tags: serve,gpu'); }); - it('load TFSavedModel with wrong signature throw exception', async done => { - try { - await tf.node.loadSavedModel( - './test_objects/saved_model/times_three_float', ['serve'], - 'wrong_signature'); - done.fail(); - } catch (error) { - expect(error.message) - .toBe('The SavedModel does not have signature: wrong_signature'); - done(); - } + it('load TFSavedModel with wrong signature throw exception', async () => { + await expectAsync( + tf.node.loadSavedModel( + './test_objects/saved_model/times_three_float', ['serve'], + 'wrong_signature') + ).toBeRejectedWithError( + 'The SavedModel does not have signature: wrong_signature' + ); }); it('load TFSavedModel and delete', async () => { @@ -252,18 +238,13 @@ describe('SavedModel', () => { expect(tf.node.getNumOfSavedModels()).toBe(0); }); - it('delete TFSavedModel multiple times throw exception', async done => { + it('delete TFSavedModel multiple times throw exception', async () => { const model = await tf.node.loadSavedModel( './test_objects/saved_model/times_three_float', ['serve'], 'serving_default'); model.dispose(); - try { - model.dispose(); - done.fail(); - } catch (error) { - expect(error.message).toBe('This SavedModel has already been deleted.'); - done(); - } + expect(() => model.dispose()) + .toThrowError('This SavedModel has already been deleted.'); }); it('load multiple signatures from the same metagraph only call binding once', @@ -316,23 +297,17 @@ describe('SavedModel', () => { expect(spyOnNodeBackendDelete).toHaveBeenCalledTimes(2); }); - it('throw error when input tensors do not match input ops', async done => { + it('throw error when input tensors do not match input ops', async () => { const model = await tf.node.loadSavedModel( - './test_objects/saved_model/times_three_float', ['serve'], - 'serving_default'); + './test_objects/saved_model/times_three_float', ['serve'], + 'serving_default'); const input1 = tf.tensor1d([1.0, 2, 3]); const input2 = tf.tensor1d([1.0, 2, 3]); - try { - model.predict([input1, input2]); - done.fail(); - } catch (error) { - expect(error.message) - .toBe( - 'Length of input op names (1) does not match the ' + - 'length of input tensors (2).'); - model.dispose(); - done(); - } + + expect(() => model.predict([input1, input2])).toThrowError( + 'Length of input op names (1) does not match the ' + + 'length of input tensors (2).'); + model.dispose(); }); it('execute model float times three', async () => { @@ -377,22 +352,16 @@ describe('SavedModel', () => { model.dispose(); }); - it('execute model with wrong tensor name', async done => { + it('execute model with wrong tensor name', async () => { const model = await tf.node.loadSavedModel( './test_objects/saved_model/times_three_float', ['serve'], 'serving_default'); const input = tf.tensor1d([1.0, 2, 3]); - try { - model.predict({'xyz': input}); - done.fail(); - } catch (error) { - expect(error.message) - .toBe( - 'The model signatureDef input names are x, however ' + - 'the provided input names are xyz.'); - model.dispose(); - done(); - } + expect(() => model.predict({'xyz': input})).toThrowError( + 'The model signatureDef input names are x, however ' + + 'the provided input names are xyz.'); + + model.dispose(); }); it('execute model with uint8 input', async () => { const model = await tf.node.loadSavedModel( diff --git a/tfjs-node/yarn.lock b/tfjs-node/yarn.lock index 79549431c9..a7abe614cf 100644 --- a/tfjs-node/yarn.lock +++ b/tfjs-node/yarn.lock @@ -266,10 +266,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/jasmine@~2.8.6": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.17.tgz#65fa3be377126253f6c7988b365dfc78d62d536e" - integrity sha512-lXmY2lBjE38ASvP7ah38yZwXCdc7DTCKhHqx4J3WGNiVzp134U0BD9VKdL5x9q9AAfhnpJeQr4owL6ZOXhOpfA== +"@types/jasmine@~4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-4.0.3.tgz#097ce710d70eb7f3662e96c1f75824dd22c27d5c" + integrity sha512-Opp1LvvEuZdk8fSSvchK2mZwhVrsNT0JgJE9Di6MjnaIpmEXM8TLCPPrVtNTYh8+5MPdY8j9bAHMu2SSfwpZJg== "@types/long@^4.0.1": version "4.0.2" @@ -427,6 +427,11 @@ are-we-there-yet@^2.0.0: delegates "^1.0.0" readable-stream "^3.6.0" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -434,11 +439,6 @@ argparse@^1.0.10, argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - async@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" @@ -685,11 +685,6 @@ detect-libc@^2.0.0: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" integrity "sha1-4Yl6qI+mrRl4YpN/vARB7zUu4M0= sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" -diff@^3.1.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -839,7 +834,7 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -glob@^7.0.0, glob@^7.0.6, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1050,18 +1045,18 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jasmine-core@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.1.0.tgz#a4785e135d5df65024dfc9224953df585bd2766c" - integrity sha1-pHheE11d9lAk38kiSVPfWFvSdmw= +jasmine-core@^4.2.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-4.6.0.tgz#6884fc3d5b66bf293e422751eed6d6da217c38f5" + integrity sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ== -jasmine@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.1.0.tgz#2bd59fd7ec6ec0e8acb64e09f45a68ed2ad1952a" - integrity sha1-K9Wf1+xuwOistk4J9Fpo7SrRlSo= +jasmine@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-4.2.1.tgz#55f81ab9d5d32f2645aa598d1356b6858407f4a9" + integrity sha512-LNZEKcScnjPRj5J92I1P515bxTvaHMRAERTyCoaGnWr87eOT6zv+b3M+kxKdH/06Gz4TnnXyHbXLiPtMHZ0ncw== dependencies: - glob "^7.0.6" - jasmine-core "~3.1.0" + glob "^7.1.6" + jasmine-core "^4.2.0" js-tokens@^4.0.0: version "4.0.0" @@ -1153,7 +1148,7 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.2.5, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -1188,7 +1183,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp@^0.5.1, mkdirp@^0.5.3: +mkdirp@^0.5.3: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -1516,10 +1511,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== -source-map-support@^0.5.3: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -1660,19 +1655,16 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= -ts-node@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-5.0.1.tgz#78e5d1cb3f704de1b641e43b76be2d4094f06f81" - integrity sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw== +ts-node@~8.8.2: + version "8.8.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.8.2.tgz#0b39e690bee39ea5111513a9d2bcdc0bc121755f" + integrity sha512-duVj6BpSpUpD/oM4MfhO98ozgkp3Gt9qIp3jGxwU2DFvl/3IRaEAvbLa8G60uS7C77457e/m5TMowjedeRxI1Q== dependencies: - arrify "^1.0.0" - chalk "^2.3.0" - diff "^3.1.0" + arg "^4.1.0" + diff "^4.0.1" make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - yn "^2.0.0" + source-map-support "^0.5.6" + yn "3.1.1" tslib@^1.13.0, tslib@^1.8.1: version "1.14.1" @@ -1884,7 +1876,7 @@ yargs@^16.0.3, yargs@^16.1.1, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" - integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo= +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/tfjs/yarn.lock b/tfjs/yarn.lock index e41e0948d8..4be23df951 100644 --- a/tfjs/yarn.lock +++ b/tfjs/yarn.lock @@ -1760,6 +1760,9 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== +"@tensorflow/tfjs-backend-cpu@link:../link-package/node_modules/@tensorflow/link-package/node_modules/@tensorflow/tfjs-backend-cpu": + version "0.0.0" + "@tensorflow/tfjs-backend-cpu@link:../link-package/node_modules/@tensorflow/tfjs-backend-cpu": version "0.0.0" uid "" @@ -1822,11 +1825,24 @@ resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.7.tgz#3fe583928ae0a22cdd34cedf930eeffeda2602fd" integrity sha512-RdbrPcW1aD78UmdLiDa9ZCKrbR5Go8PXh6GCpb4oIOkWVEusubSJJDrP4c5RYOu8m/CBz+ygZpicj6Pgms5a4Q== +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + "@types/minimatch@*": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== +"@types/node-fetch@^2.1.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*", "@types/node@>=10.0.0": version "18.11.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" @@ -1837,6 +1853,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.56.tgz#010c9e047c3ff09ddcd11cbb6cf5912725cdc2b3" integrity sha512-LuAa6t1t0Bfw4CuSR0UITsm1hP17YL+u82kfHGrHUWdhlBtH7sa7jGY5z7glGaIj/WDYDkRtgGd+KCjCzxBW1w== +"@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/offscreencanvas@~2019.7.0": + version "2019.7.0" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz#e4a932069db47bb3eabeb0b305502d01586fa90d" + integrity sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg== + "@types/resolve@0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" @@ -1857,6 +1883,11 @@ "@types/glob" "*" "@types/node" "*" +"@types/webgl-ext@0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d" + integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg== + "@types/yargs-parser@*": version "20.2.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" @@ -1869,6 +1900,11 @@ dependencies: "@types/yargs-parser" "*" +"@webgpu/types@0.1.21": + version "0.1.21" + resolved "https://registry.yarnpkg.com/@webgpu/types/-/types-0.1.21.tgz#b181202daec30d66ccd67264de23814cfd176d3a" + integrity sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow== + accepts@~1.3.4: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1983,6 +2019,11 @@ async@^3.0.1: resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" @@ -2395,6 +2436,13 @@ combine-source-map@^0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^2.12.1, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -2594,6 +2642,11 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -2881,6 +2934,15 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" @@ -3607,6 +3669,11 @@ log4js@^6.3.0, log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.0.2" +long@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + magic-string@^0.25.2: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -3680,6 +3747,13 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +mime-types@^2.1.12, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime-types@~2.1.24: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" @@ -3687,13 +3761,6 @@ mime-types@~2.1.24: dependencies: mime-db "1.51.0" -mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - mime@^2.5.2: version "2.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" @@ -3758,6 +3825,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-fetch@~2.6.1: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + node-releases@^1.1.71: version "1.1.72" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" @@ -4648,6 +4722,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-node@~8.8.2: version "8.8.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.8.2.tgz#0b39e690bee39ea5111513a9d2bcdc0bc121755f" @@ -4856,6 +4935,19 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"