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.
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:
Vielleicht ein paar mögliche Lösungen, die ich bisher aus Offline-Feedback gesammelt habe, zur Überlegung:
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.
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.
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.
Definieren Sie in Schnittstellentypen:
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 wiebyte_string
, um die Absicht zu kommunizieren) anstatt der IT-Typstring
, 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:
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 :)
Hilfreichster Kommentar
Dies ist derzeit auch meine bevorzugte Lösung - ein
wtf16string
Typ wäre ein Alias für(list u16)
genauso wiestring
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, diewtf16string
zurückgibt,Das Hinzufügen eines zusätzlichen Alias
wtf16string
zum kanonischen ABI-Entwurf scheint relativ unaufdringlich zu sein.