Skip to content

Commit

Permalink
Bug 1926581 [wpt PR 48773] - bluetooth: Use [PassAsSpan] to handle Bu…
Browse files Browse the repository at this point in the history
…fferSource arguments, a=testonly

Automatic update from web-platform-tests
bluetooth: Use [PassAsSpan] to handle BufferSource arguments

This change simplifies the implementation of Web Bluetooth methods which
accept a BufferSource argument by using the [PassAsSpan] WebIDL
attribute.

Using this requires a behavior change: Passing a detached buffer is now
no longer fatal (except when it causes other argument validation errors)
because a detached buffer turns into an empty span. I think this is a
safe change to make because it matches the WebIDL rules for handling
detached buffers (throwing a specific error was unspecified behavior)
and this case is developer error, so sites shouldn't be depending on it.

Change-Id: I1e47d8e3a219f65bd69f78018a434ab6f8a3cd62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5952456
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Reviewed-by: Matt Reynolds <mattreynolds@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1372813}

--

wpt-commits: 94d12028e9fa7cf3edd63fe1d7921c23baa5a047
wpt-pr: 48773
  • Loading branch information
reillyeon authored and moz-wptsync-bot committed Oct 25, 2024
1 parent 0093d1d commit 960250d
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,39 @@
// META: script=/bluetooth/resources/bluetooth-test.js
// META: script=/bluetooth/resources/bluetooth-fake-devices.js
'use strict';
const test_desc = 'writeValue() fails when passed a detached buffer';
const test_desc = 'Detached buffers are safe to pass to writeValue()';

function detachBuffer(buffer) {
window.postMessage('', '*', [buffer]);
}

bluetooth_test(async (t) => {
const {characteristic} = await getMeasurementIntervalCharacteristic();
const {characteristic, fake_characteristic} =
await getMeasurementIntervalCharacteristic();

let lastValue, lastWriteType;
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_equals(lastValue, null);
assert_equals(lastWriteType, 'none');

await fake_characteristic.setNextWriteResponse(GATT_SUCCESS);

const typed_array = Uint8Array.of(1, 2);
detachBuffer(typed_array.buffer);
await promise_rejects_dom(
t, 'InvalidStateError', characteristic.writeValue(typed_array));
await characteristic.writeValue(typed_array);
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_array_equals(lastValue, []);
assert_equals(lastWriteType, 'default-deprecated');

await fake_characteristic.setNextWriteResponse(GATT_SUCCESS);

const array_buffer = Uint8Array.of(3, 4).buffer;
detachBuffer(array_buffer);
await promise_rejects_dom(
t, 'InvalidStateError', characteristic.writeValue(array_buffer));
await characteristic.writeValue(array_buffer);
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_array_equals(lastValue, []);
assert_equals(lastWriteType, 'default-deprecated');
}, test_desc);
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,40 @@
// META: script=/bluetooth/resources/bluetooth-fake-devices.js
'use strict';
const test_desc =
'writeValueWithResponse() fails when passed a detached buffer';
'Detached buffers are safe to pass to writeValueWithResponse()';


function detachBuffer(buffer) {
window.postMessage('', '*', [buffer]);
}

bluetooth_test(async (t) => {
const {characteristic} = await getMeasurementIntervalCharacteristic();
const {characteristic, fake_characteristic} =
await getMeasurementIntervalCharacteristic();

let lastValue, lastWriteType;
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_equals(lastValue, null);
assert_equals(lastWriteType, 'none');

await fake_characteristic.setNextWriteResponse(GATT_SUCCESS);

const typed_array = Uint8Array.of(1, 2);
detachBuffer(typed_array.buffer);
await promise_rejects_dom(
t, 'InvalidStateError',
characteristic.writeValueWithResponse(typed_array));
await characteristic.writeValueWithResponse(typed_array);
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_array_equals(lastValue, []);
assert_equals(lastWriteType, 'with-response');

await fake_characteristic.setNextWriteResponse(GATT_SUCCESS);

const array_buffer = Uint8Array.of(3, 4).buffer;
detachBuffer(array_buffer);
await promise_rejects_dom(
t, 'InvalidStateError',
characteristic.writeValueWithResponse(array_buffer));
await characteristic.writeValueWithResponse(array_buffer);
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_array_equals(lastValue, []);
assert_equals(lastWriteType, 'with-response');
}, test_desc);
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,35 @@
// META: script=/bluetooth/resources/bluetooth-fake-devices.js
'use strict';
const test_desc =
'writeValueWithoutResponse() fails when passed a detached buffer';
'Detached buffers are safe to pass to writeValueWithoutResponse()';

function detachBuffer(buffer) {
window.postMessage('', '*', [buffer]);
}

