v8/test/mjsunit/wasm/stringrefs-exec.js
Andy Wingo ec8b247201 [stringrefs] Implement string.new_wtf16
Bug: v8:12868
Change-Id: Ied5e985db139517ec34446bcb8b16041e5d79af7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3663092
Commit-Queue: Andy Wingo <wingo@igalia.com>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80823}
2022-05-30 15:12:46 +00:00

142 lines
4.2 KiB
JavaScript

// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-stringref
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
let kSig_w_ii = makeSig([kWasmI32, kWasmI32], [kWasmStringRef]);
function encodeWtf8(str) {
// String iterator coalesces surrogate pairs.
let out = [];
for (let codepoint of str) {
codepoint = codepoint.codePointAt(0);
if (codepoint <= 0x7f) {
out.push(codepoint);
} else if (codepoint <= 0x7ff) {
out.push(0xc0 | (codepoint >> 6));
out.push(0x80 | (codepoint & 0x3f));
} else if (codepoint <= 0xffff) {
out.push(0xe0 | (codepoint >> 12));
out.push(0x80 | ((codepoint >> 6) & 0x3f));
out.push(0x80 | (codepoint & 0x3f));
} else if (codepoint <= 0x10ffff) {
out.push(0xf0 | (codepoint >> 18));
out.push(0x80 | ((codepoint >> 12) & 0x3f));
out.push(0x80 | ((codepoint >> 6) & 0x3f));
out.push(0x80 | (codepoint & 0x3f));
} else {
throw new Error("bad codepoint " + codepoint);
}
}
return out;
}
function makeWtf8TestDataSegment() {
let data = []
let valid = {};
let invalid = {};
for (let str of ['',
'ascii',
'latin \xa9 1',
'two \ucccc byte',
'surrogate \ud800\udc000 pair',
'isolated \ud800 leading',
'isolated \udc00 trailing']) {
let bytes = encodeWtf8(str);
valid[str] = { offset: data.length, length: bytes.length };
for (let byte of bytes) {
data.push(byte);
}
}
for (let bytes of ['trailing high byte \xa9',
'interstitial high \xa9 byte',
'invalid \xc0 byte',
'surrogate \xed\xa0\x80\xed\xd0\x80 pair']) {
invalid[bytes] = { offset: data.length, length: bytes.length };
for (let i = 0; i < bytes.length; i++) {
data.push(bytes.charCodeAt(i));
}
}
return { valid, invalid, data: Uint8Array.from(data) };
};
(function TestStringNewWtf8() {
let builder = new WasmModuleBuilder();
builder.addMemory(1, undefined, false, false);
let data = makeWtf8TestDataSegment();
builder.addDataSegment(0, data.data);
builder.addFunction("string_new_wtf8", kSig_w_ii)
.exportAs("string_new_wtf8")
.addBody([
kExprLocalGet, 0, kExprLocalGet, 1,
kGCPrefix, kExprStringNewWtf8, 0
]);
let instance = builder.instantiate();
for (let [str, {offset, length}] of Object.entries(data.valid)) {
assertEquals(str, instance.exports.string_new_wtf8(offset, length));
}
for (let [str, {offset, length}] of Object.entries(data.invalid)) {
assertThrows(() => instance.exports.string_new_wtf8(offset, length),
WebAssembly.RuntimeError, "invalid WTF-8 string");
}
})();
function encodeWtf16LE(str) {
// String iterator coalesces surrogate pairs.
let out = [];
for (let i = 0; i < str.length; i++) {
codeunit = str.charCodeAt(i);
out.push(codeunit & 0xff)
out.push(codeunit >> 8);
}
return out;
}
function makeWtf16TestDataSegment() {
let data = []
let valid = {};
for (let str of ['',
'ascii',
'latin \xa9 1',
'two \ucccc byte',
'surrogate \ud800\udc000 pair',
'isolated \ud800 leading',
'isolated \udc00 trailing']) {
valid[str] = { offset: data.length, length: str.length };
for (let byte of encodeWtf16LE(str)) {
data.push(byte);
}
}
return { valid, data: Uint8Array.from(data) };
};
(function TestStringNewWtf16() {
let builder = new WasmModuleBuilder();
builder.addMemory(1, undefined, false, false);
let data = makeWtf16TestDataSegment();
builder.addDataSegment(0, data.data);
builder.addFunction("string_new_wtf16", kSig_w_ii)
.exportAs("string_new_wtf16")
.addBody([
kExprLocalGet, 0, kExprLocalGet, 1,
kGCPrefix, kExprStringNewWtf16, 0
]);
let instance = builder.instantiate();
for (let [str, {offset, length}] of Object.entries(data.valid)) {
assertEquals(str, instance.exports.string_new_wtf16(offset, length));
}
})();