Start · Sprachen · JavaScript · Referenz · GPUCompilationMessage.linePos

GPUCompilationMessage.linePos

Eigenschaft

Schreibgeschützte Zahl: die 1-basierte Spaltenposition (in UTF-16-Codeeinheiten) innerhalb der Shader-Codezeile, auf die sich eine Compiler-Meldung bezieht.

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

Signatur

GPUCompilationMessage.linePos

Beschreibung

Die Eigenschaft linePos einer GPUCompilationMessage gibt an, an welcher Stelle innerhalb einer Zeile des WGSL-Shader-Codes eine Fehlermeldung, Warnung oder ein Hinweis beginnt. Zusammen mit lineNum ergibt sich so eine Position im Stil „Zeile:Spalte“, wie man sie aus Compiler-Ausgaben und Code-Editoren kennt.

Der Wert ist 1-basiert und wird in UTF-16-Codeeinheiten gezählt – also genauso wie JavaScript-String-Indizes, nur um eins verschoben. Bezieht sich eine Meldung nicht auf eine bestimmte Stelle (etwa auf den gesamten Shader), ist linePos 0.

Man erhält GPUCompilationMessage-Objekte über GPUShaderModule.getCompilationInfo(), das ein GPUCompilationInfo-Objekt mit dem Array messages liefert. Typische Anwendungen sind eigene Fehlerausgaben mit Markierung unter der fehlerhaften Stelle (Caret) oder das Setzen von Markierungen in Online-Shader-Editoren.

Rückgabewert

Typ
number
Beschreibung
Ganzzahl ≥ 0: 1-basierte Spalte (in UTF-16-Codeeinheiten) innerhalb der Zeile lineNum; 0, wenn die Meldung keiner bestimmten Position zugeordnet ist.

Beispiele

Compiler-Meldungen mit Zeile und Spalte ausgeben

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

const code = `@vertex
fn main() -> @builtin(position) vec4f {
  return vec4f(0.0, 0.0, 0.0, 1.0)
}`; // fehlendes Semikolon

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

for (const msg of info.messages) {
  console.log(`${msg.type} [${msg.lineNum}:${msg.linePos}] ${msg.message}`);
}
error [3:36] expected ';' for return statement

Fehlerstelle mit Caret (^) markieren

const formatMessage = (source, msg) => {
  if (msg.lineNum === 0) return `${msg.type}: ${msg.message}`;
  const line = source.split('\n')[msg.lineNum - 1] ?? '';
  // linePos ist 1-basiert, daher -1 für die Einrückung
  const caretPos = Math.max(msg.linePos - 1, 0);
  const marker = ' '.repeat(caretPos) + '^'.repeat(Math.max(msg.length, 1));
  return `${msg.lineNum}:${msg.linePos} ${msg.type}: ${msg.message}\n${line}\n${marker}`;
};

const info = await module.getCompilationInfo();
info.messages.forEach((m) => console.warn(formatMessage(code, m)));
3:36 error: expected ';' for return statement return vec4f(0.0, 0.0, 0.0, 1.0) ^

Markierungen für einen Code-Editor erzeugen

const toEditorMarkers = (messages) =>
  messages
    .filter((m) => m.lineNum > 0)
    .map((m) => ({
      severity: m.type, // 'error' | 'warning' | 'info'
      startLineNumber: m.lineNum,
      startColumn: m.linePos,
      endLineNumber: m.lineNum,
      endColumn: m.linePos + Math.max(m.length, 1),
      message: m.message,
    }));

const { messages } = await module.getCompilationInfo();
console.log(toEditorMarkers(messages));
[{ severity: 'error', startLineNumber: 3, startColumn: 36, endLineNumber: 3, endColumn: 37, message: "expected ';' for return statement" }]

// Wichtig · Fallstricke

  • 1-basiert: Für String-Operationen wie slice() oder substring() muss man linePos - 1 verwenden. Ein Wert von 0 bedeutet „keine konkrete Position“ und sollte nicht als Spalte 0 interpretiert werden.
  • UTF-16-Codeeinheiten: Stehen Zeichen außerhalb der BMP (z. B. Emojis in Kommentaren) vor der Fehlerstelle, zählen diese doppelt. Das passt zu JavaScript-Strings, aber nicht zur Anzahl sichtbarer Zeichen oder zu UTF-8-Byte-Offsets.
  • Die Eigenschaft ist schreibgeschützt; Zuweisungen werden ignoriert (im Strict Mode TypeError).
  • Inhalt und genaue Position der Meldungen hängen von der Implementierung ab (Chrome nutzt Tint, Firefox Naga) – nicht auf exakte Werte in Tests verlassen.
  • WebGPU ist nur in sicheren Kontexten (HTTPS) verfügbar und noch nicht auf allen Plattformen aktiviert; vorher per if (!navigator.gpu) prüfen.