Design: Diskussion: WebAssembly, Unicode und die Webplattform

Erstellt am 22. Mai 2021  ·  19Kommentare  ·  Quelle: WebAssembly/design

Diese Ausgabe dient der begleitenden Diskussion über "WebAssembly, Unicode und die Webplattform". Die Präsentation ist vorab aufgezeichnet, was wir beschlossen haben, es in https://github.com/WebAssembly/meetings/pull/775 auszuprobieren, wobei die Diskussionszeit für das CG-Videomeeting am 22. Juni geplant ist.


(anklicken um abzuspielen)

Bitte beachten Sie, dass ich einige Konzepte erwähne, von denen ich erwarten würde, dass sie den CG-Mitgliedern bekannt sind, aber ich habe mich entschieden, sie dennoch aufzunehmen, um die Präsentation auch für diejenigen zugänglich zu machen, die mit dem Thema nicht vertraut sind. Rückmeldung willkommen!

Verwandte Themen:

Hilfreichster Kommentar

Eine einfache Lösung wäre, dass Sprachen/APIs, die ungültige Unicode-Strings akzeptieren oder produzieren, (list u8) oder (list u16) (möglicherweise mit einem netten Alias ​​wie byte_string , um die Absicht zu kommunizieren) anstatt der IT-Typ string , der IIRC ein Alias ​​für (list char) .

Dies ist derzeit auch meine bevorzugte Lösung - ein wtf16string Typ wäre ein Alias ​​für (list u16) genauso wie string derzeit als Alias ​​für (list char) . Der Wert des Alias, IIUC, besteht darin, dass das Ergebnis einer Funktion, die (list u16) zurückgibt, die von (zB) JS aufgerufen wird, als eine JS-Liste (von Zahlen) erscheinen würde, während das Ergebnis einer Funktion, die wtf16string zurückgibt,

Das Hinzufügen eines zusätzlichen Alias wtf16string zum kanonischen ABI-Entwurf scheint relativ unaufdringlich zu sein.

Alle 19 Kommentare

Vielleicht ein paar mögliche Lösungen, die ich bisher aus Offline-Feedback gesammelt habe, zur Überlegung:

Separate WTF-16

Definieren Sie in Schnittstellentypen:

string   := list char
string16 := list u16

Definieren Sie einen beim Verknüpfen angewendeten Zwang mit den folgenden Fällen:

| Von | Nach | Erwartung
|------------|------------|-------------
| string | string16 | Umcodieren von UTF-8 in UTF-16
| string16 | string | Neucodierung von WTF-16 auf UTF-8 (Ersatzoption)

Der Zwang stellt sicher, dass ein string16 Modul auf einem WASI-Host funktioniert bzw. dass ein string und ein string16 Modul miteinander kommunizieren können, auch wenn beide ein string und ein string16 Modul oder Host rufen denselben string oder string16 Export auf, der sonst mehrdeutig wäre.

Dies führt auch zu einer Mehrdeutigkeit in der Web-Einbettung, da die Übergabe eines list u16 an JS zu einem Uint16Array oder einem DOMString . Ein JS-weiter Zwang von Uint16Array auf DOMString scheint unerwünscht, aber der JS-Typ könnte durch explizite Verwendung des Alias string16 (mit seiner eigenen Binär-ID string16 :> list u16 ist, wo erforderlich, rein semantisch) anstelle von list u16 in einem Adaptermodul. Daher der Deckname. In diesem Fall würde aus string16 ein DOMString und aus list u16 ein Uint16Array .

Ich hänge nicht besonders an dem Namen string16 und würde mit jedem anderen Namen oder jeder Alternative, die keinen Namen / keine ID erfordert, um die Mehrdeutigkeit zu lösen, in Ordnung sein.

Eine Optimierung ähnlich list.is_canon ist hier nicht notwendig, da list.count verwendet werden kann. Außerdem kann die Tür zu UTF-beliebig und einer möglichen Latin1-Optimierung (siehe unten) offen gehalten werden, indem Platz für eine zukünftige sofortige in list.*_canon Adapteranweisungen reserviert wird.

UTF-beliebig

Definieren Sie in Schnittstellentypen:

list.lift_canon $unit [...]
list.is_canon $unit [...]
list.lower_canon $unit [...]

