From 0ef3b9416e4f7cad68cae6a274a90728f947f954 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 4 Sep 2024 16:27:52 -0700 Subject: [PATCH 01/21] add support for Uint8ClampedArray --- js/common/lib/tensor-impl.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 4e0ef821dde57..0728ea0d342b4 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -243,6 +243,9 @@ export class Tensor implements TensorInterface { } else { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } + } else if (arg0 instanceof Uint8ClampedArray) { + type = "uint8"; + data = Uint8Array.from(arg0); } else { // get tensor type from TypedArray const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get( From 76d9eb7e31d27b44c5d8e1d593eb89b99c9583ba Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 4 Sep 2024 16:34:19 -0700 Subject: [PATCH 02/21] add test --- js/common/test/type-tests/tensor/create-new-array.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 js/common/test/type-tests/tensor/create-new-array.ts diff --git a/js/common/test/type-tests/tensor/create-new-array.ts b/js/common/test/type-tests/tensor/create-new-array.ts new file mode 100644 index 0000000000000..a6877773868f5 --- /dev/null +++ b/js/common/test/type-tests/tensor/create-new-array.ts @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as ort from 'onnxruntime-common'; + +// construct from Uint8ClampedArray +// +// {type-tests}|pass +new ort.Tensor(new Uint8ClampedArray(1)) + + From 71796316827bcd3d7d68baec8c70870f517e10f6 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Thu, 5 Sep 2024 11:59:46 -0700 Subject: [PATCH 03/21] address comments --- js/common/lib/tensor-impl.ts | 2 ++ js/common/lib/tensor.ts | 4 ++-- .../{create-new-array.ts => create-new-uint8.ts} | 0 .../test/unit-tests/tensor/constructor-type.ts | 15 ++++++++++++--- 4 files changed, 16 insertions(+), 5 deletions(-) rename js/common/test/type-tests/tensor/{create-new-array.ts => create-new-uint8.ts} (100%) diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 0728ea0d342b4..cd54c56606017 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -216,6 +216,8 @@ export class Tensor implements TensorInterface { } } else if (arg1 instanceof typedArrayConstructor) { data = arg1; + } else if (arg1 instanceof Uint8ClampedArray) { + data = Uint8Array.from(arg1); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 70396bbe1e9a3..9ba0d32622862 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -66,7 +66,7 @@ interface TypedTensorBase { export declare namespace Tensor { interface DataTypeMap { float32: Float32Array; - uint8: Uint8Array; + uint8: Uint8Array | Uint8ClampedArray; int8: Int8Array; uint16: Uint16Array; int16: Int16Array; @@ -243,7 +243,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new (data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>; + new(data: Uint8Array | Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new uint16 tensor object from the given data and dims. diff --git a/js/common/test/type-tests/tensor/create-new-array.ts b/js/common/test/type-tests/tensor/create-new-uint8.ts similarity index 100% rename from js/common/test/type-tests/tensor/create-new-array.ts rename to js/common/test/type-tests/tensor/create-new-uint8.ts diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index def711684d7f5..9c6929a28a2d3 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -82,9 +82,18 @@ describe('Tensor Constructor Tests - check types', () => { assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); - it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { - const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); - assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); + it("[uint8] new Tensor(uint8ClampedArray, dims): uint8 tensor can be constructed from Uint8ClampedArray", () => { + const uint8ClampedArray = new Uint8ClampedArray(2); + uint8ClampedArray[0] = 0; + uint8ClampedArray[1] = 256; // clamped + assert.equal(uint8ClampedArray[1], 255, "uint8ClampedArray[1] should be clamped to 255"); + const tensor = new Tensor('uint8', uint8ClampedArray, [2]); + assert.equal(tensor.type, 'uint8', "tensor.type should be 'uint8'"); + }); + + it("[clamp] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { + const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); + assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); it('[bool] new Tensor(booleans, dims): "tensor.data" should match inferred type', () => { From ebd3347667df67226fe9e5b1332f897f501c4200 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Thu, 5 Sep 2024 12:00:44 -0700 Subject: [PATCH 04/21] formatting --- js/common/lib/tensor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 9ba0d32622862..e5f3ed3f18413 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -243,7 +243,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Uint8Array | Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; + new(data: Uint8Array | Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new uint16 tensor object from the given data and dims. From 7de7b57927209bc8a76933831d6ff2c7ba315891 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Thu, 5 Sep 2024 12:01:00 -0700 Subject: [PATCH 05/21] formatting --- js/common/lib/tensor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index e5f3ed3f18413..ac7887232bad7 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -243,7 +243,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Uint8Array | Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; + new (data: Uint8Array | Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new uint16 tensor object from the given data and dims. From 7491a9b9c5e91a764ecd88fbeb9696fe1a0fe781 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Thu, 5 Sep 2024 14:52:56 -0700 Subject: [PATCH 06/21] add/fix tests --- js/common/test/type-tests/tensor/create-new-uint8.ts | 9 +++++++++ js/common/test/unit-tests/tensor/constructor-type.ts | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/js/common/test/type-tests/tensor/create-new-uint8.ts b/js/common/test/type-tests/tensor/create-new-uint8.ts index a6877773868f5..dd4676e175847 100644 --- a/js/common/test/type-tests/tensor/create-new-uint8.ts +++ b/js/common/test/type-tests/tensor/create-new-uint8.ts @@ -3,9 +3,18 @@ import * as ort from 'onnxruntime-common'; +// construct from Uint8Array +// +// {type-tests}|pass +new ort.Tensor(new Uint8Array(1)) + // construct from Uint8ClampedArray // // {type-tests}|pass new ort.Tensor(new Uint8ClampedArray(1)) +// construct from type (bool), data (Uint8Array) and shape (number array) +// +// {type-tests}|fail +new ort.Tensor('bool', new Uint8ClampedArray([255, 256]), [2]); diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 9c6929a28a2d3..e3401772eca29 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -86,12 +86,11 @@ describe('Tensor Constructor Tests - check types', () => { const uint8ClampedArray = new Uint8ClampedArray(2); uint8ClampedArray[0] = 0; uint8ClampedArray[1] = 256; // clamped - assert.equal(uint8ClampedArray[1], 255, "uint8ClampedArray[1] should be clamped to 255"); const tensor = new Tensor('uint8', uint8ClampedArray, [2]); assert.equal(tensor.type, 'uint8', "tensor.type should be 'uint8'"); }); - it("[clamp] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { + it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); From 7caee942cd9a4912cec43fca403a93f119c21c1b Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Thu, 5 Sep 2024 14:54:32 -0700 Subject: [PATCH 07/21] formatting --- js/common/test/unit-tests/tensor/constructor-type.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index e3401772eca29..565856571fd44 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -91,8 +91,8 @@ describe('Tensor Constructor Tests - check types', () => { }); it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { - const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); - assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); + const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); + assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); it('[bool] new Tensor(booleans, dims): "tensor.data" should match inferred type', () => { From 710cf6da503979d2143268f21f77c387444b1c03 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Fri, 6 Sep 2024 11:33:19 -0700 Subject: [PATCH 08/21] npm run format --- js/common/lib/tensor-impl.ts | 2 +- js/common/test/type-tests/tensor/create-new-uint8.ts | 5 ++--- js/common/test/unit-tests/tensor/constructor-type.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index cd54c56606017..6e9570968dd72 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -246,7 +246,7 @@ export class Tensor implements TensorInterface { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } } else if (arg0 instanceof Uint8ClampedArray) { - type = "uint8"; + type = 'uint8'; data = Uint8Array.from(arg0); } else { // get tensor type from TypedArray diff --git a/js/common/test/type-tests/tensor/create-new-uint8.ts b/js/common/test/type-tests/tensor/create-new-uint8.ts index dd4676e175847..39983df847f5c 100644 --- a/js/common/test/type-tests/tensor/create-new-uint8.ts +++ b/js/common/test/type-tests/tensor/create-new-uint8.ts @@ -6,15 +6,14 @@ import * as ort from 'onnxruntime-common'; // construct from Uint8Array // // {type-tests}|pass -new ort.Tensor(new Uint8Array(1)) +new ort.Tensor(new Uint8Array(1)); // construct from Uint8ClampedArray // // {type-tests}|pass -new ort.Tensor(new Uint8ClampedArray(1)) +new ort.Tensor(new Uint8ClampedArray(1)); // construct from type (bool), data (Uint8Array) and shape (number array) // // {type-tests}|fail new ort.Tensor('bool', new Uint8ClampedArray([255, 256]), [2]); - diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 565856571fd44..02390800e8611 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -82,7 +82,7 @@ describe('Tensor Constructor Tests - check types', () => { assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); - it("[uint8] new Tensor(uint8ClampedArray, dims): uint8 tensor can be constructed from Uint8ClampedArray", () => { + it('[uint8] new Tensor(uint8ClampedArray, dims): uint8 tensor can be constructed from Uint8ClampedArray', () => { const uint8ClampedArray = new Uint8ClampedArray(2); uint8ClampedArray[0] = 0; uint8ClampedArray[1] = 256; // clamped From 22df6067a7cdd6de0496ab772217f26e28b528f8 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Mon, 9 Sep 2024 11:45:48 -0700 Subject: [PATCH 09/21] introduce standalone Uint8ClampedArray implementation --- js/common/lib/tensor-impl-type-mapping.ts | 3 +++ js/common/lib/tensor-impl.ts | 5 ----- js/common/lib/tensor.ts | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index 14dbdca707220..ff96c021c3cc9 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -6,6 +6,7 @@ import { Tensor } from './tensor.js'; export type SupportedTypedArrayConstructors = | Float32ArrayConstructor | Uint8ArrayConstructor + | Uint8ClampedArrayConstructor | Int8ArrayConstructor | Uint16ArrayConstructor | Int16ArrayConstructor @@ -21,6 +22,7 @@ export type SupportedTypedArray = InstanceType; export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([ ['float32', Float32Array], ['uint8', Uint8Array], + ['uint8c', Uint8ClampedArray], ['int8', Int8Array], ['uint16', Uint16Array], ['int16', Int16Array], @@ -36,6 +38,7 @@ export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([ [Float32Array, 'float32'], [Uint8Array, 'uint8'], + [Uint8ClampedArray, 'uint8c'], [Int8Array, 'int8'], [Uint16Array, 'uint16'], [Int16Array, 'int16'], diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 6e9570968dd72..4e0ef821dde57 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -216,8 +216,6 @@ export class Tensor implements TensorInterface { } } else if (arg1 instanceof typedArrayConstructor) { data = arg1; - } else if (arg1 instanceof Uint8ClampedArray) { - data = Uint8Array.from(arg1); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } @@ -245,9 +243,6 @@ export class Tensor implements TensorInterface { } else { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } - } else if (arg0 instanceof Uint8ClampedArray) { - type = 'uint8'; - data = Uint8Array.from(arg0); } else { // get tensor type from TypedArray const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get( diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index ac7887232bad7..de8d20bd79ec2 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -66,7 +66,8 @@ interface TypedTensorBase { export declare namespace Tensor { interface DataTypeMap { float32: Float32Array; - uint8: Uint8Array | Uint8ClampedArray; + uint8: Uint8Array; + uint8c: Uint8ClampedArray; int8: Int8Array; uint16: Uint16Array; int16: Int16Array; @@ -88,6 +89,7 @@ export declare namespace Tensor { interface ElementTypeMap { float32: number; uint8: number; + uint8c: number; int8: number; uint16: number; int16: number; @@ -139,7 +141,7 @@ export declare namespace Tensor { /** * supported data types for constructing a tensor from a WebGPU buffer */ - export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'bool'; + export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'uint8c' | 'bool'; /** * represent where the tensor data is stored @@ -243,7 +245,15 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new (data: Uint8Array | Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; + new (data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>; + + /** + * Construct a new uint8 tensor object from the given data and dims. + * + * @param data - Specify the CPU tensor data. + * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. + */ + new (data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8c'>; /** * Construct a new uint16 tensor object from the given data and dims. From 50e4dee1833dd9c4d46bb319fbb8820121e2c614 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Mon, 9 Sep 2024 11:47:00 -0700 Subject: [PATCH 10/21] adjust test --- js/common/test/unit-tests/tensor/constructor-type.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 02390800e8611..50d640b40dde4 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -86,8 +86,8 @@ describe('Tensor Constructor Tests - check types', () => { const uint8ClampedArray = new Uint8ClampedArray(2); uint8ClampedArray[0] = 0; uint8ClampedArray[1] = 256; // clamped - const tensor = new Tensor('uint8', uint8ClampedArray, [2]); - assert.equal(tensor.type, 'uint8', "tensor.type should be 'uint8'"); + const tensor = new Tensor('uint8c', uint8ClampedArray, [2]); + assert.equal(tensor.type, 'uint8c', "tensor.type should be 'uint8c'"); }); it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { From 5067c40a12dd091e80585a3772a307d5b69508d7 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Mon, 9 Sep 2024 11:49:35 -0700 Subject: [PATCH 11/21] adjust test again --- js/common/test/type-tests/tensor/create-new-uint8.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/test/type-tests/tensor/create-new-uint8.ts b/js/common/test/type-tests/tensor/create-new-uint8.ts index 39983df847f5c..0386f8aa1e5d5 100644 --- a/js/common/test/type-tests/tensor/create-new-uint8.ts +++ b/js/common/test/type-tests/tensor/create-new-uint8.ts @@ -13,7 +13,7 @@ new ort.Tensor(new Uint8Array(1)); // {type-tests}|pass new ort.Tensor(new Uint8ClampedArray(1)); -// construct from type (bool), data (Uint8Array) and shape (number array) +// construct from type (bool), data (Uint8ClampedArray) and shape (number array) // // {type-tests}|fail new ort.Tensor('bool', new Uint8ClampedArray([255, 256]), [2]); From 2ef91e04850efb84d3ebbb5d6796923248e1b7d9 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 10 Sep 2024 10:10:28 -0700 Subject: [PATCH 12/21] adjust impl --- js/common/lib/tensor-impl-type-mapping.ts | 4 ++-- js/common/lib/tensor.ts | 8 +++----- js/common/test/unit-tests/tensor/constructor-type.ts | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index ff96c021c3cc9..ec171c805aa80 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -22,7 +22,7 @@ export type SupportedTypedArray = InstanceType; export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([ ['float32', Float32Array], ['uint8', Uint8Array], - ['uint8c', Uint8ClampedArray], + ['uint8', Uint8ClampedArray], ['int8', Int8Array], ['uint16', Uint16Array], ['int16', Int16Array], @@ -38,7 +38,7 @@ export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([ [Float32Array, 'float32'], [Uint8Array, 'uint8'], - [Uint8ClampedArray, 'uint8c'], + [Uint8ClampedArray, 'uint8'], [Int8Array, 'int8'], [Uint16Array, 'uint16'], [Int16Array, 'int16'], diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index de8d20bd79ec2..906000fbcc38d 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -66,8 +66,7 @@ interface TypedTensorBase { export declare namespace Tensor { interface DataTypeMap { float32: Float32Array; - uint8: Uint8Array; - uint8c: Uint8ClampedArray; + uint8: Uint8Array | Uint8ClampedArray; int8: Int8Array; uint16: Uint16Array; int16: Int16Array; @@ -89,7 +88,6 @@ export declare namespace Tensor { interface ElementTypeMap { float32: number; uint8: number; - uint8c: number; int8: number; uint16: number; int16: number; @@ -141,7 +139,7 @@ export declare namespace Tensor { /** * supported data types for constructing a tensor from a WebGPU buffer */ - export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'uint8c' | 'bool'; + export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'bool'; /** * represent where the tensor data is stored @@ -253,7 +251,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new (data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8c'>; + new (data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new uint16 tensor object from the given data and dims. diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 50d640b40dde4..02390800e8611 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -86,8 +86,8 @@ describe('Tensor Constructor Tests - check types', () => { const uint8ClampedArray = new Uint8ClampedArray(2); uint8ClampedArray[0] = 0; uint8ClampedArray[1] = 256; // clamped - const tensor = new Tensor('uint8c', uint8ClampedArray, [2]); - assert.equal(tensor.type, 'uint8c', "tensor.type should be 'uint8c'"); + const tensor = new Tensor('uint8', uint8ClampedArray, [2]); + assert.equal(tensor.type, 'uint8', "tensor.type should be 'uint8'"); }); it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { From 23bf057dda4ee4c1f247cde5cbe2c91888c73dee Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 10 Sep 2024 11:30:17 -0700 Subject: [PATCH 13/21] add back orig impl --- js/common/lib/tensor-impl.ts | 8 +++++++- js/common/lib/tensor.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 4e0ef821dde57..f9a1d92d92a09 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -216,6 +216,8 @@ export class Tensor implements TensorInterface { } } else if (arg1 instanceof typedArrayConstructor) { data = arg1; + } else if (arg1 instanceof Uint8ClampedArray) { + data = Uint8Array.from(arg1); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } @@ -252,7 +254,11 @@ export class Tensor implements TensorInterface { throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`); } type = mappedType; - data = arg0 as SupportedTypedArray; + if (arg0 instanceof Uint8ClampedArray) { + data = Uint8Array.from(arg0); + } else { + data = arg0 as SupportedTypedArray; + } } } diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 906000fbcc38d..8e4878245acff 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -66,7 +66,7 @@ interface TypedTensorBase { export declare namespace Tensor { interface DataTypeMap { float32: Float32Array; - uint8: Uint8Array | Uint8ClampedArray; + uint8: Uint8Array; int8: Int8Array; uint16: Uint16Array; int16: Int16Array; From de002f00d73066773596ebd64e8b5e17949cd25e Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 10 Sep 2024 15:28:22 -0700 Subject: [PATCH 14/21] yulong's edits --- js/common/lib/tensor-impl-type-mapping.ts | 3 --- js/common/lib/tensor-impl.ts | 16 ++++++++-------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index ec171c805aa80..14dbdca707220 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -6,7 +6,6 @@ import { Tensor } from './tensor.js'; export type SupportedTypedArrayConstructors = | Float32ArrayConstructor | Uint8ArrayConstructor - | Uint8ClampedArrayConstructor | Int8ArrayConstructor | Uint16ArrayConstructor | Int16ArrayConstructor @@ -22,7 +21,6 @@ export type SupportedTypedArray = InstanceType; export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([ ['float32', Float32Array], ['uint8', Uint8Array], - ['uint8', Uint8ClampedArray], ['int8', Int8Array], ['uint16', Uint16Array], ['int16', Int16Array], @@ -38,7 +36,6 @@ export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([ [Float32Array, 'float32'], [Uint8Array, 'uint8'], - [Uint8ClampedArray, 'uint8'], [Int8Array, 'int8'], [Uint16Array, 'uint16'], [Int16Array, 'int16'], diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index f9a1d92d92a09..ee1aa08446185 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -51,13 +51,13 @@ export class Tensor implements TensorInterface { */ constructor( type: TensorType, - data: TensorDataType | readonly string[] | readonly number[] | readonly boolean[], + data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly number[] | readonly boolean[], dims?: readonly number[], ); /** * Construct a new CPU tensor object from the given data and dims. Type is inferred from data. */ - constructor(data: TensorDataType | readonly string[] | readonly boolean[], dims?: readonly number[]); + constructor(data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly boolean[], dims?: readonly number[]); /** * Construct a new tensor object from the pinned CPU data with the given type and dims. * @@ -90,12 +90,13 @@ export class Tensor implements TensorInterface { arg0: | TensorType | TensorDataType + | Uint8ClampedArray | readonly string[] | readonly boolean[] | CpuPinnedConstructorParameters | TextureConstructorParameters | GpuBufferConstructorParameters, - arg1?: TensorDataType | readonly number[] | readonly string[] | readonly boolean[], + arg1?: TensorDataType | Uint8ClampedArray | readonly number[] | readonly string[] | readonly boolean[], arg2?: readonly number[], ) { // perform one-time check for BigInt/Float16Array support @@ -245,6 +246,9 @@ export class Tensor implements TensorInterface { } else { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } + } else if (arg0 instanceof Uint8ClampedArray) { + type = 'uint8' + data = Uint8Array.from(arg0); } else { // get tensor type from TypedArray const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get( @@ -254,11 +258,7 @@ export class Tensor implements TensorInterface { throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`); } type = mappedType; - if (arg0 instanceof Uint8ClampedArray) { - data = Uint8Array.from(arg0); - } else { - data = arg0 as SupportedTypedArray; - } + data = arg0 as SupportedTypedArray; } } From c6727910491d1b23b3b1fe72b641ec5b05a08420 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 10 Sep 2024 15:31:37 -0700 Subject: [PATCH 15/21] npm run format --- js/common/lib/tensor-impl.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index ee1aa08446185..0d4d3f084cc76 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -57,7 +57,10 @@ export class Tensor implements TensorInterface { /** * Construct a new CPU tensor object from the given data and dims. Type is inferred from data. */ - constructor(data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly boolean[], dims?: readonly number[]); + constructor( + data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly boolean[], + dims?: readonly number[], + ); /** * Construct a new tensor object from the pinned CPU data with the given type and dims. * @@ -247,8 +250,8 @@ export class Tensor implements TensorInterface { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } } else if (arg0 instanceof Uint8ClampedArray) { - type = 'uint8' - data = Uint8Array.from(arg0); + type = 'uint8'; + data = Uint8Array.from(arg0); } else { // get tensor type from TypedArray const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get( From ccb0151dafed38e427417d1e0d9cb8ea259ba6d5 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 10 Sep 2024 23:37:06 -0700 Subject: [PATCH 16/21] add another constructor def --- js/common/lib/tensor.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 8e4878245acff..8a1197994393b 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -192,6 +192,15 @@ export interface TensorConstructor extends TensorFactory { dims?: readonly number[], ): TypedTensor<'bool'>; + /** + * Construct a new uint8 tensor object from a Uint8ClampedArray, data and dims. + * + * @param type - Specify the element type. + * @param data - Specify the CPU tensor data. + * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. + */ + new (type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; + /** * Construct a new 64-bit integer typed tensor object from the given type, data and dims. * From bfb939a42369c228326fc5c35709e01455f99e24 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 11 Sep 2024 12:10:39 -0700 Subject: [PATCH 17/21] move constructor test --- js/common/test/type-tests/tensor/create-new-uint8.ts | 5 ----- js/common/test/unit-tests/tensor/constructor-type.ts | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/js/common/test/type-tests/tensor/create-new-uint8.ts b/js/common/test/type-tests/tensor/create-new-uint8.ts index 0386f8aa1e5d5..98d8ac092e92d 100644 --- a/js/common/test/type-tests/tensor/create-new-uint8.ts +++ b/js/common/test/type-tests/tensor/create-new-uint8.ts @@ -12,8 +12,3 @@ new ort.Tensor(new Uint8Array(1)); // // {type-tests}|pass new ort.Tensor(new Uint8ClampedArray(1)); - -// construct from type (bool), data (Uint8ClampedArray) and shape (number array) -// -// {type-tests}|fail -new ort.Tensor('bool', new Uint8ClampedArray([255, 256]), [2]); diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 02390800e8611..d1e8e5edab22c 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -90,6 +90,10 @@ describe('Tensor Constructor Tests - check types', () => { assert.equal(tensor.type, 'uint8', "tensor.type should be 'uint8'"); }); + it("[badtype] new Tensor('bool', Uint8ClampedArray, dims): expect to throw because 'bool' is incorrect type", () => { + assert.throws(() => new Tensor('bool', new Uint8ClampedArray([255, 256]), [2])); + }); + it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); From c6e4cc21f136722f6bf2fa61258d069a3aebbd27 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 11 Sep 2024 12:12:41 -0700 Subject: [PATCH 18/21] npm run format --- js/common/test/unit-tests/tensor/constructor-type.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index d1e8e5edab22c..a395846da78b1 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -91,7 +91,7 @@ describe('Tensor Constructor Tests - check types', () => { }); it("[badtype] new Tensor('bool', Uint8ClampedArray, dims): expect to throw because 'bool' is incorrect type", () => { - assert.throws(() => new Tensor('bool', new Uint8ClampedArray([255, 256]), [2])); + assert.throws(() => new Tensor('bool', new Uint8ClampedArray([255, 256]), [2]), TypeError); }); it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { From 3a986d1feded6217914dc32c560fc16aeea03d68 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 11 Sep 2024 15:14:42 -0700 Subject: [PATCH 19/21] adjust fail line --- js/common/lib/tensor.ts | 2 +- js/common/test/type-tests/tensor/create-new-uint8.ts | 5 +++++ js/common/test/unit-tests/tensor/constructor-type.ts | 4 ---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 8a1197994393b..12e9d03c955da 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -199,7 +199,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new (type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; + new(type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new 64-bit integer typed tensor object from the given type, data and dims. diff --git a/js/common/test/type-tests/tensor/create-new-uint8.ts b/js/common/test/type-tests/tensor/create-new-uint8.ts index 98d8ac092e92d..46438f97ca2e7 100644 --- a/js/common/test/type-tests/tensor/create-new-uint8.ts +++ b/js/common/test/type-tests/tensor/create-new-uint8.ts @@ -12,3 +12,8 @@ new ort.Tensor(new Uint8Array(1)); // // {type-tests}|pass new ort.Tensor(new Uint8ClampedArray(1)); + +// construct from type (bool), data (Uint8ClampedArray) and shape (number array) +// +// {type-tests}|fail|1|2769 +new ort.Tensor('bool', new Uint8ClampedArray([255, 256]), [2]); diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index a395846da78b1..02390800e8611 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -90,10 +90,6 @@ describe('Tensor Constructor Tests - check types', () => { assert.equal(tensor.type, 'uint8', "tensor.type should be 'uint8'"); }); - it("[badtype] new Tensor('bool', Uint8ClampedArray, dims): expect to throw because 'bool' is incorrect type", () => { - assert.throws(() => new Tensor('bool', new Uint8ClampedArray([255, 256]), [2]), TypeError); - }); - it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); From 4b764777ab8164ebb46fca3feea5391f717d6ed1 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 11 Sep 2024 15:30:11 -0700 Subject: [PATCH 20/21] npm run format --- js/common/lib/tensor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 12e9d03c955da..8a1197994393b 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -199,7 +199,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; + new (type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new 64-bit integer typed tensor object from the given type, data and dims. From 1f6dd045665b64ef05db799350b6a8a5c6401fd3 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Wed, 11 Sep 2024 17:04:15 -0700 Subject: [PATCH 21/21] add more type checks --- js/common/lib/tensor-impl.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 0d4d3f084cc76..342f5e3a467eb 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -221,7 +221,11 @@ export class Tensor implements TensorInterface { } else if (arg1 instanceof typedArrayConstructor) { data = arg1; } else if (arg1 instanceof Uint8ClampedArray) { - data = Uint8Array.from(arg1); + if (arg0 === 'uint8') { + data = Uint8Array.from(arg1); + } else { + throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`); + } } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); }