tag: Wasm-Definition
Die tag-Definition deklariert einen Ausnahmetyp, der im Modul ausgelöst werden kann.
Probieren Sie es aus
(module
;; Declare an exception tag $my_error with two i32 parameters
(tag $my_error (param i32) (param i32))
;; Import console.log
(import "env" "log" (func $log (param i32)))
;; Define $try_and_catch function that tries running the $might_throw function
;; and catches the $my_error exception if thrown, returning the exception's
;; arguments from the block
(func $try_and_catch (param $value i32)
(block $handler (result i32) (result i32)
(try_table (catch $my_error $handler)
(call $might_throw (local.get $value))
)
(return)
)
;; Log the exception's arguments
call $log
call $log
)
(func $might_throw (param $value i32)
;; If value is negative, throw an exception
(local.get $value)
(i32.const 0)
(i32.lt_s)
(if
(then
;; Push the error code onto the stack, then throw
(i32.const 0) ;; error code
(i32.const 42) ;; error payload
(throw $my_error) ;; throw $my_error exception
)
)
)
;; Export $try_and_catch function
(export "try_and_catch" (func $try_and_catch))
)
// Import object containing console.log
const env = {
log: console.log,
};
WebAssembly.instantiateStreaming(fetch("{%wasm-url%}"), { env }).then(
(result) => {
// Negative value causes function to throw
result.instance.exports.try_and_catch(-1);
},
);
Syntax
tag identifier parameters
tag-
Der
tag-Definitionstyp. Muss immer zuerst angegeben werden. identifierOptional-
Ein identifizierender Name für den Tag. Dieser muss mit einem
$-Symbol beginnen, beispielsweise$my_error. parameters-
Ein oder mehrere Werte, die die Parameter des Ausnahmetyps und deren Typen spezifizieren. Jeder besteht aus:
- Dem Schlüsselwort
param - Dem Typ des Parameters. Dies kann jeder Wasm-Typ sein.
- Dem Schlüsselwort
Beschreibung
Die WebAssembly-tag-Definition ermöglicht es, Ausnahmetypen für das Modul zu definieren. Jeder besteht aus einem optionalen identifizierenden Namen, dem ein $-Symbol vorangestellt ist, gefolgt von einer oder mehreren Parameterdefinitionen. Zum Beispiel:
(tag $my_error (param i32))
Später im Modul können Sie auf den Ausnahmetyp durch seinen identifizierenden Namen, in diesem Fall $my_error, verweisen.
Hinweis:
Falls kein identifier angegeben wird, kann der Tag durch seine Tag-Indexnummer identifiziert werden — 0 für den zuerst angegebenen Tag, 1 für den zweiten usw.
Zum Beispiel, die folgende Funktion nimmt einen i32-Parameter und überprüft, ob er kleiner als 0 ist, mittels der [lt_s]-Anweisung(/de/docs/WebAssembly/Reference/Numeric/lt_s). Falls dies der Fall ist, werfen wir eine Ausnahme des Typs $my_error und übergeben einen Wert von 42, welcher einen Fehlercode oder eine Nutzlast darstellen könnte.
(func $might_throw (param $value i32)
(local.get $value)
(i32.const 0)
(i32.lt_s)
(if
(then
(i32.const 42)
(throw $my_error)
)
)
)
Die ausgelöste Ausnahme könnte dann behandelt werden, und die Nutzlast könnte unter Verwendung eines Wasm-try/catch-Blocks abgerufen werden. Sie können ein Beispiel im Abschnitt Probieren Sie es aus oben auf der Seite sehen; siehe auch die folgenden Seiten für weitere Beispiele:
Behandeln von Wasm-Ausnahmen in JavaScript
Alternativ, wenn die Funktion, die die Ausnahme auslöst, exportiert wird, kann die Ausnahme über eine reguläre JavaScript-try...catch-Anweisung behandelt werden.
Zum Beispiel könnten wir die $might_throw-Funktion wie folgt exportieren:
(export "might_throw" (func $might_throw))
Um auf die Nutzlast der Ausnahme zuzugreifen, müssen Sie auch den Tag exportieren:
(export "my_error" (tag $my_error))
Zurück in JavaScript können wir das Modul instanziieren und dann die exportierte Funktion (über das exports-Objekt) mit einem numerischen Argument, das kleiner als 0 ist, aufrufen, um die $my_error-Ausnahme auszulösen. Wir können auch auf den exportierten Tag über das exports-Objekt zugreifen.
Dann können wir innerhalb des catch-Blocks auf die Nutzlast der Ausnahme mithilfe der [Exception.getArg()]-Methode(/de/docs/WebAssembly/Reference/JavaScript_interface/Exception/getArg) zugreifen.
let myErrorTag;
WebAssembly.instantiateStreaming(fetch("module.wasm")).then((result) => {
myErrorTag = result.instance.exports.my_error;
try {
result.instance.exports.might_throw(-1); // negative value causes function to throw
} catch (e) {
if (e instanceof WebAssembly.Exception && e.is(myErrorTag)) {
console.log("Error code:", e.getArg(myErrorTag, 0));
} else {
throw e; // throw other errors
}
}
});
Sie können dies in Aktion zusammen mit einer vollständigen Erklärung in unserem vollständigen Beispiel zur Behandlung von JavaScript-Ausnahmen später sehen.
Erstellen von Tags in JavaScript
Es ist auch möglich, einen Wasm-Tag innerhalb des JavaScript-Hosts zu erstellen, indem Sie den [WebAssembly.Tag()]-Konstruktor(/de/docs/WebAssembly/Reference/JavaScript_interface/Tag/Tag) verwenden:
Zum Beispiel:
const myErrorTag = new WebAssembly.Tag({ parameters: ["i32"] });
Sie können es in das Modul importieren:
const env = {
my_error: myErrorTag,
};
WebAssembly.instantiateStreaming(fetch("module.wasm"), { env });
Dann verweisen Sie innerhalb des Wasm-Moduls darauf:
(module
(tag $my_error (import "env" "my_error") (param i32))
...
)
Beispiele
>Vollständiges Beispiel zur Behandlung von JavaScript-Ausnahmen
In diesem Beispiel zeigen wir, wie man eine in einem Wasm-Modul definierte und geworfene Ausnahme vom zugehörigen JavaScript-Host behandelt.
Wasm
In unserem Wasm-Modul beginnen wir, indem wir einen Ausnahmetag namens $my_error mit einem einzelnen i32-Parameter definieren, dann exportieren wir ihn. Dann definieren wir eine Funktion namens $might_throw, die einen einzelnen i32-Parameter entgegennimmt, überprüft, ob er kleiner als 0 ist, und die $my_error-Ausnahme mit einer Nutzlast von 42 wirft, wenn dies der Fall ist. Schließlich exportieren wir die Funktion $might_throw.
(module
(tag $my_error (param i32))
(export "my_error" (tag $my_error))
(func $might_throw (param $value i32)
(local.get $value)
(i32.const 0)
(i32.lt_s)
(if
(then
(i32.const 42)
(throw $my_error)
)
)
)
(export "might_throw" (func $might_throw))
)
JavaScript
Wir beginnen unser Skript mit der Definition einer Variablen namens myErrorTag, greifen auf eine Ausgabe-<p>-Element zu, in das Ergebnisse ausgegeben werden sollen, und instanziieren unser Wasm-Modul mithilfe von WebAssembly.instantiateStreaming().
let myErrorTag;
const output = document.querySelector("p");
const wasm = WebAssembly.instantiateStreaming(fetch("{%wasm-url%}"));
Wenn das instantiateStreaming()-Versprechen aufgelöst wird, setzen wir die Variable myErrorTag auf den exportierten my_error-Tag und versuchen dann, die exportierte might_throw()-Funktion innerhalb eines try-Blocks mit einem negativen numerischen Argument auszuführen, um sie auslösen zu lassen.
Innerhalb des entsprechenden catch-Blocks wird die ausgelöste Wasm-Ausnahme im error-Objekt verfügbar sein, das eine Instanz von WebAssembly.Exception ist. Wir überprüfen, ob dies zutrifft mit error instanceof WebAssembly.Exception, und ob das error-Objekt eine Ausnahme des exportierten myErrorTag-Typs darstellt (mithilfe der [is()]-Methode(/de/docs/WebAssembly/Reference/JavaScript_interface/Exception/is)).
Wenn beide Bedingungen zutreffen, greifen wir mithilfe der [getArg()]-Methode(/de/docs/WebAssembly/Reference/JavaScript_interface/Exception/getArg) auf die Nutzlast der Wasm-Ausnahme zu und schreiben sie in das Ausgabe-<p>. Falls nicht, schreiben wir das Fehlerobjekt in das Ausgabe-<p>.
wasm.then((result) => {
myErrorTag = result.instance.exports.my_error;
try {
result.instance.exports.might_throw(-1);
} catch (error) {
if (error instanceof WebAssembly.Exception && error.is(myErrorTag)) {
output.textContent = `Error code: ${error.getArg(myErrorTag, 0)}`;
} else {
output.textContent = `Error: ${error}`; // report other errors
}
}
});
Ergebnis
Spezifikationen
Diese Funktion scheint in keiner Spezifikation definiert zu sein.>Browser-Kompatibilität
Siehe auch
throw-Anweisungthrow_ref-Anweisungtry_table-Anweisungcatch-Klauselcatch_all-Klauselcatch_ref-Klauselcatch_all_ref-Klausel
exnref-TypWebAssembly.Exception-JavaScript-SchnittstelleWebAssembly.Tag-JavaScript-Schnittstelle