where the $unit immediate is
  0: 8-bit (UTF-8, ASCII-compatible)
  1: 16-bit (UTF-16)
  2: 32-bit (UTF-32)
  3: 8-bit (Latin1, narrow UTF-16)

Diese potenzielle Lösung kann in Betracht gezogen werden, wenn Wohlgeformtheit erforderlich ist. Es würde einen doppelten Neucodierungsaufwand und indirekte Auswirkungen auf die Codegröße vermeiden, lässt jedoch das Ersatzproblem unberücksichtigt. Beachten Sie, dass $unit 1-3 möglicherweise nach dem MVP als weitere Optimierungen hinzugefügt werden oder wir sofort mit einigen davon beginnen.

WTF-beliebig

Definieren Sie in Schnittstellentypen:

list.lift_canon $unit [...]
list.is_canon $unit [...]
list.lower_canon $unit [...]

where the $unit immediate is
  0: 8-bit (WTF-8, ASCII-compatible)
  1: 16-bit (WTF-16)
  2: 32-bit (Code points except surrogate pairs)
  3: 8-bit (Latin1, narrow WTF-16)

Diese mögliche Lösung würde auch erfordern eine Neudefinition char von Unicode Scalar Werte in Unicode - Codepunkte, während Einschränkung Listen von char nicht Surrogatpaare enthalten (aber erlaubt isoliert Surrogate), die möglicherweise bei der Aufhebung erzwungen. Auch hier sind konkrete $unit s in einem MVP fraglich.

Dieser führt nicht allein zu Verlusten, sodass alles andere tatsächlich nur eine Post-MVP-Optimierung wird.

Integrierte W/UTF-any

Definieren Sie in Schnittstellentypen:

  • Heben Sie die "Liste der Unicode-Codepunkte, die Ersatzpaare ändern" auf, aber senken Sie die "Liste der Unicode-Skalarwerte". Dies ist eine nicht-funktionale Design-only-Änderung, wenn sie nur während des 16-Bit-Lifts angewendet wird.
  • Fügen Sie beim Absenken eine optionale Option passthrough , um eine "Liste der Unicode-Codepunkte" zu erhalten. Dies ist eine funktionale Ergänzung, die verlustfreies Passthrough ermöglicht.

Damit erreichen wir:

IIUC, das Grundproblem besteht darin, dass die IT möchte, dass Strings Sequenzen von Unicode-Codepunkten sind, aber einige Sprachen betrachten Strings als Sequenzen von i8- oder i16-Werten, die wohlgeformten Unicode-Strings entsprechen können oder nicht. Eine einfache Lösung wäre, dass Sprachen/APIs, die ungültige Unicode-Strings akzeptieren oder produzieren, (list u8) oder (list u16) (möglicherweise mit einem netten Alias ​​wie byte_string , um die Absicht zu kommunizieren) anstatt der IT-Typ string , der IIRC ein Alias ​​für (list char) . Wurden die Kompromisse, dies zu tun, schon irgendwo diskutiert?

Ich denke, das Problem ist etwas nuancierter, da die IT char als "Unicode-Skalarwerte" definieren möchte, die eine Lücke haben, wo die Surrogat-Codepunkte wären, und als solche können keine isolierten Surrogate darstellen . WTF hingegen ist "Unicode Code Points" ohne diese Einschränkung, aber Sequenzen, die darauf beschränkt sind, keine Surrogat-Codepunktpaare zu enthalten (diese würden durch zusätzliche Codepunkte > U+FFFF ersetzt, während isolierte Surrogate OK sind). Meinten Sie das?

Abgesehen davon denke ich, dass C-ähnliche Byte-Strings ab const char* , die alles sein können, noch nicht diskutiert wurden. Vielleicht habe ich es aber übersehen.

Eine einfache Lösung wäre, dass Sprachen/APIs, die ungültige Unicode-Strings akzeptieren oder produzieren, (list u8) oder (list u16) (möglicherweise mit einem netten Alias ​​wie byte_string , um die Absicht zu kommunizieren) anstatt der IT-Typ string , der IIRC ein Alias ​​für (list char) .

