blob: 7ab983d466d5c919996c58f4579c2a99589beddd [file] [log] [blame]
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: timeout=long
const kJSEmbeddingMaxTypes = 1000000;
const kJSEmbeddingMaxFunctions = 1000000;
const kJSEmbeddingMaxImports = 100000;
const kJSEmbeddingMaxExports = 100000;
const kJSEmbeddingMaxGlobals = 1000000;
const kJSEmbeddingMaxDataSegments = 100000;
const kJSEmbeddingMaxMemoryPages = 65536;
const kJSEmbeddingMaxModuleSize = 1024 * 1024 * 1024; // = 1 GiB
const kJSEmbeddingMaxFunctionSize = 7654321;
const kJSEmbeddingMaxFunctionLocals = 50000;
const kJSEmbeddingMaxFunctionParams = 1000;
const kJSEmbeddingMaxFunctionReturns = 1;
const kJSEmbeddingMaxTableSize = 10000000;
const kJSEmbeddingMaxElementSegments = 10000000;
const kJSEmbeddingMaxTables = 1;
const kJSEmbeddingMaxMemories = 1;
// This function runs the {gen} function with the values {min}, {limit}, and
// {limit+1}, assuming that values below and including the limit should
// pass. {name} is used for test names.
function testLimit(name, min, limit, gen) {
function get_buffer(count) {
const builder = new WasmModuleBuilder();
gen(builder, count);
return builder.toBuffer();
}
const buffer_with_min = get_buffer(min);
const buffer_with_limit = get_buffer(limit);
const buffer_with_limit_plus_1 = get_buffer(limit + 1);
test(() => {
assert_true(WebAssembly.validate(buffer_with_min));
}, `Validate ${name} minimum`);
test(() => {
assert_true(WebAssembly.validate(buffer_with_limit));
}, `Validate ${name} limit`);
test(() => {
assert_false(WebAssembly.validate(buffer_with_limit_plus_1));
}, `Validate ${name} over limit`);
test(() => {
new WebAssembly.Module(buffer_with_min);
}, `Compile ${name} minimum`);
test(() => {
new WebAssembly.Module(buffer_with_limit);
}, `Compile ${name} limit`);
test(() => {
assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer_with_limit_plus_1));
}, `Compile ${name} over limit`);
promise_test(t => {
return WebAssembly.compile(buffer_with_min);
}, `Async compile ${name} minimum`);
promise_test(t => {
return WebAssembly.compile(buffer_with_limit);
}, `Async compile ${name} limit`);
promise_test(t => {
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.compile(buffer_with_limit_plus_1));
}, `Async compile ${name} over limit`);
}
testLimit("types", 1, kJSEmbeddingMaxTypes, (builder, count) => {
for (let i = 0; i < count; i++) {
builder.addType(kSig_i_i);
}
});
testLimit("functions", 1, kJSEmbeddingMaxFunctions, (builder, count) => {
const type = builder.addType(kSig_v_v);
const body = [];
for (let i = 0; i < count; i++) {
builder.addFunction(/*name=*/ undefined, type).addBody(body);
}
});
testLimit("imports", 1, kJSEmbeddingMaxImports, (builder, count) => {
const type = builder.addType(kSig_v_v);
for (let i = 0; i < count; i++) {
builder.addImport("", "", type);
}
});
testLimit("exports", 1, kJSEmbeddingMaxExports, (builder, count) => {
const type = builder.addType(kSig_v_v);
const f = builder.addFunction(/*name=*/ undefined, type);
f.addBody([]);
for (let i = 0; i < count; i++) {
builder.addExport("f" + i, f.index);
}
});
testLimit("globals", 1, kJSEmbeddingMaxGlobals, (builder, count) => {
for (let i = 0; i < count; i++) {
builder.addGlobal(kWasmI32, true);
}
});
testLimit("data segments", 1, kJSEmbeddingMaxDataSegments, (builder, count) => {
const data = [];
builder.addMemory(1, 1, false, false);
for (let i = 0; i < count; i++) {
builder.addDataSegment(0, data);
}
});
testLimit("initial declared memory pages", 1, kJSEmbeddingMaxMemoryPages,
(builder, count) => {
builder.addMemory(count, undefined, false, false);
});
testLimit("maximum declared memory pages", 1, kJSEmbeddingMaxMemoryPages,
(builder, count) => {
builder.addMemory(1, count, false, false);
});
testLimit("initial imported memory pages", 1, kJSEmbeddingMaxMemoryPages,
(builder, count) => {
builder.addImportedMemory("mod", "mem", count, undefined);
});
testLimit("maximum imported memory pages", 1, kJSEmbeddingMaxMemoryPages,
(builder, count) => {
builder.addImportedMemory("mod", "mem", 1, count);
});
testLimit("function size", 2, kJSEmbeddingMaxFunctionSize, (builder, count) => {
const type = builder.addType(kSig_v_v);
const nops = count - 2;
const array = new Array(nops);
for (let i = 0; i < nops; i++) array[i] = kExprNop;
builder.addFunction(undefined, type).addBody(array);
});
testLimit("function locals", 1, kJSEmbeddingMaxFunctionLocals, (builder, count) => {
const type = builder.addType(kSig_v_v);
builder.addFunction(undefined, type)
.addLocals({i32_count: count})
.addBody([]);
});
testLimit("function params", 1, kJSEmbeddingMaxFunctionParams, (builder, count) => {
const array = new Array(count);
for (let i = 0; i < count; i++) {
array[i] = kWasmI32;
}
const type = builder.addType({params: array, results: []});
});
testLimit("function params+locals", 1, kJSEmbeddingMaxFunctionLocals - 2, (builder, count) => {
const type = builder.addType(kSig_i_ii);
builder.addFunction(undefined, type)
.addLocals({i32_count: count})
.addBody([kExprUnreachable]);
});
testLimit("function returns", 0, kJSEmbeddingMaxFunctionReturns, (builder, count) => {
const array = new Array(count);
for (let i = 0; i < count; i++) {
array[i] = kWasmI32;
}
const type = builder.addType({params: [], results: array});
});
testLimit("initial table size", 1, kJSEmbeddingMaxTableSize, (builder, count) => {
builder.setTableBounds(count, undefined);
});
testLimit("maximum table size", 1, kJSEmbeddingMaxTableSize, (builder, count) => {
builder.setTableBounds(1, count);
});
testLimit("element segments", 1, kJSEmbeddingMaxElementSegments, (builder, count) => {
builder.setTableBounds(1, 1);
const array = [];
for (let i = 0; i < count; i++) {
builder.addElementSegment(0, false, array, false);
}
});
testLimit("tables", 0, kJSEmbeddingMaxTables, (builder, count) => {
for (let i = 0; i < count; i++) {
builder.addImportedTable("", "", 1, 1);
}
});
testLimit("memories", 0, kJSEmbeddingMaxMemories, (builder, count) => {
for (let i = 0; i < count; i++) {
builder.addImportedMemory("", "", 1, 1, false);
}
});