WebNN: Respect ArrayBufferView's byte offset and length for MLGraphMojo

An `ArrayBufferView` can be created from an `ArrayBuffer` with bigger
size and with a proper byte offset, i.e. `new Float32Array(arrayBuffer,
byteOffset, length)`. `MLGraphMojo::ComputeImpl()` should use
`ArrayBufferView`'s byte offset and length when copying the input or
output data into or from the mojo `BigBuffer`.

Bug: 332151809
Change-Id: Ib8873a100de0e5565ae39b483f6fa06b024cb6f6
Cq-Include-Trybots: luci.chromium.try:win11-blink-rel
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5409911
Reviewed-by: Austin Sullivan <asully@chromium.org>
Commit-Queue: ningxin hu <ningxin.hu@intel.com>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1284226}
diff --git a/webnn/conformance_tests/gpu/compute-arraybufferview-with-bigger-arraybuffer.https.any.js b/webnn/conformance_tests/gpu/compute-arraybufferview-with-bigger-arraybuffer.https.any.js
new file mode 100644
index 0000000..ddc3901
--- /dev/null
+++ b/webnn/conformance_tests/gpu/compute-arraybufferview-with-bigger-arraybuffer.https.any.js
@@ -0,0 +1,37 @@
+// META: title=test WebNN MLContext.compute() for ArrayBufferView created from bigger ArrayBuffer
+// META: global=window,dedicatedworker
+// META: script=../../resources/utils.js
+
+'use strict';
+
+// These tests are used to reproduce the Chromium issue:
+// https://issues.chromium.org/issues/332151809
+promise_test(async t => {
+  const context = await navigator.ml.createContext({deviceType: 'gpu'});
+  const builder = new MLGraphBuilder(context);
+  const a = builder.input('a', {dataType: 'float32', dimensions: [2]});
+  const b = builder.relu(a);
+  const graph = await builder.build({b});
+  const arraybuffer = new ArrayBuffer(100);
+  const aBuffer = new Float32Array(arraybuffer, /*byteOffset*/ 4, /*length*/ 2)
+  aBuffer.set([1, -1]);
+  const bBuffer = new Float32Array(2);
+  const results = await context.compute(graph, {'a': aBuffer}, {'b': bBuffer});
+  assert_array_approx_equals_ulp(
+      results.outputs.b, [1, 0], /*nulp*/ 0, 'float32');
+}, 'Test compute() working for input ArrayBufferView created from bigger ArrayBuffer');
+
+promise_test(async t => {
+  const context = await navigator.ml.createContext({deviceType: 'gpu'});
+  const builder = new MLGraphBuilder(context);
+  const a = builder.input('a', {dataType: 'float32', dimensions: [2]});
+  const b = builder.relu(a);
+  const graph = await builder.build({b});
+  const aBuffer = new Float32Array(2);
+  aBuffer.set([1, -1]);
+  const arraybuffer = new ArrayBuffer(100);
+  const bBuffer = new Float32Array(arraybuffer, /*byteOffset*/ 8, /*length*/ 2);
+  const results = await context.compute(graph, {'a': aBuffer}, {'b': bBuffer});
+  assert_array_approx_equals_ulp(
+      results.outputs.b, [1, 0], /*nulp*/ 0, 'float32');
+}, 'Test compute() working for output ArrayBufferView created from bigger ArrayBuffer');