Dies ist derzeit auch meine bevorzugte Lösung - ein wtf16string Typ wäre ein Alias ​​für (list u16) genauso wie string derzeit als Alias ​​für (list char) . Der Wert des Alias, IIUC, besteht darin, dass das Ergebnis einer Funktion, die (list u16) zurückgibt, die von (zB) JS aufgerufen wird, als eine JS-Liste (von Zahlen) erscheinen würde, während das Ergebnis einer Funktion, die wtf16string zurückgibt,

Das Hinzufügen eines zusätzlichen Alias wtf16string zum kanonischen ABI-Entwurf scheint relativ unaufdringlich zu sein.

WTF hingegen ist "Unicode Code Points" ohne diese Einschränkung, aber Sequenzen, die darauf beschränkt sind, keine Surrogat-Codepunktpaare zu enthalten (diese würden durch zusätzliche Codepunkte > U+FFFF ersetzt, während isolierte Surrogate OK sind).

Ah, bedeutet das, dass WTF-8 nicht dasselbe wie ein einfaches (list u16) weil es diese Einschränkung beim Hinzufügen hat? Ich hatte diese Nuance nicht geschätzt. Meine Intuition ist, dass es übertrieben wäre, sowohl einen string Typ zu haben, der Sequenzen wohlgeformter Unicode-Skalarwerte repräsentiert, als auch einen wtf16string Typ, der fast ein (list u16) Typ ist, aber hat zusätzliche Einschränkungen. Würde die Verwendung eines Alias ​​für ein uneingeschränktes (list u16) gut genug für Systeme funktionieren, die keine Unicode-Wohlformung erzwingen? Dieser Hinweis in der WTF-8-Spezifikation legt nahe, dass dies der Fall wäre.

Ah, bedeutet das, dass WTF-8 nicht mit einer Ebene (Liste u16) identisch ist, weil es diese Einschränkung beim Hinzufügen hat?

Darin heißt es: "Wie UTF-8 künstlich auf Unicode-Text beschränkt ist, um UTF-16 zu entsprechen, wird WTF-8 künstlich eingeschränkt, um Ersatz-Codepunktpaare auszuschließen, um potenziell falsch formatierten UTF-16 zu entsprechen." Iiuc behandelt es diese ähnlich wie UTF-8 überlange oder abgeschnittene Byte-Sequenzen behandelt. WTF-8 kann jedes (list u16) , aber nicht jedes (list u8) ist gültiges WTF-8.

Würde die Verwendung eines Alias ​​für ein uneingeschränktes (Liste u16) gut genug für Systeme funktionieren, die die Wohlgeformtheit von Unicode nicht erzwingen?

WTF-16 ordnet 1:1 zufälligen u16 Werten zu und es hängt nur davon ab, wie diese Werte interpretiert werden, also würde (list u16) funktionieren.

IIUC, WTF-8 ist nicht ganz dasselbe wie willkürlich list u8 . Zum Beispiel verbietet es "Ersatzpaar-Byte-Sequenzen" (siehe hier ).

WTF-16 _ist_ jedoch dasselbe wie list u16 . Es ist ein wenig seltsam, dass sie ein Namensthema teilen.

EDIT: sollte aktualisiert haben :)

Ich habe eine erste Frage/Antwort gepostet, die sich nur auf die Frage nach Surrogaten in interface-types/#135 konzentriert . Ich denke, das ist das höherwertige Bit, und wenn wir uns darauf einigen können, wird eine anschließende Diskussion über die Unterstützung eines oder mehrerer Kodierungsformate einfacher sein.

Danke, Lukas.

Wenn Sie bereit wären, "Separate WTF-16" wie oben beschrieben zu unterstützen (der Zwang ist entscheidend, um den Zugriff auf WASI-APIs zu ermöglichen und mit JavaScript ohne Glue-Code zu kommunizieren), würde ich mich mit den vorgeschlagenen char wohl fühlen Wertebereich. WTF-16-Sprachen hätten dann die Notluke, die sie für die Integration benötigen, so wie es mit Modulen in derselben Sprache, JavaScript und durch Ersetzen durch UTF-*-Sprachen möglich ist. Ich würde mich übrigens auch viel besser bei WASI fühlen, da der Hauptschmerzpunkt, der durch die Nichtübereinstimmung von String-Codierungen verursacht wird, mit dem Zwang gelöst würde.

