Commit af08f139 authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

[mojo-bindings] Fix complex arrays for JS lite

We underestimate the total size of a message carrying arrays with struct
elements. This fixes that.

Bug: 905529
Change-Id: Ib05fa52e42d850c3ebe38bd4f716f7c1327e4cd7
Reviewed-on: https://chromium-review.googlesource.com/c/1336779Reviewed-by: default avatarcalamity <calamity@chromium.org>
Commit-Queue: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#608246}
parent 5805cf76
......@@ -4,6 +4,10 @@
module lite_js_test.mojom;
struct TestStruct {
int32 x;
};
// An interface whose definition covers various types of message signatures in
// order to exercise the lite JS mojom bindings.
interface TestMessageTarget {
......@@ -17,6 +21,8 @@ interface TestMessageTarget {
Repeat(string? message, array<int32>? numbers)
=> (string? message, array<int32>? numbers);
Flatten(array<TestStruct> values) => (array<int32> values);
RequestSubinterface(Subinterface& request, SubinterfaceClient client);
};
......
......@@ -724,15 +724,36 @@ mojo.internal.computeTotalStructSize = function(structSpec, value) {
* @param {number} length
* @return {number}
*/
mojo.internal.computeArraySize = function(arraySpec, length) {
mojo.internal.computeInlineArraySize = function(arraySpec, value) {
if (arraySpec.elementType === mojo.mojom.Bool) {
return mojo.internal.kArrayHeaderSize + (length + 7) >> 3;
return mojo.internal.kArrayHeaderSize + (value.length + 7) >> 3;
} else {
return mojo.internal.kArrayHeaderSize +
length * arraySpec.elementType.$.arrayElementSize;
value.length * arraySpec.elementType.$.arrayElementSize;
}
};
/**
* @param {!mojo.internal.ArraySpec} arraySpec
* @param {number} length
* @return {number}
*/
mojo.internal.computeTotalArraySize = function(arraySpec, value) {
const inlineSize = mojo.internal.computeInlineArraySize(arraySpec, value);
if (!arraySpec.elementType.$.computePayloadSize)
return inlineSize;
let totalSize = inlineSize;
for (let elementValue of value) {
if (!mojo.internal.isNullOrUndefined(elementValue)) {
totalSize += mojo.internal.align(
arraySpec.elementType.$.computePayloadSize(elementValue), 8);
}
}
return totalSize;
};
/**
* @param {!DataView} dataView
* @param {number} byteOffset
......@@ -908,7 +929,7 @@ mojo.internal.Encoder = class {
* @param {*} value
*/
encodeArray(arraySpec, offset, value) {
const arraySize = mojo.internal.computeArraySize(arraySpec, value.length);
const arraySize = mojo.internal.computeInlineArraySize(arraySpec, value);
const arrayData = this.message_.allocate(arraySize);
const arrayEncoder = new mojo.internal.Encoder(this.message_, arrayData);
this.encodeOffset(offset, arrayData.byteOffset);
......@@ -1573,8 +1594,8 @@ mojo.mojom.String = {
return decoder.decodeString(byteOffset);
},
computePayloadSize: function(value) {
return mojo.internal.computeArraySize(
{elementType: mojo.mojom.Uint8}, value.length);
return mojo.internal.computeTotalArraySize(
{elementType: mojo.mojom.Uint8}, value);
},
arrayElementSize: 8,
isValidObjectKeyType: true,
......@@ -1604,7 +1625,7 @@ mojo.mojom.Array = function(elementType, elementNullable) {
return decoder.decodeArray(arraySpec, byteOffset);
},
computePayloadSize: function(value) {
return mojo.internal.computeArraySize(arraySpec, value.length);
return mojo.internal.computeTotalArraySize(arraySpec, value);
},
arrayElementSize: 8,
isValidObjectKeyType: false,
......@@ -1637,16 +1658,19 @@ mojo.mojom.Map = function(keyType, valueType, valueNullable) {
return decoder.decodeMap(mapSpec, byteOffset);
},
computePayloadSize: function(value) {
const numEntries =
(value instanceof Map) ? value.size : Object.keys(value).length;
const keys = (value instanceof Map) ? Array.from(value.keys()) :
Object.keys(value);
const values = (value instanceof Map) ? Array.from(value.values()) :
keys.map(k => value[k]);
return mojo.internal.kMapDataSize +
mojo.internal.computeArraySize({elementType: keyType}, numEntries) +
mojo.internal.computeArraySize(
mojo.internal.computeTotalArraySize({elementType: keyType}, keys) +
mojo.internal.computeTotalArraySize(
{
elementType: valueType,
elementNullable: valueNullable,
},
numEntries);
values);
},
arrayElementSize: 8,
isValidObjectKeyType: false,
......
......@@ -18,6 +18,7 @@ class TargetImpl {
poke() { this.numPokes++; }
ping() { return Promise.resolve(); }
repeat(message, numbers) { return {message: message, numbers: numbers}; }
flatten(values) {}
requestSubinterface(request, client) {}
}
......@@ -118,4 +119,13 @@ promise_test(() => {
subinterfaceProxy.flush();
});
}, 'can send and receive interface requests and proxies');
promise_test(() => {
let targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
let targetProxy = targetRouter.createProxy();
targetRouter.flatten.addListener(values => ({values: values.map(v => v.x)}));
return targetProxy.flatten([{x: 1}, {x: 2}, {x: 3}]).then(reply => {
assert_array_equals(reply.values, [1, 2, 3]);
});
}, 'regression test for complex array serialization');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment