tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit b8ab0b6ce9c9d312b57414c281df16cd57d9af99
parent cf36a61d3e94ed60b29356da045a71da000ecd42
Author: Ningxin Hu <ningxin.hu@intel.com>
Date:   Wed, 15 Oct 2025 08:22:06 +0000

Bug 1993493 [wpt PR 55147] - WebNN: Align tensor limits implementation with spec, a=testonly

Automatic update from web-platform-tests
WebNN: Align tensor limits implementation with spec

This CL aligns the tensor limits setting in
`WebNNContextImpl::IntersectWithBaseProperties` with spec, especially
for scalar operand limits that was fixed by spec PR [1].

The change includes:
1. argMin/Max doesn't accept scalar input and output data types except
   int32 and int64 [2]
2. batchNormalization doesn't accept scalar input [3]
3. concat doesn't accept scalar input [4]
4. conv2d/convTranspose2d only accept floating-point input data types
   [5]
5. softmax doesn't accept scalar input [6]
6. split doesn't accept scalar input [7]

Pad [8] and slice [9] support scalar input as a no-op. This CL
replaces pad or slice having scalar input with an identity operator at
MLGraphBuilder to unify the behaviors across backends.

[1]: https://github.com/webmachinelearning/webnn/pull/882
[2]: https://www.w3.org/TR/webnn/#tensor-limits-argMin-argMax
[3]: https://www.w3.org/TR/webnn/#tensor-limits-batchNormalization
[4]: https://www.w3.org/TR/webnn/#tensor-limits-concat
[5]: https://www.w3.org/TR/webnn/#tensor-limits-conv2d
[6]: https://www.w3.org/TR/webnn/#tensor-limits-softmax
[7]: https://www.w3.org/TR/webnn/#tensor-limits-split
[8]: https://www.w3.org/TR/webnn/#tensor-limits-pad
[9]: https://www.w3.org/TR/webnn/#tensor-limits-slice

Change-Id: I8480cf9ef1e9e18a175677a16a553c1562a747c5
Bug: 446481989
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6972256
Commit-Queue: ningxin hu <ningxin.hu@intel.com>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1527306}

--

wpt-commits: a460ea73b9d67a705401622c6a7f8c0088b6a036
wpt-pr: 55147

Diffstat:
Mtesting/web-platform/tests/webnn/conformance_tests/pad.https.any.js | 64+++++++++++++++++++++++++++++++++++-----------------------------
Mtesting/web-platform/tests/webnn/conformance_tests/slice.https.any.js | 24++++++++++++++++++++++++
Mtesting/web-platform/tests/webnn/validation_tests/argMinMax.https.any.js | 6++++++
Mtesting/web-platform/tests/webnn/validation_tests/batchNormalization.https.any.js | 10++++++++++
Mtesting/web-platform/tests/webnn/validation_tests/cumulativeSum.https.any.js | 6++++++
Mtesting/web-platform/tests/webnn/validation_tests/pad.https.any.js | 5+++--
Mtesting/web-platform/tests/webnn/validation_tests/slice.https.any.js | 9++++++++-
Mtesting/web-platform/tests/webnn/validation_tests/softmax.https.any.js | 5+++++
Mtesting/web-platform/tests/webnn/validation_tests/split.https.any.js | 2+-
9 files changed, 98 insertions(+), 33 deletions(-)