Einen separaten string16 -Typ zu haben, wie Sie es mit Ersatzzeichen vorschlagen, würde immer noch alle Probleme mit Ersatzzeichen haben, die in interface-types/#135 beschrieben sind , also denke ich, dass es nicht besser wäre, zwei Zeichenfolgentypen zu haben vs .eins (besonders wenn sie implizit interkonvertierbar sind; dann sind sie keine sinnvoll getrennten Typen). Zwei String-Typen würden die Dinge auch konkret verschlimmern, da sie jedem Interface-Designer und Verbraucher eine mentale Belastung aufbürden ("Warum gibt es zwei Typen? Was ist der Unterschied? Wann sollte ich den einen oder den anderen verwenden?"). Schließlich würde das Hinzufügen von Unterstützung für WTF-16 im Allgemeinen gegen die Leitlinien zur Weiterentwicklung zukünftiger Standards Web/IETF verstoßen, die auch in interface-types/#135 erwähnt werden . Daher denke ich, dass wir nicht erwägen sollten, Ersatztypen hinzuzufügen, es sei denn, wir haben konkrete Beweise dafür, dass Schnittstellentypen ohne sie nicht lebensfähig sind.

Für Web-exklusive Anwendungsfälle halte ich es für sinnvoll, das Problem in den JS- oder Web-APIs zu lösen. Man kann sich zB leicht JS-APIs zum "binden" von Wasm-Importen und -Exporten vorstellen. Dies ist bereits ein Ansatz in anderen aufkommenden JS-APIs, wie zum Beispiel Stack-Switching, und ich habe mich gefragt, ob wir allgemeine "bind import" / "bind export" JS-APIs sind, die das Web verarbeiten können -spezifische Fälle von Promises, JS-Strings und typisierten Array-Ansichten.

Wenn Sie einen separaten string16-Typ haben, wie Sie es mit Ersatzzeichen vorschlagen, würden immer noch alle Probleme mit Ersatzzeichen auftreten, die in interface-types/135 . beschrieben sind

Technisch richtig, aber es wird auch übersehen, dass Strings zumindest immer zwischen separat kompilierten Modulen in derselben Sprache, jeder kompatiblen Sprache und JavaScript funktionieren würden, sogar ohne Vorkenntnisse, mit welcher Art von Modul man verbunden ist. Das ist in der Regel die Mehrzahl der Fälle, denke ich. Dies scheint mir ein vernünftiger Kompromiss zu sein, auch weil es ermöglicht, den gewünschten char Wertebereich wohlgeformten (USV) Strings zuzuweisen.

Zwei String-Typen würden die Dinge auch konkret verschlimmern, indem sie jedem Interface-Designer und Verbraucher eine mentale Belastung aufbürden ("Warum gibt es zwei Typen? Was ist der Unterschied? Wann sollte ich den einen oder den anderen verwenden?")

Die Alternative des gelegentlichen Bruchs scheint mir viel schlimmer zu sein, wenn es also nötig ist, denke ich, dass die meisten Leute damit zurechtkommen. Vielleicht reicht ein guter Name für den zweiten Zeichenfolgentyp ( domstring ?) aus, um dieses kleinere Problem zu mildern.

Schließlich würde das Hinzufügen von Unterstützung für WTF-16 im Allgemeinen gegen die Leitlinien zur Weiterentwicklung zukünftiger Standards Web/IETF . verstoßen

Leider ist es mir in Ermangelung einer Fluchtluke für betroffene Sprachen egal, wie stichhaltig die Argumentation eines vermeintlichen Trends ist, da der IT-MVP irgendjemandem irgendwo etwas kaputtmachen wird und weitgehend nutzlos ist der JavaScript-ähnlichen Sprache, an der ich arbeite, kann ich nur widersprechen.

Daher versuche ich, eine vernünftige Lösung oder einen Kompromiss zu finden, mit dem jeder leben kann, und es würde mich freuen, wenn wir zusammenarbeiten könnten.

Ich verstehe nicht, wie das, was Sie sagen, die in interface-types/#135 aufgeworfenen Probleme anspricht oder Gegenbeweise liefert, dass die IT im Allgemeinen ohne die Aufnahme eines neuen domstring Typs nicht lebensfähig wäre. Die vorhandene JS-API bietet bereits eine Allzweck-Escape-Schraffur zum Ausführen beliebiger Wertkonvertierungen an Grenzen, daher sehe ich nicht, wie zu diesem frühen Zeitpunkt eine zweite Escape-Schraffur benötigt wird. Ich denke, wir brauchen einfach mehr erfahrungsbasierte Beweise, um der starken Anleitung entgegenzuwirken, die wir gegen die weitere Verbreitung von Strings mit Surrogaten erhalten haben.

(FWIW, Wenn wir uns auf das Fehlen von Surrogate einigen können, wäre es meiner Meinung nach sinnvoll, über die Unterstützung von U TF-16 als zusätzliche Codierung im kanonischen ABI von string zu sprechen. Aber das ist ein ganz anderes Thema mit ein paar Optionen, also möchte ich das nicht mit der abstrakten String-Semantik verwechseln, die zuerst verstanden werden muss.)

Ich schätze Ihren zweiten Absatz, da er bereits einige sehr lästige Probleme lösen würde. Ich stimme zu, dass die Unterstützung von UTF-16 separat nützlich ist, und würde es begrüßen, wenn es dem Explainer / MVP hinzugefügt wird. Ich bin dabei!

Es fällt mir jedoch schwer, Ihren Argumenten im ersten Absatz zu folgen. Vielleicht, wenn Sie mir nicht glauben, hier ist Linus Torvalds, der eine sehr wichtige Regel erklärt, die meiner Meinung nach über den Linux-Kernel hinausgeht: Don't break userspace . Und hier ist er im selben Vortrag, der die Programmiererweisheit von Wenn es ein Fehler ist, auf den sich die Leute verlassen , aufrecht erhält

Es ist wirklich traurig, wenn die Kernbibliothek des gesamten Systems damit einverstanden ist, Dinge zu zerstören, solange sich die Dinge "verbessern" und sie das ABI "reparieren".

Und sich keine Sorgen um Surrogate machen zu müssen, ist in der Tat eine Art Feature, da Benutzer hier oder da ein unvorsichtiges substring(0, 1) ausführen und damit eine importierte Funktion aufrufen können, oder split("") , weitergeben und join() erneut, oder erstellen Sie ein StringBuilder als Modul, das nicht gelegentlich doppelte Ersetzungszeichen wie von Zauberhand hervorbringt. Ich meine, es gibt einen Grund, warum sich eine Reihe sehr beliebter Sprachen gegen die Durchsetzung von Wohlgeformtheit entschieden haben, und wenn Wasm diese Sprachen und ihre Benutzer gut unterstützen möchte, dann wird es umso mehr Grenzen geben, je modularer Wasm wird Es wird schwieriger zu sagen, in welchem ​​Modul eine Funktion steckt, und desto offensichtlicher wird das Problem.

Ich weiß wirklich nicht, wie viele Beweise ich noch brauche, um zu beweisen, dass es eine schlechte Idee ist, etwas so zu gestalten, dass die aktuelle Realität ignoriert wird. Tatsächlich scheint dies nur bei Schnittstellentypen in Ordnung zu sein, während wir alle anderen Vorschläge auf sehr hohen Standards halten. Und obwohl ich kein Experte dafür bin, denke ich, dass der Unicode-Standard selbst genau den gleichen Fehler in Bezug auf die Bedürfnisse von UCS-2-Sprachen gemacht hat, indem er auf USVs bestand, was zu etwa einem Jahrzehnt ähnlicher Verzweiflung führte Diskussionen (kann den gesamten Thread empfehlen, vor allem aber den letzten Kommentar, bevor er verstummt wurde), der 2014 in der Beschreibung der häufig angewandten praktischen Lösung, der WTF-8-Kodierung, gipfelte.

Beachten Sie, dass das Ausgeben eines Ersatzzeichens beim Auftreten von Zeichencodierungsfehlern in Bitstreams eine bekannte Form gefährlicher stiller Datenkorruption ist und Systeme, die Integrität erfordern, dies verbieten.

Wenn codePointAt eine Ausnahme auslöst, wenn ein einzelner Ersatz gefunden wird, kann es sehr gut sein, dass ein Fehler auftritt, der Ihre gesamte Anwendung unterbricht, weil jemand versehentlich ein Emoji-Zeichen an der falschen Position in einer Zeichenfolge in einer Datenbank platziert hat

Leider macht es ecmascript sehr schwierig sicherzustellen, dass Sie keine Strings mit ungepaarten Surrogat-Codepunkten irgendwo darin generieren. Es ist so einfach, die ersten 157 Längeneinheiten eines Strings zu nehmen und vielleicht "..." anzuhängen, um ihn abzukürzen. Und es ist ein sonderbarer Unfall, wenn das in der Praxis tatsächlich passiert, weil Nicht-BMP-Charaktere selten sind. Wir sollten sehr zurückhaltend sein, Gefahren einzuführen, in der Hoffnung, unsere Unicode-Hygiene zu verbessern.

Der Grund dafür, dass JS, Java und C# die Strings haben, die sie verwenden, ist, dass, als Unicode erkannte, dass 2 Bytes nicht ausreichen und UCS-2 nicht praktikabel war, bereits eine Menge Code geschrieben war, also diese Sprachen einfach nicht habe keine Wahl. Ebenso für Linux-Systemaufrufe, die dem Userspace ausgesetzt sind. Im Gegensatz dazu existiert heute kein Code, der in der IT definierte APIs verwendet, daher haben wir nicht die gleichen Abwärtskompatibilitätsanforderungen. Aus vielen Gründen versuchen wasm und Interface Types absichtlich nicht , eine existierende einzelne Sprache oder Systemaufruf-ABI perfekt zu emulieren. Es mag ein gültiges Ziel sein, aber das wäre ein separates Projekt/Standard/Schicht als das Komponentenmodell. Das ist der Vorteil von Layering und Scoping: Wir brauchen nicht eine Sache, die alle möglichen Ziele erreicht.

Ich möchte noch einmal betonen, dass Strings natürlich innerhalb einer Komponente in jeder für die Sprache angemessenen Weise dargestellt werden können, also sprechen wir wirklich nur über die Semantik von APIs . Was die bereits definierten Web-APIs betrifft:

  1. wir haben viele Gründe zu der Annahme, dass es nicht notwendig (und oft auch nicht sinnvoll) ist, Leihmuttern zu übergeben
  2. es gibt immer die Möglichkeit, benutzerdefinierte JS-API-Bindungen zu verwenden (es ist nicht erforderlich, dass 100 % der Web-APIs über eine JS-kleberlose Bindung an Web-APIs verfügen).

Daher glaube ich immer noch nicht, dass wir Beweise dafür haben, dass IT ohne die Fortführung dieser WTF-16-String-Semantik nicht lebensfähig sein wird, was meiner Meinung nach die richtige Frage für einen MVP ist.

Ein paar Punkte, denen ich nicht zustimme:

Ich verstehe nicht, wie das, was Sie sagen, die in interface-types/#135 aufgeworfenen Probleme anspricht

Dies ist jetzt ein separates Thema, und in der Post zuvor sprach ich über einen meiner Meinung nach vernünftigen Kompromiss zur Lösung von Verlusten. Insbesondere würde ich mit Ihrer Argumentation in der separaten Ausgabe einverstanden sein, aber nur, wenn ein verlustfreier Fallback verfügbar ist. Das ist meiner Meinung nach kein Entweder/Oder. Wenn nicht, bleibe ich der Meinung, dass WTF-8/16 die umfassendere, weniger eingeschränkte Wahl ist und als solche vorzuziehen ist, auch weil eines der übergeordneten Ziele von Wasm darin besteht, sich nahtlos in die Web-Plattform zu integrieren bzw -Kompatibilität des Webs, und das gilt auch für Schnittstellentypen.

Die vorhandene JS-API bietet bereits eine Allzweck-Escape-Schraffur zum Ausführen beliebiger Wertkonvertierungen an Grenzen, daher sehe ich nicht, wie zu diesem frühen Zeitpunkt eine zweite Escape-Schraffur benötigt wird.

es gibt immer die Möglichkeit, benutzerdefinierte JS-API-Bindungen zu verwenden

Dies ist in unserem Fall leider nicht ausreichend, wo wir derzeit Glue-Code haben wie:

const STRING_SMALLSIZE = 192; // break-even point in V8
const STRING_CHUNKSIZE = 1024; // mitigate stack overflow
const utf16 = new TextDecoder("utf-16le", { fatal: true }); // != wtf16