bluetooth_test(async (t) => {
const {characteristic} = await getMeasurementIntervalCharacteristic();
const {characteristic, fake_characteristic} =
await getMeasurementIntervalCharacteristic();

let lastValue, lastWriteType;
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_equals(lastValue, null);
assert_equals(lastWriteType, 'none');

const typed_array = Uint8Array.of(1, 2);
detachBuffer(typed_array.buffer);
await promise_rejects_dom(
t, 'InvalidStateError',
characteristic.writeValueWithoutResponse(typed_array));
await characteristic.writeValueWithoutResponse(typed_array);
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_array_equals(lastValue, []);
assert_equals(lastWriteType, 'without-response');

const array_buffer = Uint8Array.of(3, 4).buffer;
detachBuffer(array_buffer);
await promise_rejects_dom(
t, 'InvalidStateError',
characteristic.writeValueWithoutResponse(array_buffer));
await characteristic.writeValueWithoutResponse(array_buffer);
({lastValue, lastWriteType} =
await fake_characteristic.getLastWrittenValue());
assert_array_equals(lastValue, []);
assert_equals(lastWriteType, 'without-response');
}, test_desc);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// META: script=/bluetooth/resources/bluetooth-test.js
// META: script=/bluetooth/resources/bluetooth-fake-devices.js
'use strict';
const test_desc = 'writeValue() fails when passed a detached buffer';
const test_desc = 'Detached buffers are safe to pass to writeValue()';

function detachBuffer(buffer) {
window.postMessage('', '*', [buffer]);
Expand All @@ -12,13 +12,22 @@ function detachBuffer(buffer) {
bluetooth_test(async (t) => {
const {descriptor, fake_descriptor} = await getUserDescriptionDescriptor();

let lastValue = await fake_descriptor.getLastWrittenValue();
assert_equals(lastValue, null);

await fake_descriptor.setNextWriteResponse(GATT_SUCCESS);

const typed_array = Uint8Array.of(1, 2);
detachBuffer(typed_array.buffer);
await promise_rejects_dom(
t, 'InvalidStateError', descriptor.writeValue(typed_array));
await descriptor.writeValue(typed_array);
lastValue = await fake_descriptor.getLastWrittenValue();
assert_array_equals(lastValue, []);

await fake_descriptor.setNextWriteResponse(GATT_SUCCESS);

const array_buffer = Uint8Array.of(3, 4).buffer;
detachBuffer(array_buffer);
await promise_rejects_dom(
t, 'InvalidStateError', descriptor.writeValue(array_buffer));
await descriptor.writeValue(array_buffer);
lastValue = await fake_descriptor.getLastWrittenValue();
assert_array_equals(lastValue, []);
}, test_desc);
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ bluetooth_test(async (t) => {
const typed_array = Uint8Array.of(1, 2);
detachBuffer(typed_array.buffer);

await promise_rejects_dom(
t, 'InvalidStateError', requestDeviceWithTrustedClick({
// A detached `dataPrefix` is treated as empty, which is an invalid value.
await promise_rejects_js(
t, TypeError, requestDeviceWithTrustedClick({
filters:
[{manufacturerData: [{companyIdentifier, dataPrefix: typed_array}]}]
}));

const array_buffer = Uint8Array.of(3, 4).buffer;
detachBuffer(array_buffer);

await promise_rejects_dom(
t, 'InvalidStateError', requestDeviceWithTrustedClick({
await promise_rejects_js(
t, TypeError, requestDeviceWithTrustedClick({
filters: [
{manufacturerData: [{companyIdentifier, dataPrefix: array_buffer}]}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ bluetooth_test(async (t) => {
const typed_array = Uint8Array.of(1, 2);
detachBuffer(typed_array.buffer);

await promise_rejects_dom(
t, 'InvalidStateError', requestDeviceWithTrustedClick({
// A detached `mask` is treated as empty, which doesn't match the size of
// `dataPrefix`.
await promise_rejects_js(
t, TypeError, requestDeviceWithTrustedClick({
filters: [{
manufacturerData: [{companyIdentifier, dataPrefix, mask: typed_array}]
}]
Expand All @@ -26,8 +28,8 @@ bluetooth_test(async (t) => {
const array_buffer = Uint8Array.of(3, 4).buffer;
detachBuffer(array_buffer);

await promise_rejects_dom(
t, 'InvalidStateError', requestDeviceWithTrustedClick({
await promise_rejects_js(
t, TypeError, requestDeviceWithTrustedClick({
filters: [{
manufacturerData:
[{companyIdentifier, dataPrefix, mask: array_buffer}]
Expand Down

0 comments on commit 960250d

Please sign in to comment.