diff --git a/testing/web-platform/tests/webnn/conformance_tests/pad.https.any.js b/testing/web-platform/tests/webnn/conformance_tests/pad.https.any.js @@ -29,6 +29,32 @@ const padTests = [ { + 'name': + 'padding float32 0D constant tensor with empty paddings should be no-op', + 'graph': { + 'inputs': { + 'padInput': { + 'data': [22.76361846923828], + 'descriptor': {shape: [], dataType: 'float32'}, + 'constant': true + } + }, + 'operators': [{ + 'name': 'pad', + 'arguments': [ + {'input': 'padInput'}, {'beginningPadding': []}, {'endingPadding': []} + ], + 'outputs': 'padOutput' + }], + 'expectedOutputs': { + 'padOutput': { + 'data': [22.76361846923828], + 'descriptor': {shape: [], dataType: 'float32'} + } + } + } + }, + { 'name': 'pad float32 1D constant tensor default options', 'graph': { 'inputs': { @@ -690,11 +716,7 @@ const padTests = [ 'graph': { 'inputs': { 'padInput': { - 'data': [ - 22, -21, -91, - 16, 60, -70, - -60, -47, 68 - ], + 'data': [22, -21, -91, 16, 60, -70, -60, -47, 68], 'descriptor': {shape: [3, 3], dataType: 'int64'} } }, @@ -764,30 +786,14 @@ const padTests = [ 'expectedOutputs': { 'padOutput': { 'data': [ - -Infinity, - -Infinity, - -Infinity, - -Infinity, - -Infinity, - -Infinity, - 22.76361846923828, - -21.168529510498047, - -91.66168975830078, - -Infinity, - -Infinity, - 16.863798141479492, - 60.51472091674805, - -70.56755065917969, - -Infinity, - -Infinity, - -60.643272399902344, - -47.8821907043457, - 68.72557830810547, - -Infinity, - -Infinity, - -Infinity, - -Infinity, - -Infinity, + -Infinity, -Infinity, -Infinity, + -Infinity, -Infinity, -Infinity, + 22.76361846923828, -21.168529510498047, -91.66168975830078, + -Infinity, -Infinity, 16.863798141479492, + 60.51472091674805, -70.56755065917969, -Infinity, + -Infinity, -60.643272399902344, -47.8821907043457, + 68.72557830810547, -Infinity, -Infinity, + -Infinity, -Infinity, -Infinity, -Infinity ], 'descriptor': {shape: [5, 5], dataType: 'float32'} diff --git a/testing/web-platform/tests/webnn/conformance_tests/slice.https.any.js b/testing/web-platform/tests/webnn/conformance_tests/slice.https.any.js @@ -17,6 +17,30 @@ const sliceTests = [ { + 'name': + 'slicing float32 0D constant tensor with empty starts and sizes should be a no-op', + 'graph': { + 'inputs': { + 'sliceInput': { + 'data': [28.846250534057617], + 'descriptor': {shape: [], dataType: 'float32'}, + 'constant': true + } + }, + 'operators': [{ + 'name': 'slice', + 'arguments': [{'input': 'sliceInput'}, {'starts': []}, {'sizes': []}], + 'outputs': 'sliceOutput' + }], + 'expectedOutputs': { + 'sliceOutput': { + 'data': [28.846250534057617], + 'descriptor': {shape: [], dataType: 'float32'} + } + } + } + }, + { 'name': 'slice float32 1D constant tensor', 'graph': { 'inputs': { diff --git a/testing/web-platform/tests/webnn/validation_tests/argMinMax.https.any.js b/testing/web-platform/tests/webnn/validation_tests/argMinMax.https.any.js @@ -62,6 +62,12 @@ const tests = [ label: label, }, }, + { + name: '[argMin/Max] Throw if outputDataType=float32', + input: {dataType: 'float32', shape: [1, 2, 3, 4]}, + axis: 1, + options: {outputDataType: 'float32', label: label} + } ]; function runTests(operatorName, tests) { diff --git a/testing/web-platform/tests/webnn/validation_tests/batchNormalization.https.any.js b/testing/web-platform/tests/webnn/validation_tests/batchNormalization.https.any.js @@ -248,6 +248,16 @@ const tests = [ label: label, }, }, + { + name: '[batchNormalization] Throw if the input is a scalar.', + input: {dataType: 'float32', shape: []}, + mean: {dataType: 'float32', shape: [1]}, + variance: {dataType: 'float32', shape: [1]}, + options: { + axis: 0, + label: label, + } + } ]; tests.forEach( diff --git a/testing/web-platform/tests/webnn/validation_tests/cumulativeSum.https.any.js b/testing/web-platform/tests/webnn/validation_tests/cumulativeSum.https.any.js @@ -15,6 +15,12 @@ const tests = [ output: {dataType: 'float32', shape: [3, 2, 5]} }, { + name: '[cumulativeSum] Test with integer input', + input: {dataType: 'int32', shape: [3, 2, 5]}, + axis: 0, + output: {dataType: 'int32', shape: [3, 2, 5]} + }, + { name: '[cumulativeSum] Test with axis=1', input: {dataType: 'float32', shape: [3, 2, 5]}, axis: 1, diff --git a/testing/web-platform/tests/webnn/validation_tests/pad.https.any.js b/testing/web-platform/tests/webnn/validation_tests/pad.https.any.js @@ -53,11 +53,12 @@ const tests = [ output: {dataType: 'float32', shape: [4, 7]} }, { - name: '[pad] Throw if building pad for scalar input.', + name: + '[pad] Test pad for scalar input with empty beginningPadding and endingPadding.', input: {dataType: 'float32', shape: []}, beginningPadding: [], endingPadding: [], - options: {label} + output: {dataType: 'float32', shape: []} }, { name: diff --git a/testing/web-platform/tests/webnn/validation_tests/slice.https.any.js b/testing/web-platform/tests/webnn/validation_tests/slice.https.any.js @@ -26,7 +26,14 @@ const tests = [ output: {dataType: 'float32', shape: [1, 2, 3]} }, { - name: '[slice] Throw if input is a scalar.', + name: '[slice] Test slicing a scalar with empty starts and sizes.', + input: {dataType: 'float32', shape: []}, + starts: [], + sizes: [], + output: {dataType: 'float32', shape: []} + }, + { + name: '[slice] Throw if input is a scalar and starts/sizes are not empty.', input: {dataType: 'float32', shape: []}, starts: [0], sizes: [1] diff --git a/testing/web-platform/tests/webnn/validation_tests/softmax.https.any.js b/testing/web-platform/tests/webnn/validation_tests/softmax.https.any.js @@ -80,6 +80,11 @@ const tests = [ name: '[softmax] Throw if the axis is greater than input rank - 1.', input: {dataType: 'float16', shape: [3, 1, 5, 2]}, axis: 4 + }, + { + name: '[softmax] Throw if the input is a scalar.', + input: {dataType: 'float32', shape: []}, + axis: 0 } ]; diff --git a/testing/web-platform/tests/webnn/validation_tests/split.https.any.js b/testing/web-platform/tests/webnn/validation_tests/split.https.any.js @@ -41,7 +41,7 @@ const tests = [ { name: '[split] Throw if splitting a scalar.', input: {dataType: 'float32', shape: []}, - splits: [2], + splits: [1], options: {label} }, {