/** Gets a string from memory. */
function getStringImpl(buffer, ptr) {
  let len = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2] >>> 1;
  const wtf16 = new Uint16Array(buffer, ptr, len);
  if (len <= STRING_SMALLSIZE) return String.fromCharCode(...wtf16);
  try {
    return utf16.decode(wtf16);
  } catch {
    let str = "", off = 0;
    while (len - off > STRING_CHUNKSIZE) {
      str += String.fromCharCode(...wtf16.subarray(off, off += STRING_CHUNKSIZE));
    }
    return str + String.fromCharCode(...wtf16.subarray(off));
  }
}

Da uns Chrome und Node.js sehr am Herzen liegen, haben wir festgestellt, dass TextDecoder V8 für UTF-16LE viel langsamer ist als in anderen Engines (SMs sind sehr schnell), also ist String.fromCharCode tatsächlich schneller in V8 bis zu einem bestimmten Break-Even-Punkt. Also haben wir uns entschieden, vorerst darum herum zu optimieren. Als nächstes gibt es kein TextDecoder für WTF-16 (was separat ärgerlich ist), also versuchen wir zuerst, wohlgeformtes UTF-16 zu decodieren, und wenn das fehlschlägt, lassen wir es werfen und fallen zurück auf das Chunking-Through das viel langsamere String.fromCharCode . Das Chunking ist notwendig, weil man String.fromCharCode nicht einfach auf einen langen String anwenden kann, da dies wahrscheinlich den Stack überlaufen lässt.

Auf der anderen Seite würde Rust zum Beispiel das nicht brauchen, was einer der Gründe ist, warum ich denke, dass die IT derzeit nicht so neutral ist, wie sie sein sollte. Im Allgemeinen denke ich, dass der Sinn von IT string s tatsächlich darin besteht, gut mit JS kommunizieren zu können, was immer noch unser primäres Interop-Ziel ist.

Es gibt heute keinen Code, der in der IT definierte APIs verwendet, daher haben wir nicht die gleichen Abwärtskompatibilitätsanforderungen

Die erste Hälfte ist technisch richtig, da es noch keine IT gibt, aber unsere Anforderungen an IIUC beinhalten die Verbesserung bestehender Anwendungsfälle, wie zum Beispiel die Berücksichtigung des ungeschickten Stücks von Klebecode oben. Idealerweise für so viele Sprachen wie möglich, damit Post-MVP tatsächlich "nur eine Optimierung" wird, wie Sie in Ihrer Präsentation gesagt haben. Im Gegenteil, im Moment beginnt die IT im Grunde mit einer Optimierung für Sprachen, die einen UTF-8-Encoder/Decoder verwenden kann, was meiner Meinung nach nicht neutral ist.

wasm- und Interface-Typen versuchen absichtlich nicht, eine vorhandene einzelne Sprache oder syscall ABI . perfekt zu emulieren

Ich habe das gelesen, als ob ich dieser Meinung wäre, was ich absolut nicht bin. Ich bin bereit, Ihnen hier den Vorteil des Zweifels zu geben, möchte jedoch hinzufügen, dass die IT meiner Meinung nach derzeit unnötig eingeschränkt ist und als solche nur eine ganz bestimmte Reihe von Sprachen gut bedient. Im Gegenteil, WTF-8/16 ist die umfassendere Codierung, die ich als logische Standardeinstellung erwartet hätte, auch weil sie auf JS-Strings umläuft. Wir sind hier anderer Meinung, aber nur in Ermangelung einer richtigen Fluchtluke. Wenn es eine brauchbare verlustfreie Alternative geben würde, damit niemand kaputt oder unnötig benachteiligt wird, würde ich mit Ihrer Argumentation des Standard-String-Typs einverstanden sein.

wir haben viele Gründe zu der Annahme, dass es nicht notwendig (und oft auch nicht sinnvoll) ist, Leihmuttern zu übergeben

Wir sind hier anderer Meinung. Insbesondere denke ich, dass meine Präsentation und meine Kommentare begründete Zweifel daran aufkommen lassen, dass sie in einigen Fällen, auch wenn sie selten sind, sehr aussagekräftig sein können (z. B. wenn Integrität erforderlich ist), und ich bin der Meinung, dass " Gefahren in der Hoffnung, unsere Unicode-Hygiene zu verbessern." Das heißt, wenn wir können, sollten wir die kanonische ABI so gestalten, dass sie auch in den folgenden wichtigen Fällen garantiert funktioniert: Java/C#/AS<->JS, Java/C#/AS<-> Java/C#/AS. Ein Austausch auf anderen Pfaden ist wohl unumgänglich, aber zumindest haben dann Sprachen und Benutzer die Wahl bzw. ist in seltenen Fällen die Vorgabe nicht schon kaputt.

