From 9774d70c4b3b6944743651c18a9d9fd5fbd471d0 Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Fri, 20 Mar 2020 17:35:48 +0100 Subject: [PATCH] Encoding: use Wasm to get a SharedArrayBuffer instance For https://github.com/web-platform-tests/wpt/issues/22358. --- encoding/encodeInto.any.js | 44 +++++++++++++++++++-------- encoding/streams/decode-utf8.any.js | 19 +++++++++--- encoding/textdecoder-copy.any.js | 21 ++++++++++--- encoding/textdecoder-streaming.any.js | 13 +++++++- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/encoding/encodeInto.any.js b/encoding/encodeInto.any.js index 7e18c812499a52..807c753980377b 100644 --- a/encoding/encodeInto.any.js +++ b/encoding/encodeInto.any.js @@ -1,3 +1,21 @@ +function createBuffer(type, length = 0) { + if (type === "ArrayBuffer") { + return new ArrayBuffer(length); + } else { + // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` + // WebAssembly.Memory's size is in multiples of 64 KiB + return new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer; + } +} + +function createViewWithBuffer(type, length) { + if (type === "ArrayBuffer") { + return new Uint8Array(new ArrayBuffer(length)); + } else { + return new Uint8Array(createBuffer(type), 0, length); + } +} + [ { "input": "Hi", @@ -77,15 +95,15 @@ ["ArrayBuffer", "SharedArrayBuffer"].forEach(arrayBufferOrSharedArrayBuffer => { test(() => { // Setup - const bufferLength = testData.destinationLength + destinationData.bufferIncrease, - destinationOffset = destinationData.destinationOffset, - destinationLength = testData.destinationLength, - destinationFiller = destinationData.filler, - encoder = new TextEncoder(), - buffer = new self[arrayBufferOrSharedArrayBuffer](bufferLength), - view = new Uint8Array(buffer, destinationOffset, destinationLength), - fullView = new Uint8Array(buffer), - control = new Array(bufferLength); + const bufferLength = testData.destinationLength + destinationData.bufferIncrease; + const destinationOffset = destinationData.destinationOffset; + const destinationLength = testData.destinationLength; + const destinationFiller = destinationData.filler; + const encoder = new TextEncoder(); + const buffer = createBuffer(arrayBufferOrSharedArrayBuffer, bufferLength); + const view = new Uint8Array(buffer, destinationOffset, destinationLength); + const fullView = new Uint8Array(buffer); + const control = new Array(bufferLength); let byte = destinationFiller; for (let i = 0; i < bufferLength; i++) { if (destinationFiller === "random") { @@ -105,6 +123,8 @@ // Remainder assert_equals(result.read, testData.read); assert_equals(result.written, testData.written.length); + // This will not check the entire buffer allocated by WebAssembly.Memory, but we'll trust + // that this is sufficient. for (let i = 0; i < bufferLength; i++) { if (i < destinationOffset || i >= (destinationOffset + testData.written.length)) { assert_equals(fullView[i], control[i]); @@ -128,19 +148,17 @@ Float64Array].forEach(view => { ["ArrayBuffer", "SharedArrayBuffer"].forEach((arrayBufferOrSharedArrayBuffer) => { test(() => { - assert_throws_js(TypeError, () => new TextEncoder().encodeInto("", new view(new self[arrayBufferOrSharedArrayBuffer](0)))); + assert_throws_js(TypeError, () => new TextEncoder().encodeInto("", createViewWithBuffer(arrayBufferOrSharedArrayBuffer, 0))); }, "Invalid encodeInto() destination: " + view.name + ", backed by: " + arrayBufferOrSharedArrayBuffer); }); }); ["ArrayBuffer", "SharedArrayBuffer"].forEach((arrayBufferOrSharedArrayBuffer) => { test(() => { - assert_throws_js(TypeError, () => new TextEncoder().encodeInto("", new self[arrayBufferOrSharedArrayBuffer](10))); + assert_throws_js(TypeError, () => new TextEncoder().encodeInto("", createBuffer(arrayBufferOrSharedArrayBuffer, 10))); }, "Invalid encodeInto() destination: " + arrayBufferOrSharedArrayBuffer); }); - - test(() => { const buffer = new ArrayBuffer(10), view = new Uint8Array(buffer); diff --git a/encoding/streams/decode-utf8.any.js b/encoding/streams/decode-utf8.any.js index 421b98c2eea537..27e14e47ab59b7 100644 --- a/encoding/streams/decode-utf8.any.js +++ b/encoding/streams/decode-utf8.any.js @@ -5,11 +5,22 @@ 'use strict'; ["ArrayBuffer", "SharedArrayBuffer"].forEach((arrayBufferOrSharedArrayBuffer) => { - const inputChunkData = [73, 32, 240, 159, 146, 153, 32, 115, 116, - 114, 101, 97, 109, 115] + const inputChunkData = [73, 32, 240, 159, 146, 153, 32, 115, 116, 114, 101, 97, 109, 115]; - const emptyChunk = new Uint8Array(new self[arrayBufferOrSharedArrayBuffer](0)); - const inputChunk = new Uint8Array(new self[arrayBufferOrSharedArrayBuffer](inputChunkData.length)); + function createViewWithBuffer(type, length) { + if (type === "ArrayBuffer") { + return new Uint8Array(new ArrayBuffer(length)); + } else { + // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` + // WebAssembly.Memory's size is in multiples of 64 KiB + const size = (length === 0) ? 0 : 1; + const buffer = new WebAssembly.Memory({ shared:true, initial:size, maximum:size }).buffer; + return new Uint8Array(buffer, 0, length); + } + } + + const emptyChunk = createViewWithBuffer(arrayBufferOrSharedArrayBuffer, 0); + const inputChunk = createViewWithBuffer(arrayBufferOrSharedArrayBuffer, inputChunkData.length); inputChunk.set(inputChunkData); diff --git a/encoding/textdecoder-copy.any.js b/encoding/textdecoder-copy.any.js index 6ae65119db687c..874478fdf11843 100644 --- a/encoding/textdecoder-copy.any.js +++ b/encoding/textdecoder-copy.any.js @@ -1,10 +1,21 @@ +function createViewWithBuffer(type, length) { + if (type === "ArrayBuffer") { + return new Uint8Array(new ArrayBuffer(length)); + } else { + // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` + // WebAssembly.Memory's size is in multiples of 64 KiB + const buffer = new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer; + return new Uint8Array(buffer, 0, length); + } +} + ["ArrayBuffer", "SharedArrayBuffer"].forEach(arrayBufferOrSharedArrayBuffer => { test(() => { - const buf = new self[arrayBufferOrSharedArrayBuffer](2), - view = new Uint8Array(buf), - buf2 = new self[arrayBufferOrSharedArrayBuffer](2), - view2 = new Uint8Array(buf2), - decoder = new TextDecoder("utf-8"); + const view = createViewWithBuffer(arrayBufferOrSharedArrayBuffer, 2); + const buf = view.buffer; + const view2 = createViewWithBuffer(arrayBufferOrSharedArrayBuffer, 2); + const buf2 = view2.buffer; + const decoder = new TextDecoder("utf-8"); view[0] = 0xEF; view[1] = 0xBB; view2[0] = 0xBF; diff --git a/encoding/textdecoder-streaming.any.js b/encoding/textdecoder-streaming.any.js index e0c59472598fbd..0ec2a4908202b5 100644 --- a/encoding/textdecoder-streaming.any.js +++ b/encoding/textdecoder-streaming.any.js @@ -16,6 +16,17 @@ var octets = { 0xDF,0xFF] }; +function createViewWithBuffer(type, length) { + if (type === "ArrayBuffer") { + return new Uint8Array(new ArrayBuffer(length)); + } else { + // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` + // WebAssembly.Memory's size is in multiples of 64 KiB + const buffer = new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer; + return new Uint8Array(buffer, 0, length); + } +} + ["ArrayBuffer", "SharedArrayBuffer"].forEach((arrayBufferOrSharedArrayBuffer) => { Object.keys(octets).forEach(function(encoding) { for (var len = 1; len <= 5; ++len) { @@ -28,7 +39,7 @@ var octets = { var sub = []; for (var j = i; j < encoded.length && j < i + len; ++j) sub.push(encoded[j]); - var uintArray = new Uint8Array(new self[arrayBufferOrSharedArrayBuffer](sub.length)); + var uintArray = createViewWithBuffer(arrayBufferOrSharedArrayBuffer, sub.length); uintArray.set(sub); out += decoder.decode(uintArray, {stream: true}); }