// |jit-test| test-also=-P wasm_compact_imports
load(libdir + "wasm-binary.js" );
const { extractStackFrameFunction } = WasmHelpers;
const { Module, RuntimeError, CompileError } = WebAssembly;
const magicError = /failed to match magic number/;
const unknownSection = /expected custom section/;
function sectionError(section) {
return RegExp(`failed to start ${section} section`);
}
function versionError(actual) {
var expect = encodingVersion;
var str = `binary version 0 x${actual.toString(16 )} does not match expected version 0 x${expect.toString(16 )}`;
return RegExp(str);
}
const U32MAX_LEB = [255 , 255 , 255 , 255 , 15 ];
const wasmEval = (code, imports) => new WebAssembly.Instance(new Module(code), imports).exports;
const v2vSig = {args:[], ret:VoidCode};
const v2vSigSection = sigSection([v2vSig]);
const i2vSig = {args:[I32Code], ret:VoidCode};
const v2vBody = funcBody({locals:[], body:[]});
let toBufferOpts = [toU8, toResizableU8];
if (globalThis.SharedArrayBuffer) {
toBufferOpts.push(toSharedU8);
toBufferOpts.push(toGrowableSharedU8);
}
for (let toBuffer of toBufferOpts) {
assertErrorMessage(() => wasmEval(toBuffer([])), CompileError, magicError);
assertErrorMessage(() => wasmEval(toBuffer([42 ])), CompileError, magicError);
assertErrorMessage(() => wasmEval(toBuffer([magic0, magic1, magic2])), CompileError, magicError);
assertErrorMessage(() => wasmEval(toBuffer([1 ,2 ,3 ,4 ])), CompileError, magicError);
assertErrorMessage(() => wasmEval(toBuffer([magic0, magic1, magic2, magic3])), CompileError, /failed to read version/);
assertErrorMessage(() => wasmEval(toBuffer([magic0, magic1, magic2, magic3, 1 ])), CompileError, /failed to read version/);
assertErrorMessage(() => wasmEval(toBuffer([magic0, magic1, magic2, magic3, ver0])), CompileError, /failed to read version/);
assertErrorMessage(() => wasmEval(toBuffer([magic0, magic1, magic2, magic3, ver0, ver1, ver2])), CompileError, /failed to read version/);
assertErrorMessage(() => wasmEval(toBuffer([magic0, magic1, magic2, magic3, 1 , 2 , 3 , 4 ])), CompileError, versionError(0 x4030201));
var o = wasmEval(toBuffer(moduleHeaderThen()));
assertEq(Object.getOwnPropertyNames(o).length, 0 );
// unfinished known sections
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(typeId))), CompileError, sectionError("type" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(importId))), CompileError, sectionError("import" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(functionId))), CompileError, sectionError("function" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(tableId))), CompileError, sectionError("table" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(memoryId))), CompileError, sectionError("memory" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(globalId))), CompileError, sectionError("global" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(exportId))), CompileError, sectionError("export" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(startId))), CompileError, sectionError("start" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(elemId))), CompileError, sectionError("elem" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(codeId))), CompileError, sectionError("code" ));
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(dataId))), CompileError, sectionError("data" ));
// unknown sections are unconditionally rejected
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(37 ))), CompileError, unknownSection);
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(37 , 0 ))), CompileError, unknownSection);
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(37 , 1 , 0 ))), CompileError, unknownSection);
// user sections have special rules
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(0 ))), CompileError, sectionError("custom" )); // no length
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(0 , 0 ))), CompileError, sectionError("custom" )); // no id
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(0 , 0 , 0 ))), CompileError, sectionError("custom" )); // payload too small to have id length
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(0 , 1 , 1 ))), CompileError, sectionError("custom" )); // id not present
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(0 , 1 , 1 , 65 ))), CompileError, sectionError("custom" )); // id length doesn't fit in section
assertErrorMessage(() => wasmEval(toBuffer(moduleHeaderThen(0 , 1 , 0 , 0 ))), CompileError, sectionError("custom" )); // second, unfinished custom section
wasmEval(toBuffer(moduleHeaderThen(0 , 1 , 0 ))); // empty id
wasmEval(toBuffer(moduleHeaderThen(0 , 1 , 0 , 0 , 1 , 0 ))); // 2x empty id
wasmEval(toBuffer(moduleHeaderThen(0 , 2 , 1 , 65 ))); // id = "A"
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: U32MAX_LEB } ], toBuffer)), CompileError, /too many types/);
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1 , 0 ], } ], toBuffer)), CompileError, /expected type form/);
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1 , FuncCode, ...U32MAX_LEB], } ], toBuffer)), CompileError, /too many arguments in signature/);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: typeId, body: [1 ]}], toBuffer)), CompileError);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: typeId, body: [1 , 1 , 0 ]}], toBuffer)), CompileError);
wasmEval(moduleWithSections([sigSection([])], toBuffer));
wasmEval(moduleWithSections([v2vSigSection], toBuffer));
wasmEval(moduleWithSections([sigSection([i2vSig])], toBuffer));
wasmEval(moduleWithSections([sigSection([v2vSig, i2vSig])], toBuffer));
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[], ret:33 }])], toBuffer)), CompileError, /bad type/);
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[33 ], ret:VoidCode}])], toBuffer)), CompileError, /bad type/);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([sigSection([]), declSection([0 ])], toBuffer)), CompileError, /signature index out of range/);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([v2vSigSection, declSection([1 ])], toBuffer)), CompileError, /signature index out of range/);
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0 ])], toBuffer)), CompileError, /expected code section/);
wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([v2vBody])], toBuffer));
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([v2vBody.concat(v2vBody)])], toBuffer)), CompileError, /byte size mismatch in code section/);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([v2vSigSection, {name: importId, body:[]}], toBuffer)), CompileError);
assertErrorMessage(() => wasmEval(moduleWithSections([importSection([{module:"a" , item:"b" , type: externtype({ funcTypeIndex:0 })}])], toBuffer)), CompileError, /signature index out of range/);
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, importSection([{module:"a" , item:"b" , type: externtype({ funcTypeIndex:1 })}])], toBuffer)), CompileError, /signature index out of range/);
wasmEval(moduleWithSections([v2vSigSection, importSection([])], toBuffer));
// Normal import encoding
wasmEval(
moduleWithSections([v2vSigSection, importSection([
{ module: "a" , item: "b" , type: externtype({ funcTypeIndex: 0 }) },
{ module: "a" , item: "c" , type: externtype({ globalType: globalType({ valType: I32Code, mut: true }) }) },
])], toBuffer),
{ a: { b: () => {}, c: new WebAssembly.Global({ value: "i32" , mutable: true }) } },
);
// Compact import encodings
if (wasmCompactImportsEnabled()) {
// Encoding 1: deduplicated module name
{
wasmEval(
moduleWithSections([v2vSigSection, importSection([{ module: "a" , items: [
{ item: "b" , type: externtype({ funcTypeIndex: 0 }) },
{ item: "c" , type: externtype({ globalType: globalType({ valType: I32Code, mut: true }) }) },
]}])], toBuffer),
{ a: { b: () => {}, c: new WebAssembly.Global({ value: "i32" , mutable: true }) } },
);
// Zero-length sections are acceptable
wasmEval(
moduleWithSections([v2vSigSection, importSection([{ module: "a" , items: []}])], toBuffer),
{ a: { b: () => {}, c: new WebAssembly.Global({ value: "i32" , mutable: true }) } },
);
}
// Encoding 2: deduplicated module name and externtype
{
wasmEval(
moduleWithSections([v2vSigSection, importSection([{
module: "a" ,
type: externtype({ funcTypeIndex: 0 }),
items: ["b" , "c" ],
}])], toBuffer),
{ a: { b: () => {}, c: () => {} } },
);
// Zero-length sections are acceptable. There should not be any side
// effects from parsing the externtype before learning that there are
// zero items!
wasmEval(
moduleWithSections([v2vSigSection, importSection([{
module: "a" ,
type: externtype({ funcTypeIndex: 0 }),
items: [],
}])], toBuffer),
);
assertErrorMessage(() => wasmEval(
moduleWithSections([
v2vSigSection,
importSection([{
module: "a" ,
type: externtype({ tableType: tableType(FuncRefCode, limits({ min: 0 })) }),
items: [],
}]),
elemSection([{ mode: "active" , table: 0 , offset: 0 , indices: [] }]),
], toBuffer),
), WebAssembly.CompileError, /table index out of range|active elem segment requires a table/);
}
}
wasmEval(moduleWithSections([
v2vSigSection,
importSection([{module:"a" , item:"" , type: externtype({ funcTypeIndex:0 })}]),
declSection([0 ]),
bodySection([v2vBody])
], toBuffer), {a:{"" :()=>{}}});
assertErrorMessage(() => wasmEval(moduleWithSections([ dataSection([{offset:1 , elems:[]}]) ], toBuffer)), CompileError, /data segment requires a memory section/);
wasmEval(moduleWithSections([defaultTableSection(0 )], toBuffer));
wasmEval(moduleWithSections([elemSection([])], toBuffer));
wasmEval(moduleWithSections([defaultTableSection(0 ), elemSection([])], toBuffer));
wasmEval(moduleWithSections([defaultTableSection(1 ), elemSection([{ mode: "active" , offset: 1 , indices: [] }])], toBuffer));
assertErrorMessage(() => wasmEval(moduleWithSections([defaultTableSection(1 ), elemSection([{ mode: "active" , offset: 0 , indices: [0 ] }])], toBuffer)), CompileError, /element index out of range/);
wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), defaultTableSection(1 ), elemSection([{ mode: "active" , offset: 0 , indices: [0 ] }]), bodySection([v2vBody])], toBuffer));
wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), defaultTableSection(2 ), elemSection([{ mode: "active" , offset: 0 , indices: [0 , 0 ] }]), bodySection([v2vBody])], toBuffer));
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), defaultTableSection(2 ), elemSection([{ mode: "active" , offset: 0 , indices: [0 , 1 ] }]), bodySection([v2vBody])], toBuffer)), CompileError, /element index out of range/);
wasmEval(moduleWithSections([v2vSigSection, declSection([0 ,0 ,0 ]), defaultTableSection(4 ), elemSection([{ mode: "active" , offset: 0 , indices: [0 , 1 , 0 , 2 ] }]), bodySection([v2vBody, v2vBody, v2vBody])], toBuffer));
wasmEval(moduleWithSections([sigSection([v2vSig,i2vSig]), declSection([0 ,0 ,1 ]), defaultTableSection(3 ), elemSection([{ mode: "active" , offset: 0 , indices: [0 , 1 , 2 ] }]), bodySection([v2vBody, v2vBody, v2vBody])], toBuffer));
wasmEval(moduleWithSections([tableSection0()], toBuffer));
wasmEval(moduleWithSections([memorySection(0 )], toBuffer));
function memorySection2() {
var body = [];
body.push(...varU32(2 )); // number of memories
body.push(...varU32(0 x0));
body.push(...varU32(0 ));
body.push(...varU32(0 x0));
body.push(...varU32(0 ));
return { name: memoryId, body };
}
wasmEval(moduleWithSections([memorySection0()], toBuffer));
wasmEval(moduleWithSections([memorySection2()], toBuffer));
// Test early 'end'
const bodyMismatch = /(function body length mismatch)|(operators remaining after end of function )/;
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([funcBody({locals:[], body:[EndCode]})])], toBuffer)), CompileError, bodyMismatch);
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([funcBody({locals:[], body:[UnreachableCode,EndCode]})], toBuffer)])), CompileError, bodyMismatch);
assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([funcBody({locals:[], body:[EndCode,UnreachableCode]})])], toBuffer)), CompileError, bodyMismatch);
// Ignore errors in name section.
var tooBigNameSection = {
name: userDefinedId,
body: [...string(nameName), ...varU32(Math.pow(2 , 31 ))] // declare 2**31 functions.
};
wasmEval(moduleWithSections([tooBigNameSection], toBuffer));
// Custom sections must have valid UTF-8 names
assertErrorMessage(() => wasmEval(toBuffer([0 ,97 ,115 ,109 ,1 ,0 ,0 ,0 ,0 ,3 ,2 ,254 ,255 ,])), CompileError, /failed to start custom section/);
// Skip custom sections before any expected section
var customDefSec = customSection("wee" , 42 , 13 );
var declSec = declSection([0 ]);
var bodySec = bodySection([v2vBody]);
var nameSec = nameSection([funcNameSubsection([{name:'hi' }])]);
wasmEval(moduleWithSections([customDefSec, v2vSigSection, declSec, bodySec], toBuffer));
wasmEval(moduleWithSections([v2vSigSection, customDefSec, declSec, bodySec], toBuffer));
wasmEval(moduleWithSections([v2vSigSection, declSec, customDefSec, bodySec], toBuffer));
wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, customDefSec], toBuffer));
wasmEval(moduleWithSections([customDefSec, customDefSec, v2vSigSection, declSec, bodySec], toBuffer));
wasmEval(moduleWithSections([customDefSec, customDefSec, v2vSigSection, customDefSec, declSec, customDefSec, bodySec], toBuffer));
// custom sections reflection:
function checkCustomSection(buf, val) {
assertEq(buf instanceof ArrayBuffer, true );
assertEq(buf.byteLength, 1 );
assertEq(new Uint8Array(buf)[0 ], val);
}
var custom1 = customSection("one" , 1 );
var custom2 = customSection("one" , 2 );
var custom3 = customSection("two" , 3 );
var custom4 = customSection("three" , 4 );
var custom5 = customSection("three" , 5 );
var custom6 = customSection("three" , 6 );
var m = new Module(moduleWithSections([custom1, v2vSigSection, custom2, declSec, custom3, bodySec, custom4, nameSec, custom5, custom6], toBuffer));
var arr = Module.customSections(m, "one" );
assertEq(arr.length, 2 );
checkCustomSection(arr[0 ], 1 );
checkCustomSection(arr[1 ], 2 );
var arr = Module.customSections(m, "two" );
assertEq(arr.length, 1 );
checkCustomSection(arr[0 ], 3 );
var arr = Module.customSections(m, "three" );
assertEq(arr.length, 3 );
checkCustomSection(arr[0 ], 4 );
checkCustomSection(arr[1 ], 5 );
checkCustomSection(arr[2 ], 6 );
var arr = Module.customSections(m, "name" );
assertEq(arr.length, 1 );
assertEq(arr[0 ].byteLength, nameSec.body.length - 5 /* 4name */);
// Test name/custom section warnings:
const nameWarning = /validated with warning.*'name' custom section/;
const okNameSec = nameSection([]);
assertNoWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, okNameSec], toBuffer)));
const badNameSec1 = nameSection([]);
badNameSec1.body.push(1 );
assertWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, badNameSec1], toBuffer)), nameWarning);
const badNameSec2 = nameSection([funcNameSubsection([{name:'blah' }])]);
badNameSec2.body.push(100 , 20 , 42 , 83 );
assertWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, badNameSec2], toBuffer)), nameWarning);
const badNameSec3 = nameSection([funcNameSubsection([{name:'blah' }])]);
badNameSec3.body.pop();
assertWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, badNameSec3], toBuffer)), nameWarning);
assertNoWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi' )])])));
assertWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi' ), moduleNameSubsection('boo' )])], toBuffer)), nameWarning);
// Unknown name subsection
assertNoWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi' ), [4 , 0 ]])], toBuffer)));
assertWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi' ), [4 , 1 ]])], toBuffer)), nameWarning);
assertNoWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi' ), [4 , 1 , 42 ]])], toBuffer)));
// Provide a module name but no function names.
assertErrorMessage(() => wasmEval(moduleWithSections([
v2vSigSection,
declSection([0 ]),
exportSection([{funcIndex: 0 , name: "f" }]),
bodySection([funcBody({locals:[], body:[UnreachableCode]})]),
nameSection([moduleNameSubsection('hi' )])])
).f(), RuntimeError, /unreachable/);
// Diagnose invalid block signature types.
for (var bad of [0 xff, 1 , 0 x3f])
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0 ]), bodySection([funcBody({locals:[], body:[BlockCode, bad, EndCode]})])], toBuffer)), CompileError, /(invalid .*block type)|(unknown type)/);
const multiValueModule = moduleWithSections([sigSection([v2vSig]), declSection([0 ]), bodySection([funcBody({locals:[], body:[BlockCode, 0 , EndCode]})])], toBuffer);
// In this test module, 0 denotes a void-to-void block type.
assertEq(WebAssembly.validate(multiValueModule), true );
// Ensure all invalid opcodes are rejected. Note that the game here (and for
// the prefixed cases below) is to present only opcodes which will be rejected by
// *both* Baseline and Ion.
for (let op of undefinedOpcodes) {
let binary = moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([funcBody({locals:[], body:[op]})])], toBuffer);
assertErrorMessage(() => wasmEval(binary), CompileError, /((unrecognized|Unknown) opcode)|(tail calls support is not enabled)|(Exceptions support is not enabled)|(Unexpected EOF)/);
assertEq(WebAssembly.validate(binary), false );
}
// Prefixed opcodes
function checkIllegalPrefixed(prefix, opcode) {
let binary = moduleWithSections([v2vSigSection,
declSection([0 ]),
bodySection([funcBody({locals:[],
body:[prefix, ...varU32(opcode)]})])], toBuffer);
assertErrorMessage(() => wasmEval(binary), CompileError, /((unrecognized|Unknown) opcode)|(Unknown.*subopcode)|(Unexpected EOF)|(SIMD support is not enabled)|(invalid lane index)/);
assertEq(WebAssembly.validate(binary), false );
}
// Illegal GcPrefix opcodes
let reservedGc = {
// Structure operations
0 x00: true , 0 x01: true , 0 x02: true , 0 x03: true , 0 x04: true , 0 x05: true ,
// Array operations
0 x06: true , 0 x07: true , 0 x08: true , 0 x09: true , 0 x0a: true , 0 x0b: true ,
0 x0c: true , 0 x0d: true , 0 x0e: true , 0 x0f: true , 0 x10: true , 0 x11: true ,
0 x12: true , 0 x13: true ,
// Ref operations
0 x14: true , 0 x15: true , 0 x16: true , 0 x17: true , 0 x18: true , 0 x19: true ,
0 x1a: true , 0 x1b: true ,
// i31 operations
0 x1c: true , 0 x1d: true , 0 x1e: true ,
};
for (let i = 0 ; i < 256 ; i++) {
if (reservedGc.hasOwnProperty(i)) {
continue ;
}
checkIllegalPrefixed(GcPrefix, i);
}
// Illegal ThreadPrefix opcodes
//
// June 2017 threads draft:
//
// 0x00 .. 0x03 are wait/wake/fence ops
// 0x10 .. 0x4f are primitive atomic ops
for (let i = 0 x4; i < 0 x10; i++)
checkIllegalPrefixed(ThreadPrefix, i);
for (let i = 0 x4f; i < 0 x100; i++)
checkIllegalPrefixed(ThreadPrefix, i);
// Illegal Misc opcodes
var reservedMisc =
{ // Saturating conversions (standardized)
0 x00: true , 0 x01: true , 0 x02: true , 0 x03: true , 0 x04: true , 0 x05: true , 0 x06: true , 0 x07: true ,
// Bulk memory (proposed)
0 x08: true , 0 x09: true , 0 x0a: true , 0 x0b: true , 0 x0c: true , 0 x0d: true , 0 x0e: true ,
// Table (proposed)
0 x0f: true , 0 x10: true , 0 x11: true , 0 x12: true ,
// Wide arithmetic operations (proposed as of Jan 2026)
0 x13: true , 0 x14: true , 0 x15: true , 0 x16: true ,
// Structure operations (experimental, internal)
0 x50: true , 0 x51: true , 0 x52: true , 0 x53: true };
for (let i = 0 ; i < 256 ; i++) {
if (reservedMisc.hasOwnProperty(i))
continue ;
checkIllegalPrefixed(MiscPrefix, i);
}
// Illegal SIMD opcodes - the upper bound is actually very large, not much to be
// done about that.
if (!wasmSimdEnabled()) {
for (let i = 0 ; i < 0 x130; i++) {
checkIllegalPrefixed(SimdPrefix, i);
}
} else {
let reservedSimd = [
0 x9a, 0 xa2, 0 xa5, 0 xa6, 0 xaf, 0 xb0, 0 xb2, 0 xb3, 0 xb4, 0 xbb,
0 xc2, 0 xc5, 0 xc6, 0 xcf, 0 xd0, 0 xd2, 0 xd3, 0 xd4, 0 xe2, 0 xee,
0 x115, 0 x116, 0 x117,
0 x118, 0 x119, 0 x11a, 0 x11b, 0 x11c, 0 x11d, 0 x11e, 0 x11f,
0 x120, 0 x121, 0 x122, 0 x123, 0 x124, 0 x125, 0 x126, 0 x127,
0 x128, 0 x129, 0 x12a, 0 x12b, 0 x12c, 0 x12d, 0 x12e, 0 x12f,
];
for (let i of reservedSimd) {
checkIllegalPrefixed(SimdPrefix, i);
}
}
// Illegal MozPrefix opcodes (all of them)
for (let i = 0 ; i < 256 ; i++)
checkIllegalPrefixed(MozPrefix, i);
for (let prefix of [ThreadPrefix, MiscPrefix, SimdPrefix, MozPrefix]) {
// Prefix without a subsequent opcode. We must ask funcBody not to add an
// End code after the prefix, so the body really is just the prefix byte.
let binary = moduleWithSections([v2vSigSection, declSection([0 ]), bodySection([funcBody({locals:[], body:[prefix]}, /*withEndCode=*/false)])], toBuffer);
assertErrorMessage(() => wasmEval(binary), CompileError, /(unable to read opcode)|(Unexpected EOF)|(Unknown opcode)/);
assertEq(WebAssembly.validate(binary), false );
}
}
// Checking stack trace.
function runStackTraceTest(moduleName, funcNames, expectedName) {
var sections = [
sigSection([v2vSig]),
importSection([{module:"env" , item:"callback" , type: externtype({ funcTypeIndex:0 })}]),
declSection([0 ]),
exportSection([{funcIndex:1 , name: "run" }]),
bodySection([funcBody({locals: [], body: [CallCode, varU32(0 )]})]),
customSection("whoa" ),
customSection("wee" , 42 ),
];
if (moduleName || funcNames) {
var subsections = [];
if (moduleName)
subsections.push(moduleNameSubsection(moduleName));
if (funcNames)
subsections.push(funcNameSubsection(funcNames));
sections.push(nameSection(subsections));
}
sections.push(customSection("yay" , 13 ));
var result = "" ;
var callback = () => {
result = extractStackFrameFunction(new Error().stack.split('\n' )[1 ]);
};
wasmEval(moduleWithSections(sections), {"env" : { callback }}).run();
assertEq(result, expectedName);
};
runStackTraceTest(null , null , 'wasm-function[1]' );
runStackTraceTest(null , [{name:'blah' }, {name:'test' }], 'test' );
runStackTraceTest(null , [{name:'test' , index:1 }], 'test' );
runStackTraceTest(null , [{name:'blah' }, {name:'test' , locals: [{name: 'var1' }, {name: 'var2' }]}], 'test' );
runStackTraceTest(null , [{name:'blah' }, {name:'test' , locals: [{name: 'var1' }, {name: 'var2' }]}], 'test' );
runStackTraceTest(null , [{name:'blah' }, {name:'test1' }], 'test1' );
runStackTraceTest(null , [{name:'blah' }, {name:'test☃' }], 'test☃' );
runStackTraceTest(null , [{name:'blah' }, {name:'te\xE0\xFF' }], 'te\xE0\xFF' );
runStackTraceTest(null , [{name:'blah' }], 'wasm-function[1]' );
runStackTraceTest(null , [], 'wasm-function[1]' );
runStackTraceTest("" , [{name:'blah' }, {name:'test' }], 'test' );
runStackTraceTest("a" , [{name:'blah' }, {name:'test' }], 'a.test' );
// Notice that invalid names section content shall not fail the parsing
runStackTraceTest(null , [{name:'blah' }, {name:'test' , index: 2 }], 'wasm-function[1]' ); // invalid index
runStackTraceTest(null , [{name:'blah' }, {name:'test' , index: 100000 }], 'wasm-function[1]' ); // invalid index
runStackTraceTest(null , [{name:'blah' }, {name:'test' , nameLen: 100 }], 'wasm-function[1]' ); // invalid name size
runStackTraceTest(null , [{name:'blah' }, {name:'' }], 'wasm-function[1]' ); // empty name
// Enable and disable Gecko profiling mode, to ensure all live instances
// names won't make us crash.
enableGeckoProfiling();
disableGeckoProfiling();
function testValidNameSectionWithProfiling() {
enableGeckoProfiling();
wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, nameSec]));
disableGeckoProfiling();
}
testValidNameSectionWithProfiling();
// Memory alignment can use non-minimal LEB128
wasmEval(moduleWithSections([
v2vSigSection,
declSection([0 ]),
memorySection(0 ),
bodySection([
funcBody({locals: [], body: [
I32ConstCode, 0 x00, // i32.const 0
I32Load,
0 x81, 0 x00, // alignment 1, non-minimal
0 x00, // offset 0
DropCode,
]}),
]),
]));
Messung V0.5 in Prozent C=85 H=88 G=86
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-08-26)
¤
*© Formatika GbR, Deutschland