Ich glaube immer noch nicht, dass wir Beweise dafür haben, dass IT ohne die Fortführung dieser WTF-16-String-Semantik nicht lebensfähig sein wird

Angesichts begründeter Zweifel und der fehlenden Bereitschaft, einen meiner Meinung nach vernünftigen Kompromiss zu prüfen, würde ich erwarten, dass die Beweislast jetzt bei Ihnen liegt. Auch hier bin ich bereit, Ihnen die Standardzeichenfolge und eine wohlgeformte Zukunft zu überlassen, aber nicht auf Kosten der möglicherweise seltenen, aber immer noch auftretenden Gefahren. Viele gängige Sprachen können davon betroffen sein, und das kann in Zukunft wirklich schwer zu rechtfertigen sein, sobald sie es erkennen.

Ich stimme zu, dass der JS-Glue-Code nicht ideal ist, aber ich denke, die richtige Lösung dafür liegt in der JS-API oder in JS, nicht indem das Konzept von wtf-16-string zum gesamten zukünftigen Komponenten-Ökosystem hinzugefügt wird. Darüber hinaus sehe ich keine neuen Informationen, auf die ich nicht antworten könnte, auf die nicht bereits geantwortet wurde; es scheint, dass wir uns in Fragen der Ziele/Umfang meistens nicht einig sind.

Ich würde erwarten, dass die Anomalie TextDecoder in JS noch schwieriger zu beheben ist, da anscheinend bereits entschieden wurde, dass dies außerhalb des Geltungsbereichs liegt. Und JS kann das irgendwie, weil TextDecoder in JS nicht zwischen zwei Funktionsaufrufen aufgerufen wird, sondern hauptsächlich zum Abrufen von Daten über das Netzwerk oder aus dem Speicher verwendet wird.

Die noch interessanter Anomalie ist jedoch, dass es nicht einmal einen ist TextEncoder für UTF-16LE, so hat man zu tun:

/** Allocates a new string in the module's memory and returns its pointer. */
function __newString(str) {
  if (str == null) return 0;
  const length = str.length;
  const ptr = __new(length << 1, STRING_ID);
  const U16 = new Uint16Array(memory.buffer);
  for (var i = 0, p = ptr >>> 1; i < length; ++i) U16[p + i] = str.charCodeAt(i);
  return ptr;
}

Wie Sie sehen können, ist dies ein großer Schmerzpunkt für Java, C#, AS und andere, und beide wären immer noch erforderlich, wenn ein list u16 wird. Und im Zusammenhang mit diesem Problem ist es nicht ausschließlich auf die JS-API beschränkt, da doppelte Neucodierung + Verlust zwischen zwei Modulen derselben Sprache nicht so unterschiedlich sind :(

Es gibt eine ganze Reihe von Optionen, die über TextEncoder / TextDecoder hinausgehen, um diesen Anwendungsfall im Web anzugehen. Eine andere ist die Erweiterung von new WebAssembly.Function() (die in einigen Browsern bereits implementiert ist), um Zeichenfolgenkonvertierungen durchzuführen, indem dem Konstruktor zusätzliche optionale Parameter hinzugefügt werden. Ein solcher Ansatz würde die Funktionalität auch für Nicht-Komponenten-Anwendungen von wasm verfügbar machen (und möglicherweise viel früher), was den Punkt unterstreicht, dass die JS-API der richtige Ort für diesen Anwendungsfall wäre.

Zu Ihrer Information: Die Option "Integrated W/UTF-any" wurde in https://github.com/WebAssembly/interface-types/issues/135#issuecomment -863493832 zur obigen Liste der Vorschläge hinzugefügt :)

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

ghost picture ghost  ·  7Kommentare

beriberikix picture beriberikix  ·  7Kommentare

artem-v-shamsutdinov picture artem-v-shamsutdinov  ·  6Kommentare

aaabbbcccddd00001111 picture aaabbbcccddd00001111  ·  3Kommentare

bobOnGitHub picture bobOnGitHub  ·  6Kommentare