Start · Sprachen · JavaScript · Referenz · GPUCompilationMessage.offset

GPUCompilationMessage.offset

Eigenschaft

Schreibgeschützte Zahl: Abstand in UTF-16-Codeeinheiten vom Anfang des WGSL-Shader-Codes bis zu der Stelle, auf die sich eine Compiler-Meldung bezieht.

seit JavaScript WebGPU: Chrome/Edge 113+, Safari 26+, Firefox 141+ Kategorie: webapi

Signatur

GPUCompilationMessage.offset

Beschreibung

Die schreibgeschützte Eigenschaft offset einer GPUCompilationMessage gibt an, wo im Quelltext eines Shader-Moduls die gemeldete Stelle liegt. Das kann ein einzelner Punkt sein oder der Anfang eines Abschnitts. Gezählt wird ab dem Anfang des Strings, der als code an GPUDevice.createShaderModule() übergeben wurde. Die Zählung beginnt bei 0 und erfolgt in UTF-16-Codeeinheiten, also genauso wie String-Indizes in JavaScript.

Zusammen mit length beschreibt offset genau den betroffenen Abschnitt. Mit code.slice(msg.offset, msg.offset + msg.length) holen Sie ihn direkt aus dem Quelltext. Das eignet sich gut, um Fehlerstellen in einem Shader-Editor zu markieren, zum Beispiel mit Wellenlinien, oder um eigene Fehlermeldungen mit Codeausschnitt zu bauen.

Die Meldungen erhalten Sie über GPUShaderModule.getCompilationInfo(). Das Promise liefert eine GPUCompilationInfo, deren Array messages die einzelnen GPUCompilationMessage-Objekte enthält. Jede Meldung hat einen type ("error", "warning" oder "info"), einen Text und die Positionsangaben offset, length, lineNum und linePos.

Rückgabewert

Typ
number
Beschreibung
Eine nicht-negative ganze Zahl: der 0-basierte Abstand in UTF-16-Codeeinheiten vom Anfang des Shader-Codes. Hat die Meldung keinen Bezug zu einer Stelle im Quelltext, ist der Wert 0 (und length ebenfalls 0).

Beispiele

Compiler-Meldungen mit Position ausgeben

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const code = `@fragment
fn main() -> @location(0) vec4f {
  return vec4f(1.0, 0.0, 0.0);
}`;

const module = device.createShaderModule({ code });
const info = await module.getCompilationInfo();

for (const msg of info.messages) {
  console.log(`${msg.type} bei Offset ${msg.offset} (Länge ${msg.length}): ${msg.message}`);
}
error bei Offset 50 (Länge 21): ... (Meldungstext, Offset und Länge hängen vom Browser ab)

Fehlerhaften Abschnitt aus dem Quelltext holen

const showErrors = async (device, code) => {
  const module = device.createShaderModule({ code });
  const { messages } = await module.getCompilationInfo();

  return messages
    .filter((m) => m.type === 'error')
    .map((m) => ({
      text: m.message,
      snippet: code.slice(m.offset, m.offset + m.length),
      line: m.lineNum,
      column: m.linePos
    }));
};

const errors = await showErrors(device, 'fn f() -> i32 { return 1.5; }');
console.table(errors);
Tabelle mit text, snippet (z. B. "1.5"), line und column

Fehlerstelle im Editor markieren (HTML-Ausgabe)

const escape = (s) => s.replace(/[&<>]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' })[c]);

const highlight = (code, msg) => {
  const start = msg.offset;
  const end = start + Math.max(msg.length, 1); // bei Länge 0 mindestens ein Zeichen markieren
  return escape(code.slice(0, start)) +
    '<mark>' + escape(code.slice(start, end)) + '</mark>' +
    escape(code.slice(end));
};

const { messages } = await module.getCompilationInfo();
if (messages.length > 0) {
  document.querySelector('#editor').innerHTML = highlight(code, messages[0]);
}

// Wichtig · Fallstricke

  • UTF-16 statt Bytes oder Zeichen: offset zählt UTF-16-Codeeinheiten. Bei Emojis oder anderen Zeichen außerhalb der BMP (in Kommentaren) stimmt der Wert deshalb nicht mit der Anzahl sichtbarer Zeichen überein. Für String.prototype.slice() passt er aber genau.
  • Unterschiedliche Zählbasis: offset beginnt bei 0, lineNum und linePos beginnen bei 1. Nicht vermischen.
  • Kein Positionsbezug: Bei allgemeinen Meldungen sind offset und length beide 0. Prüfen Sie deshalb auch length oder lineNum, bevor Sie eine Stelle markieren.
  • Browserabhängig: Ob Warnungen oder Infos erscheinen, der Meldungstext und die genaue Länge des Abschnitts hängen von der Implementierung ab. Die Werte eignen sich zur Anzeige, nicht für feste Tests.
  • Sicherheit: Wenn Sie Codeausschnitte per innerHTML einfügen, müssen Sie Quelltext und Meldungstext vorher maskieren (siehe Beispiel 3), sonst droht XSS.
  • Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht in allen Browsern. Prüfen Sie vorher mit if (!navigator.gpu), ob die API vorhanden ist.