module.getCompilationInfo() resolves to GPUCompilationMessage objects: message, type ('error', 'warning' or 'info'), one-based lineNum and linePos, and offset and length in UTF-16 code units, ready for code.substr(offset, length). Order and wording are up to the browser. This variant of the helper's compileWGSL() underlines each problem in its source line, as an editor would:
<script type="module">
const device = await (await navigator.gpu.requestAdapter()).requestDevice();
const code = `fn sale(price: f32) -> f32 {
return round(price * 85) / 100;
let unused = price;
}
fn inStock(copies: u32) -> bool {
return copies > 0.5;
}`;
const module = device.createShaderModule({ label: 'sale.wgsl', code });
for (const m of (await module.getCompilationInfo()).messages) {
console.log(`${m.type} ${m.lineNum}:${m.linePos}, offset ${m.offset}, length ${m.length}`);
console.log(` ${code.split('\n')[m.lineNum - 1]}`); // the source line
const mark = ' '.repeat(m.linePos - 1) + '^'.repeat(m.length); // the underline
console.log(` ${mark} ${m.message.split('\n')[0]}`);
}
</script>warning 3:3, offset 65, length 10
let unused = price;
^^^^^^^^^^ code is unreachable
error 6:10, offset 130, length 12
return copies > 0.5;
^^^^^^^^^^^^ no matching overload for 'operator > (u32, abstract-float)'The device also gets a validation error carrying Chrome 1 's full report (warnings alone raise none), and messages after the first error may be missing (Storage Access Modes). In production, log errors with the module's label.