Design: Larang impor duplikat?

Dibuat pada 3 Mar 2021  ·  44Komentar  ·  Sumber: WebAssembly/design

(Masalah ini menangkap presentasi di CG-03-02 , dengan tujuan mendapatkan lebih banyak umpan balik dalam persiapan untuk polling di beberapa pertemuan CG mendatang.)

Proposal Penautan Modul mengusulkan untuk menyusun kembali impor dua tingkat sebagai gula untuk impor instans satu tingkat . Sebagai contoh:

(module
  (import "a" "foo" (func))
  (import "a" "bar" (func))
)

akan didesugasi menjadi AST yang sama dengan:

(module
  (import "a" (instance
    (export "foo" (func))
    (export "bar" (func)))
)

Satu masalah dengan ini adalah bahwa wasm saat ini memungkinkan impor duplikat (dengan tanda tangan yang sama atau berbeda):

(module
  (import "a" "b" (func))
  (import "a" "b" (func))
)

sementara ekspor duplikat tidak diizinkan. Dengan demikian, desugaring di atas untuk:

(module
  (import "a" (instance
    (export "b" (func))
    (export "b" (func)))
)

tidak akan valid. module-linking/#7 membahas berbagai cara untuk mendamaikan perbedaan ini, tetapi solusi paling sederhana adalah dengan melarang impor duplikat secara surut.

Bug 1647791 menambahkan telemetri untuk mengukur impor duplikat di Firefox, dan hasil untuk Firefox Beta 86 menunjukkan 0,00014% dari pemuatan halaman berisi impor duplikat (yang mungkin hanya pengujian unit dalam otomatisasi atau sumber sintetis lainnya). Jadi, sepertinya ini adalah perubahan besar yang bisa kita lakukan secara praktis.

Alasan berprinsip lain untuk melarang impor duplikat adalah bahwa impor duplikat dengan tanda tangan yang berbeda hanya dapat diterapkan oleh host yang melanggar tujuan umum yang memungkinkan wasm untuk selalu dapat memvirtualisasikan (polyfill, mock, dll) impor wasm.

Pada sedikit pengalaman nyata adalah bahwa suite uji spesifikasi dulu memiliki impor duplikat (untuk "kelebihan" fungsi cetak yang berbeda), tetapi ini dihapus karena menyebabkan masalah bagi orang yang ingin menjalankan tes.

Dengan demikian, dapat dikatakan bahwa pembatasan ini secara umum baik untuk ekosistem persampahan, bahkan mengesampingkan kekhawatiran proposal Module Linking.

Komentar yang paling membantu

Impor duplikat cukup berguna untuk memanggil impor dari bahasa dinamis seperti JS, di mana fungsi yang sama dapat memiliki berbagai tanda tangan, dan saya berharap itu digunakan lebih dari kurang begitu sistem tipe pada batas menjadi lebih kaya, katakanlah seseorang dapat menelepon fungsi yang sama dengan argumen angka atau string, atau dengan satu atau dua argumen. Saya merasa menghapus fitur ini akan sangat disayangkan untuk interop dengan JS.

Semua 44 komentar

Hal buruk apa yang akan terjadi dalam proposal penautan modul jika kami tidak melakukan perubahan ini? Apakah itu berarti desugaring ini tidak akan berfungsi dan deskripsi spesifikasi impor karenanya akan lebih rumit? Atau apakah itu akan mengganggu fungsionalitas proposal penautan modul secara lebih mendasar? (Saya sama sekali tidak menentang perubahan ini, saya hanya mencoba memahami motivasi dengan lebih baik.)

Seperti yang saya ingat dari presentasi Luke, saat ini kami melarang ekspor duplikat.

Bagaimana jika kami mencabut pembatasan ini dan mengizinkan ekspor duplikat? Itu membuka ruang desain untuk penautan modul untuk menyelesaikan masalah ini dengan cara lain.

Saat ini, mesin hanya perlu memeriksa nama impor/ekspor karena dua alasan: kesesuaian UTF-8, dan pemeriksaan ekspor duplikat. Kami telah berbicara secara offline tentang mencabut batasan UTF-8, tapi mungkin kami bisa mengangkat keduanya.

Ekspor duplikat akan membuat penautan berbasis nama menjadi ambigu.

@tlively Jika kami tidak melarang impor duplikat, maka solusi alternatif yang kami diskusikan di penautan modul/#7 sepertinya akan menambah kerumitan yang signifikan pada implementasi validasi dan penautan, terutama seputar menanyakan apakah modul A yang diberikan saat pembuatan instance waktu yang dapat diterima untuk impor dari modul B.

@titzer Saya pikir menambahkan ekspor duplikat akan menghasilkan banyak pertanyaan sulit untuk setiap integrasi bahasa sumber. Misalnya, di JS API: apakah ekspor duplikat muncul sebagai objek fungsi JS tunggal yang melakukan resolusi kelebihan beban dinamis? Web IDL melakukan ini dan itu cukup rumit . Apa yang terjadi jika saya mencoba mengimpor fungsi JS ini dari wasm (via WebAssembly.instantiate )? Saya tidak mengatakan itu masalah desain yang mustahil, tetapi jika ada opsi untuk menghindari pertanyaan sulit/berantakan ini sama sekali untuk integrasi bahasa N, itu tampaknya lebih disukai.

Impor duplikat cukup berguna untuk memanggil impor dari bahasa dinamis seperti JS, di mana fungsi yang sama dapat memiliki berbagai tanda tangan, dan saya berharap itu digunakan lebih dari kurang begitu sistem tipe pada batas menjadi lebih kaya, katakanlah seseorang dapat menelepon fungsi yang sama dengan argumen angka atau string, atau dengan satu atau dua argumen. Saya merasa menghapus fitur ini akan sangat disayangkan untuk interop dengan JS.

@lukewagner , ini mungkin ide yang buruk karena kurangnya pemahaman saya dengan proposal penautan modul, tetapi bukankah pilihan lain adalah menjaga impor MVP dan impor instance berbeda? Jika tidak disatukan, impor MVP masih bisa digandakan dan tidak perlu tipe persimpangan yang rumit.

Impor duplikat cukup berguna untuk memanggil impor dari bahasa dinamis seperti JS, di mana fungsi yang sama dapat memiliki berbagai tanda tangan, dan saya berharap itu digunakan lebih dari kurang begitu sistem tipe pada batas menjadi lebih kaya, katakanlah seseorang dapat menelepon fungsi yang sama dengan argumen angka atau string, atau dengan satu atau dua argumen. Saya merasa menghapus fitur ini akan sangat disayangkan untuk interop dengan JS.

Ini. Seribu kali ini. Saya adalah pengembang utama pada proyek yang menyediakan kerangka kerja pengujian untuk pengembang skrip perakitan, dan saya melihat ini mungkin sebagai salah satu bagian terpenting dari perakitan web saat ini.

0,00014% termasuk as-pect , test runner untuk AssemblyScript oleh @jtenner , yang merupakan bagian penting dari ekosistem AssemblyScript yang berkembang.

Impor duplikat cukup berguna untuk memanggil impor dari bahasa dinamis seperti JS, di mana fungsi yang sama dapat memiliki berbagai tanda tangan,

Jika setidaknya akan ada alternatif untuk ini, maka itu akan bagus, karena asal WebAssembly ada di browser dengan JavaScript. Mari kita buat hal-hal mudah untuk target itu.

@tlively Itu salah satu opsi alternatif yang mungkin, ya, tetapi memiliki konsekuensi yang tidak menguntungkan karena memiliki dua cara untuk melakukan hal yang kira-kira sama, yang secara umum adalah sesuatu yang baik untuk dihindari, dan itu juga menciptakan lebih banyak kasus untuk dipedulikan oleh implementasi selama validasi, pemeriksaan subtipe, dan instantiasi.

@jtenner @trusktr Agar jelas, Anda masih dapat mengimpor fungsi JS yang sama beberapa kali, satu-satunya perbedaan adalah bahwa setiap tanda tangan berbeda yang Anda impor akan memerlukan nama yang berbeda. Jadi, misalnya, alih-alih memancarkan:

(module
  (import "env" "log" (func (param i32)))
  (import "env" "log" (func (param f32)))
  (import "env" "log" (func (param i64)))
  (import "env" "log" (func (param f64)))
  ...
)

diinstansiasi melalui:

WebAssembly.instantiate(module, { env: { log:log } });

Anda bisa memancarkan:

(module
  (import "env" "log_i32" (func (param i32)))
  (import "env" "log_f32" (func (param f32)))
  (import "env" "log_i64" (func (param i64)))
  (import "env" "log_f64" (func (param f64)))
  ...
)

diinstansiasi dengan:

WebAssembly.instantiate(module, { env: { log_i32:log, log_f32:log, log_i64:log, log_f64:log } })

Apakah itu kemungkinan perubahan yang dapat Anda buat atau akankah itu menjadi penghalang dalam beberapa hal?

Apakah itu kemungkinan perubahan yang dapat Anda buat atau akankah itu menjadi penghalang dalam beberapa hal?

Terlalu tinggi? Tidak. Jika yang harus saya lakukan hanyalah mengubah nama fungsi yang saya tautkan, ini tidak masalah. Mengganggu, tapi baik-baik saja. Saya hanya ingin memastikan bahwa saya didengar dengan benar.

Mari kita buat hal-hal mudah untuk target itu.

Pengembang JavaScript akan paling terpengaruh oleh perubahan ini. Dan karena kami adalah "perakitan web", kami harus sangat berhati-hati dalam memperlakukan pengembang web sehubungan dengan masalah di masa mendatang seperti ini.

Saya siap untuk perubahan jika itu membuat segalanya lebih baik. Jadi saya memiliki pertanyaan berikut dalam urutan apa yang saya anggap paling penting hingga yang paling tidak penting:

  1. Apakah ini membuat web menjadi tempat yang lebih baik untuk pengembangan?

Sejauh yang saya bisa lihat? Mungkin. Ini memaksa pengembang untuk lebih eksplisit tentang impor, dan mencegah pengembang JavaScript untuk melakukan lebih sedikit hal-hal javascripty. Mungkin lebih banyak batasan mengarah pada lebih banyak kreativitas. Percakapan yang sepertinya tidak pernah terjadi adalah bagaimana hal ini memengaruhi pengembang C# dan Java. Saya percaya ini mungkin berdampak negatif pada C# devs yang menulis kompiler rakitan web juga, tetapi mungkin kerumitan ini tidak terlalu buruk.

  1. Apakah ini membuat WebAssembly lebih mudah diterapkan, dipelihara, dan lebih cepat dijalankan?

Saya tidak tahu jawaban untuk ini. Pengembang kompiler akan lebih berpengalaman dalam hal semacam ini. Dugaan saya adalah lebih nyaman bagi pengembang yang mencoba memelihara mesin wasm. Dan ya, itu akan lebih cepat, atau setidaknya akan lebih eksplisit, lebih mudah untuk memvalidasi status modul.

  1. Apakah perubahan ini akan berdampak negatif pada pengembang yang mengandalkan perilaku yang sebelumnya tidak berubah?

Sejauh yang saya tahu, beberapa orang yang menggunakan fitur ini, barang-barang mereka akan rusak, dan mereka tidak akan senang karena harus kembali dan mencoba mencari cara untuk memperbaiki perangkat lunak mereka.

Setelah mempertahankan pengujian perangkat lunak kerangka kerja untuk AssemblyScript, saya menyadari bahwa perubahan kecil seperti ini tidak memengaruhi pengembang akhir biasa. Perubahan ini memengaruhi orang yang memelihara perangkat lunak ekosistem, alat pengembangan, dan kompiler. Perubahan halus dalam spesifikasi seperti ini dapat menghasilkan permintaan tarik yang sangat besar yang membutuhkan waktu berhari-hari atau berminggu-minggu untuk diselesaikan.

Pendapat tl;dr terakhir saya: Saya tidak suka perubahan ini, tetapi jika Anda akan membuat perubahan, lepaskan plester. Mulai reaksi berantai sekarang, dan buatlah itu diperhitungkan.

Saya melihat satu lagi kelemahan dari ini:

(module
  (import "env" "log_i32_f32_f64" (func (param i32 f32 f64)))
  (import "env" "log_f32_i32_f64" (func (param f32 i32 f64)))
  ...
)

itu berpotensi meningkatkan ukuran biner ketika Anda harus menyimpan nama impor asli (untuk demangling) dan tidak dapat menerapkan pass binaryen yang mengompresi nama impor.

Namun itu bukan masalah yang terlalu besar untuk kasus umum

Masalah inti yang saya lihat adalah bahwa pengguna harus mengetahui semua aritas dan tipe argumen di muka untuk secara manual memotong objek impor, sementara saat ini kompiler dapat mengasumsikan bahwa misalnya Math diimpor secara keseluruhan, dan menghasilkan impor dengan nama yang sama tetapi aritas atau tipe argumen yang berbeda saat menghadapi panggilan impor selama kompilasi. Contoh sederhana di sini adalah Math.max , yang sedikit lebih kompleks adalah ctors Typed Array dengan tanda tangan yang sangat berbeda , dan itu hanya menjadi lebih kompleks dengan misalnya Node.js API, yang sering memungkinkan menghilangkan argumen di tengah hal sementara juga memungkinkan jenis yang sangat berbeda, dan pada akhirnya kode pengguna tentu saja, yang tidak pernah diketahui pasti. Dan tentu saja, setiap kali sesuatu yang terkait dalam sumber modul Wasm berubah, seseorang juga harus mengunjungi kembali objek impor. Itu semua akan sangat menyedihkan.

Saya pikir apa yang tidak dapat saya ungkapkan dalam pertemuan CG adalah bahwa saya pikir proposal penautan modul mencoba menekan persyaratan dari penautan berbasis nama ke mesin dan tampaknya wajar bagi saya bahwa ada lapisan di sini sehingga persyaratan tersebut melakukannya tidak terdorong ke bawah. Misalnya, ketika kami membatasi format biner dari core wasm, kami menyatakan bahwa mesin harus memeriksa dan menolak modul yang tidak sesuai. Untuk keamanan tipe, batasan ukuran yang wajar, dan hal-hal lain yang penting bagi mesin, ini sangat masuk akal.

Saya berpendapat bahwa nama tidak penting bagi mesin; mereka hanya penting untuk menjadi tuan rumah embeddings, dan mesin benar-benar tidak perlu melihat (apalagi menolak) nama. Ini dibuktikan dalam situasi kelebihan beban JS yang disebutkan oleh komentator lain.

Komentar saya tentang UTF-8 mengarah ke sana; mesin benar-benar tidak membutuhkan pemrosesan UTF-8 kecuali untuk menolak nama buruk; sama untuk ekspor duplikat. Ini berbau aneh melakukan Wizard, karena saya tiba-tiba harus mengimplementasikan validator UTF-8 dari awal ... hmm. Juga, pemeriksaan ekspor duplikat adalah satu-satunya tempat Wizard menggunakan tabel hash. Bukan berarti seratus atau lebih baris kode adalah krisis, tetapi ini adalah bebek aneh dalam latihan VM yang berorientasi komputasi.

Saya mengerti tujuan dari proposal penautan modul adalah untuk memberikan solusi penautan berbasis nama standar untuk Wasm, tetapi untuk beberapa alasan saya pikir itu memiliki beberapa risiko tidak berfungsi secara umum sehingga kita harus menggunakan pelarangan hal-hal yang sempurna dari sudut pandang mesin, pada tingkat mesin.

Jadi saya mendukung saran saya sebelumnya bahwa kita harus lebih liberal, dan mungkin mencabut pembatasan ekspor duplikat.

Jika proposal penautan modul ingin menolak modul saat ini yang tidak dapat ditautkan karena masalah penamaan, maka itu tampaknya baik-baik saja sebagai pembatasan lapisan di atas inti wasm. Tetapi seperti yang saya katakan, ada risiko proposal penautan modul tidak akan menyelesaikan masalah penautan untuk banyak bahasa pemrograman dan sebaliknya kita memerlukan solusi yang lebih dapat diprogram yang melibatkan API untuk modul kelas satu. Tapi itu mungkin percakapan yang lebih panjang dan ini adalah masalah yang cukup sempit. Itulah konteks pemikiran saya di sini.

Ah, menarik @titzer. Saya pernah memiliki pemikiran serupa. Singkatnya, kompilasi dan penautan terhubung tetapi masih berbeda, dan masalah ini adalah kenari bahwa mereka terlalu erat digabungkan.

Kami dapat membayangkan mengambil semua aspek yang berhubungan dengan penautan dari WebAssembly dan memasukkannya ke dalam bagian terpisah. Bagian "kompilasi" akan tetap memiliki impor, tetapi tidak disebutkan namanya (di luar indeksnya)—hanya lubang yang akan diisi oleh bagian "tautan". Bagian "kompilasi" mungkin masih memiliki ekspor, tetapi sekali lagi tidak disebutkan namanya dan bagian "penautan" bertanggung jawab untuk memberikan nama.

Menautkan bagian, kemudian, dapat memiliki konten khusus penyemat. Misalnya, bagian yang menghubungkan untuk Jenis Antarmuka bisa memberikan adapter_func s, sedangkan bagian yang menghubungkan untuk JS bisa menginstal rtt kamus seperti dalam @tebbi 's WebAssembly / gc # 132-dalam kedua kasus, konten tambahan ini hanya masuk akal untuk penyemat tertentu dan sangat berguna untuk penyemat tertentu. Proposal tipe modul pada dasarnya adalah penyemat penautan lain, dan bagian dari ketegangan adalah bahwa apa yang paling masuk akal di sana (misalnya nama tunggal untuk resolusi tautan sederhana) bukanlah yang paling masuk akal di JS (misalnya nama yang kelebihan beban).

Tambahan: Ini bisa berguna untuk mendukung jitting. Modul ingin agar fungsinya dapat langsung dipanggil dari modul tambahan yang dihasilkan secara dinamis tanpa juga harus mengekspos fungsi tersebut ke sistem tautan tertanam.

Seperti yang dikatakan @titzer , ini juga berada di luar cakupan diskusi ini, tetapi saya juga ingin menggabungkan pemikiran saya dengan ide tersebut.

@dcodeIO Dalam semua skenario yang saya lihat, kode JS yang membuat modul wasm dihasilkan oleh rantai alat yang sama yang menghasilkan modul wasm (b/c instantiasi secara umum cenderung memiliki banyak kode lem yang diperlukan), jadi saya Saya tidak menyadari bahwa detail impl ini akan disampaikan kepada pengguna. Tapi pernahkah Anda melihat secara berbeda?

Satu hal yang ingin saya klarifikasi dan tekankan: dari POV ekosistem JS murni, impor duplikat adalah bahaya karena JS API dan integrasi ESM tidak memiliki cara untuk menghubungkan dua instance wasm A dan B di mana B memiliki impor duplikat yang ingin kita penuhi dengan A. A mungkin dapat mengekspor dua fungsi dengan tanda tangan yang sesuai, tetapi B hanya akan dapat mengimpor 1 di antaranya (dengan satu tanda tangan, yang secara umum tidak akan dapat memenuhi kedua impor).

@titzer Saya memahami keinginan untuk menjaga nama dari inti wasm, tetapi untuk mewujudkan tujuan Anda, alih-alih mengimpor modul seperti yang diusulkan saat ini:

(module
  (import "other" (module
    (import "foo" (func))
    (export "bar" (func))
  ))
)

kita malah harus menghapus "foo" dan "bar" dari tipe impor, meninggalkan sesuatu yang murni posisi:

(module
  (import "other" (module
    (import (func))
    (export (func))
  ))
)

Jika kita berharap untuk skenario kompilasi terpisah (misalnya, memfaktorkan perpustakaan bersama ke dalam modul yang digunakan kembali secara luas), maka ini akan mengarah ke versi lama dari masalah dasar rapuh C++ lama karena kita akan bergantung sepenuhnya pada urutan posisi; inilah yang diperbaiki oleh nama impor/ekspor. Apakah itu yang Anda usulkan? (Perhatikan bahwa referensi modul kelas satu dan/atau instance/instansi kelas satu semuanya memiliki masalah yang sama; ini ortogonal.)

Tetapi jika bukan itu yang Anda usulkan, maka saya tidak melihat bagaimana kita dapat melepaskan diri dari nama sebagai bagian penting dari penautan modul dan dengan demikian ambiguitas yang disebabkan oleh impor/ekspor duplikat.

Tidak, saya tidak mengusulkan tautan posisi. Saya setuju bahwa itu memang sangat rapuh.

Tetapi dengan melihat kasus penggunaan Jawa, dan juga pada tipe antarmuka, hal yang menonjol adalah kebutuhan untuk benar-benar mengurai dan menerapkan logika pada impor. Di Jawa, nama impor bukan string tetapi sebenarnya ekspresi dalam suatu bahasa, dan dengan argumen impor, mereka dapat mengambil tipe dan fungsi sebagai impor. Tidak ada solusi wasm murni untuk pengikatan terlambat dengan Java, atau IMHO bahasa tingkat tinggi apa pun. Solusi penautan berbasis nama tingkat rendah mungkin melayani ekosistem ceruk yang dibangun dengan seperangkat bahasa yang sangat terbatas, tetapi itu tidak menyelesaikan kasus penggunaan bahasa tingkat yang lebih tinggi dalam jangka panjang. Jadi IMO sedang membangun mekanisme untuk memungkinkan terciptanya ekosistem baru yang sangat terbatas, sebagai lawan menambahkan mekanisme yang cukup umum untuk membangun tautan di tingkat yang lebih tinggi.

Demikian komentar saya tentang modul kelas satu. Dalam jangka panjang kita akan membutuhkan refleksi dan JITing API yang akan memungkinkan penautan yang sepenuhnya dapat diprogram dan sistem pencocokan berbasis nama yang sangat kaku tidak benar-benar menyelesaikan masalah nyata bahasa apa pun atau memberi mereka cukup tali.

Dan pencocokan berdasarkan nama juga sangat rapuh. Karena kami belum memiliki mekanisme parameterisasi untuk impor, bahasa harus menggunakan mangling nama, yang jelek dan rapuh, dan bahkan tidak dapat mendukung hal-hal sederhana seperti subtipe dan kelebihan beban.

Maaf untuk komentar yang diperpanjang; kita benar-benar membahas masalah yang lebih besar sekarang dan itu mungkin tidak boleh pada masalah yang sempit seperti di sini.

Dalam semua skenario yang saya lihat, kode JS yang membuat modul wasm dihasilkan oleh rantai alat yang sama yang menghasilkan modul wasm (instansi b/c secara umum cenderung memiliki banyak kode lem yang diperlukan)

AssemblyScript misalnya tidak menghasilkan kode lem khusus modul tetapi mencoba menghindarinya. Itu hanya memancarkan definisi tipe (untuk tujuan pengembangan) untuk digunakan dengan perpustakaan JS pendamping tujuan umum kecil (dapat membongkar nama ekspor tingkat yang lebih tinggi untuk penggunaan yang lebih nyaman dari JS) yang baru saja kita sebut "loader", tetapi menggunakannya sering opsional , terutama ketika menggunakan AS sebagian besar sebagai sintaks yang sedikit lebih baik untuk menghasilkan modul Wasm minimal, katakanlah untuk algoritme kompresi (hanya ekspor fungsi seperti C misalnya), atau ketika mengkompilasi untuk WASI. Harapan saya adalah bahwa kita pada akhirnya tidak perlu mengubah nama, seperti MyClass#myMethod , lagi, tetapi saya tidak yakin apakah ini terkait dengan masalah ini.

impor duplikat adalah bahaya karena baik JS API dan integrasi ESM tidak memiliki cara untuk menghubungkan dua instance wasm A dan B di mana B memiliki impor duplikat yang ingin kita penuhi dengan A

Saya berharap bahwa kasus ini menghasilkan kesalahan di suatu tempat di jalan, ya, mungkin selama menautkan ekspor Wasm ke impor Wasm dengan ketidakcocokan tanda tangan yang tidak dapat dipenuhi, sementara itu akan menghasilkan banyak perilaku menyenangkan saat runtime saat menggunakan tanda tangan yang tidak cocok dengan impor JS, atau impor dari bahasa dinamis lainnya.

Tidak jelas bagi saya mengapa perlu menggunakan nama yang sama untuk mengimpor beberapa fungsi Wasm dengan tanda tangan yang berbeda, karena fungsi Wasm memiliki tanda tangan tetap (tidak seperti fungsi host JS, yang memaksa semua argumen dan mengembalikan tipe ke tanda tangan yang diberikan). Apakah saya salah memahami premis?

Sepertinya akan sangat normal untuk skenario ini untuk kesalahan jika impor yang diberikan adalah fungsi Wasm, kecuali jika standar diperluas untuk memungkinkan menentukan fungsi dengan tanda tangan yang berbeda yang meminta paksaan otomatis juga.

Meskipun saya awalnya berhati-hati untuk menghapus impor duplikat, sekarang saya sangat mendukung perubahan ini.

Pengamatan penting adalah bahwa impor duplikat tidak dapat ditangani di berbagai lingkungan, seperti yang ditunjukkan oleh @lukewagner . Dan seperti yang dia katakan, itu bermasalah bahkan untuk kasus penggunaan JS.

Yang terpenting, ini merusak properti modular dasar, yaitu bahwa semua impor dapat diimplementasikan secara merata oleh Wasm atau oleh modul host. Itu penting untuk kasus penggunaan seperti virtualisasi.

Impor duplikat secara efektif memaksa mekanisme pengetikan yang berlebihan atau dinamis di sisi klien, yang buruk, karena tidak setiap klien memiliki sarana untuk mendukungnya (termasuk modul Wasm lainnya).

Dan ini adalah masalah nyata dalam praktiknya, seperti yang telah ditunjukkan oleh sejarah rangkaian pengujian.

@titzer , saya khawatir saya tidak mengikuti. Penamaan yang tidak ambigu sepertinya merupakan masalah ortogonal untuk parameterisasi. Bahkan jika kami memiliki yang terakhir, kami masih ingin memastikan bahwa nama secara unik menentukan entitas (berparameter). Mungkin lebih dari itu, karena menyelesaikan nama impor yang kelebihan beban dengan cara lain menjadi lebih rumit ketika cara lain ini menjadi lebih kompleks?

Seperti yang saya katakan, nama tidak penting bagi mesin, jadi keunikannya juga tidak penting bagi mesin. Mereka penting bagi _linkers_, jadi ini adalah pilihan solusi penautan tertentu jika ingin menerapkan keunikan pada nama impor (atau nama ekspor dalam hal ini). Dan linker dalam batas akan membutuhkan solusi yang sepenuhnya dapat diprogram pada akhirnya, yang tidak hanya modul dan instance kelas satu, tetapi JITing dan kemampuan untuk membangunnya secara bertahap.

Saya pikir semua masalah datang dari mencoba membuat modul menjadi functors yang diketik secara statis[*] dari impor ke ekspor berdasarkan nama. Efeknya adalah bahwa nama menjadi bagian dari suatu tipe, dan memperkenalkan tipe tersebut ke dalam bahasa wasm memerlukan pengecekan tipe dan oleh karena itu aturan pencocokan nama. Tetapi masalahnya adalah bahwa nama-nama ini adalah nama tingkat rendah, mirip dengan nama C/C++ yang rusak. Hasil akhirnya adalah tiga hal buruk:

  1. kita sudah melihat: wasm bahkan tidak dapat terhubung ke lingkungan host yang memiliki kelebihan beban
  2. penautan terus-menerus dibatasi oleh apa yang dapat dan tidak dapat diekspresikan menggunakan nama tingkat rendah saja, yang mengarah ke masalah desain yang konstan dengan setiap fitur wasm baru
  3. itu tidak melayani bahasa yang tidak dapat menggunakan rendah skema nama tingkat mangling, yang akan membutuhkan solusi diprogram dan Jiting.

Masalah-masalah ini mengikuti langsung dari keinginan untuk memperkenalkan jenis modul statis, karena itu dimotivasi oleh membuat mesin melakukan pencocokan berbasis nama untuk solusi penautan sederhana. Namun pada kenyataannya, mesin tidak boleh melihat nama; hal lain--penghubung--harus melihat nama dan haruskah mereka menyelesaikannya untuk mesin. Dan ya, salah satu cara untuk memecahkan masalah itu adalah bahwa API menyediakan vektor impor ke penaut dan mengembalikan vektor ekspor--itulah yang saya lakukan di Wizard dan begitulah cara kerja API penyematan C.

[ ] Dulu saya juga berpikir demikian, bahwa modul wasm adalah fungsi dari impor hingga ekspor. Tapi itu kehilangan sesuatu yang penting: logika untuk menautkan yang berasal dari bahasa tingkat yang lebih tinggi.

@titzer , saya setuju bahwa proposal penautan modul tidak menyediakan model penautan yang cukup kuat untuk banyak kasus penggunaan (misalnya, itu tidak akan dapat menggantikan file objek C), tetapi saya tidak berpikir menyediakan penautan tujuan umum model adalah tujuan dari proposal. Saya melihatnya sebagai perpanjangan dari sistem impor/ekspor berbasis string saat ini yang cukup dan berguna untuk penautan gaya bundler yang umum di Web dan yang sudah dimasukkan ke dalam struktur modul Wasm sampai batas tertentu. Penaut khusus bahasa tingkat tinggi dapat terus melakukan apa pun yang mereka inginkan sehubungan dengan penamaan karena modularitasnya harus berlapis di atas WebAssembly.

@titzer Jika nama impor dan ekspor bukan bagian dari tipe modul, lalu bagaimana Anda mengusulkan untuk menghindari masalah kerapuhan yang Anda katakan juga ingin Anda hindari?

Saya juga tidak melihat bagaimana Anda mengatasi masalah virtualisasi. Membaca komentar @rossberg , saya menyadari bahwa virtualisasi adalah masalah yang sudah ada sebelumnya yang lebih mendasar untuk diselesaikan di sini, dan itu sebenarnya tidak ada hubungannya dengan proposal Penautan Modul.

Saya bersimpati dengan perubahan tersebut, tetapi melihat WebAssembly/module-linking#7, sepertinya tidak ada banyak opsi yang dipertimbangkan. Ada banyak diskusi tentang tipe persimpangan, tetapi diskusi itu tidak menyebutkan bahwa transformasi menggunakan tipe persimpangan tidak berfungsi untuk sistem penghubung koersif seperti JS API, yang menjadi sandaran beberapa kasus penggunaan yang disebutkan di sini. Semua opsi yang dipertimbangkan tampaknya didasarkan pada konstruksi modul bahasa permukaan (terutama berdasarkan pengetahuan Andreas tentang modul untuk bahasa fungsional khusus), tetapi tampaknya tidak ada banyak pertimbangan untuk konstruksi modul tingkat rendah. Sistem modul tingkat rendah akan dengan mudah membuat masalah di sini diperdebatkan sambil tetap melayani tujuan proposal penautan modul (termasuk resolusi berbasis nama). Pada saat yang sama, akan lebih mudah untuk membangun sejumlah ekstensi penting.

@RossTate , saya tidak yakin apa yang Anda maksud sebagai "sistem modul tingkat rendah" di sini atau bagaimana perbedaannya dari apa yang telah dibahas. Jika Anda memiliki ide untuk solusi yang berbeda, mungkin dapat didiskusikan di https://github.com/WebAssembly/module-linking/issues/7 untuk menjaga agar masalah ini tetap fokus pada solusi yang diusulkan untuk melarang impor duplikat.

Saya telah meninggalkan catatan di https://github.com/WebAssembly/module-linking/issues/7#issuecomment -791063260 menanyakan apakah ini dapat menjadi bagian dari validasi penautan modul tanpa menyebabkan masalah kompatibilitas mundur untuk kode yang ada yang mungkin berada di alam liar.

Ini adalah persis masalah yang membawa saya begitu lama untuk menghadapi. Modul tidak memiliki tipe tanpa mempertimbangkan prosesor impor yang memberi arti pada nama dan batasan yang terkait dengan impor. Ini seperti menanyakan apa jenis file teks. Tentu saja file teks dapat berisi teks yang ditulis dalam bahasa apa pun, sehingga pertanyaan itu tidak masuk akal tanpa konteks. Ketika kita memperbaiki bahasa, maka kita bahkan dapat mulai berbicara tentang jenis, jika ada, dalam sebuah file. Di sini lagi sama dengan modul. Modul bukan fungsi, yaitu fungsi murni dari impor (dengan nama) ke ekspornya. Mereka membutuhkan sistem penghubung untuk memberi arti impor. Sampai kita melewati titik itu, tidak satu pun dari apa yang saya katakan masuk akal. Saya merasa itu adalah asumsi yang sangat mendasar dalam proposal penautan modul yang bahkan belum pernah muncul untuk didiskusikan. Dan saya merasa bahwa kita tidak benar-benar mempertanyakannya. Saya sepertinya mengulangi diri saya sendiri karena saya sebenarnya mempertanyakan hal-hal yang lebih dalam daripada yang terlihat sopan. Saya tidak bermaksud tidak sopan, tentu saja, tetapi saya bermaksud menantang bahwa modul harus terlihat seperti fungsi. Dan kami bahkan tidak mempertanyakan itu.

Saya dapat memberikan contoh demi contoh mengapa modul tidak berfungsi dengan jelas.

  1. Menautkan modul wasm ke JavaScript melalui objek impor--objek impor yang sebenarnya bisa menjadi proxy atau memiliki perilaku untuk menerapkan logika Turing-complete ke nama (misalnya mendekodekannya), dan bahkan memiliki status, yang membuatnya mustahil untuk berperan sebagai functor. Secara harfiah didefinisikan secara operasional sebagai algoritme yang menginterogasi objek JavaScript yang diimpor dengan mengimpor. Seluruh ekosistem penautan itu tidak dapat diekspresikan dengan penautan modul.

  2. API penyematan C adalah dengan cara yang sama. Ini menyediakan modul untuk embedder sebagai entitas yang sepenuhnya dapat diperiksa, lengkap dengan nama dan jenis serta tanda tangan untuk pemeriksaan. Untuk membuat instance modul, embedder dapat menerapkan logika apa pun yang mereka suka, selama mereka hanya menyediakan binding ke mesin (ya, dengan cara posisi) untuk instantiasi. Juga, ekosistem yang sepenuhnya dapat diprogram dan tidak diekspresikan dengan penautan modul.

  3. Baik Jawa dan Pywa juga seperti ini. Jawa sepenuhnya diketik secara statis, tetapi impornya dikodekan dalam bahasa impor dengan cara di mana pencocokan nama sederhana tidak memadai; runtime Jawa harus mensintesis (JIT) fungsi, tipe, dan ikatan baru lainnya untuk disediakan ke mesin. Pywa sepenuhnya diketik secara dinamis dan implementasi JS-nya menggunakan overloading dengan cara yang serupa.

Modul dan impornya hanya masuk akal dalam konteks skema penautan, bahasa, prosesor impor, apa pun yang Anda ingin menyebutnya. Sekali lagi, mereka bukan fungsi. Mereka tidak memiliki tipe tanpa konteks di mana mereka berada. Impor modul adalah deskripsi dari apa yang mereka butuhkan dari dunia luar yang ditulis dalam bahasa asing yang tidak, dan tidak dapat, dipahami oleh mesin. Mereka hanya memiliki tipe Wasm sehingga modul itu sendiri dapat diketik secara terpisah, terlepas dari impornya menurut sistem tipe Wasm, dan bahwa impor dapat diperiksa terhadap asumsi yang dijabarkan dalam batasan impor. Sekali lagi, tidak ada tentang nama yang muncul di sini sampai kita mulai mencoba membuat modul menjadi functor yang diketik wasm-y. Tapi nama-nama itu ungu! Di situlah semua hal bahasa sumber bertahan. Tentu saja meraba-raba dengan perbandingan string tidak akan berhasil.

Dengan mengingat hal itu, keinginan untuk membuat solusi penghubungan "tanpa embel-embel" bukanlah solusi yang buruk. Itu masuk akal ketika nama tidak terlalu gila. Ini seperti menciptakan ekosistem kecil di mana nama-nama sangat sederhana dan pencocokan sederhana sudah cukup. Itu tidak perlu menjadi primitif, karena itu bukan primitif yang tepat. Itu harus jelas karena itu memasukkan asumsinya langsung ke inti wasm dengan cara yang berisiko menjadi batu sandungan, atau kutil aneh, ketika kita sampai pada apa yang benar-benar dibutuhkan, yang merupakan API penghubung yang sepenuhnya dapat diprogram. Jika kami memiliki API yang dapat diprogram untuk penautan, maka proposal penautan modul dapat berupa perpustakaan. Jadi, sebaiknya kita berpikir tentang cara membuat API penyematan C menjadi lebih dari API wasm standar dan kemudian menulis penautan modul sebagai pustaka terhadap API tersebut.

@lukewagner Masalah "kerapuhan": perhatikan saya tidak menganjurkan membuang nama. Nama jelas dibutuhkan oleh sistem penautan. Tapi mereka tidak dibutuhkan oleh mesin. Untuk API antara mesin dan tautan, maksud saya hanya mesin dapat meneruskan impor ke tautan sebagai vektor yang dipesan, tautan dapat menyelesaikan (berpotensi sebagian dari mereka), dan mengembalikannya secara posisi. Modul sendiri tidak perlu bergantung pada posisi.

Dan ya, untuk masalah ini, ada kasus penggunaan yang sangat baik untuk impor duplikat yang telah saya pikirkan untuk sementara waktu, dan ya duplikat impor hingga argumen mereka: berbagi (atau tidak) cache inline. Jika kita ingin, misalnya mengimpor fungsi yang menjalankan akses properti JavaScript, kita mungkin memberinya nama "GetProperty[foo]". Jika kita mengimpornya sekali saja, cache inline apa yang harus digunakan mesin? Haruskah itu memeriksa kode wasm untuk menghasilkan situs panggilan baru untuk mereka? Nah, jika sebuah modul dapat mengimpor fungsi yang sama beberapa kali dengan nama yang persis sama, tetapi mendapatkan IC baru setiap kali, maka modul memiliki ukuran kontrol atas bagaimana mesin beradaptasi dengan berbagai polimorfismenya. (Tentu saja, kita selalu dapat menempelkan beberapa sampah unik yang konyol di ujung string, tetapi mengapa repot? Ini hanya mengatasi batasan dari hal yang sama sekali berbeda yang tidak kita gunakan di wasm.

@titzer Pandangan yang Anda

Secara independen, apa yang saya pelajari untuk menjadi pertanyaan utama di sini tetap: haruskah modul wasm dapat memvirtualisasikan ekspor wasm? Sepenuhnya mengesampingkan pertanyaan "bagaimana modul wasm dihubungkan bersama?", Ini sepertinya pertanyaan dasar tentang prinsip yang diajukan ke CG. Saya ingin tahu apakah mungkin perlu masalah desain terpisah untuk fokus hanya pada pertanyaan ini, terlepas dari pertanyaan tentang penautan?

Virtualisasi itu penting, dan penautan yang dapat diprogram pasti mendukung itu.

Saya sebenarnya tidak berpikir apa yang saya bicarakan sangat berbeda dari wasm hari ini, dan apa yang saya bicarakan tidak hanya ditujukan untuk Jawa. Hal yang sama muncul ketika berpikir tentang menautkan .NET atau runtime bahasa lainnya. Saya memberikan tiga contoh di atas, dua di antaranya adalah penyematan yang masih ada, yang karena disematkan dalam bahasa lain, memberikan kemampuan pemrograman penuh.

Saya sangat bersedia untuk menyusun presentasi untuk CG.

Fwiw, menurut pemahaman saya, saran titzer untuk membuat Wasm layak untuk lebih banyak kasus penggunaan daripada lebih sedikit jauh lebih sesuai dengan harapan saya daripada alternatifnya. Saya bahkan akan menyarankan bahwa diskusi yang lebih umum tentang arah Wasm mungkin diperlukan, mengingat semua kontroversi yang telah terjadi dalam masalah serupa untuk alasan yang sama di tempat lain.

Misalnya, saya menemukan pernyataan seperti

Pandangan yang Anda berikan adalah penyimpangan yang cukup signifikan dari bagaimana wasm ditentukan, diterapkan, dan dibicarakan secara luas hari ini, jadi saya pikir beban ada pada Anda untuk mengusulkan perubahan perspektif ini ke CG dan mendapatkan beberapa persetujuan--saya tidak 't berpikir itu sesuatu yang Anda dapat menegaskan sebagai sifat wasm.

sangat memprihatinkan dalam konteks. Mungkin ada masalah yang lebih luas di sini tentang bagaimana wasm ditentukan, dan tidak jelas bagi saya pihak mana yang berangkat.

@titzer Saya terutama mengacu pada bagian ini dari apa yang Anda katakan (dan semua konsekuensinya):

Modul tidak memiliki tipe tanpa mempertimbangkan prosesor impor yang memberi arti pada nama dan batasan yang terkait dengan impor. Ini seperti menanyakan apa jenis file teks.

yang akan menjadi penyimpangan yang signifikan dari spesifikasi saat ini (misalnya, bagian ini ).

@lukewagner Terima kasih telah mengarahkan saya ke sana.

Dalam formulasi itu, (seperti yang saya pikir diskusi tentang penautan modul telah menunjukkan), impor dan ekspor adalah vektor, dengan demikian, posisional. Untuk mengikat ekspor (posisi) dari satu modul ke impor (posisi) modul lain, Anda memerlukan fungsi pemetaan. Saya hanya menunjukkan bahwa fungsi pencocokan nama persis "tanpa embel-embel" hanyalah satu pilihan dan kami sudah memiliki dua penyematan lain di mana fungsi pemetaan itu sepenuhnya dapat diprogram dalam bahasa host.

@titzer Itu benar, tetapi perhatikan: terlepas dari kenyataan bahwa JS API sepenuhnya dapat diprogram, jika saya memberi Anda modul wasm dengan impor duplikat (dari berbagai jenis), Anda tidak dapat menggunakan JS API untuk mengimplementasikan impor tersebut dengan ekspor wasm karena penggunaan pencarian nama di WebAssembly.instantiate() . Hal yang sama berlaku untuk integrasi ESM . Meskipun saya dapat membayangkan ekstensi teoretis ke dua skema penautan ini untuk mendukung virtualisasi impor duplikat, saya lebih sulit membayangkan semua orang cukup termotivasi untuk benar-benar menentukan dan menerapkan kompleksitas ekstra.

Jadi, saya pikir pertanyaan yang harus kita ajukan adalah: "akankah segudang skema tautan wasm yang pasti akan muncul di seluruh ekosistem wasm akhirnya mendukung virtualisasi impor duplikat?" dan, berdasarkan kumpulan sampel kami saat ini, sepertinya tidak mungkin.

Bayangkan bahwa impor dan ekspor WebAssembly tidak memiliki string yang terkait dengannya. JS API akan menggunakan indeks posisi murni untuk mengakses impor dan ekspor. Dari apa yang saya tahu, akan mudah (dalam arti relatif) untuk membuat rantai alat yang ada berfungsi dengan pengaturan seperti itu. (Dalam beberapa kasus mungkin lebih mudah karena hal-hal seperti emscripten tidak perlu membuat nama arbitrer untuk menghubungkan kode JS "inline" (ala EM_ASM ).)

Di dunia seperti itu, tidak akan ada masalah virtualisasi. Artinya, masalah virtualisasi disebabkan oleh pilihan untuk menggunakan nama daripada indeks posisi. Seseorang bahkan bisa menyelesaikan ini dengan cara yang kompatibel dengan membuat keduanya tersedia di JS API.

Intinya adalah bahwa impor/ekspor non-posisional adalah dekorasi khusus embedder yang digunakan untuk memfasilitasi integrasi modul wasm ke dalam ekosistem. Bagaimana dekorasi tersebut ditentukan benar-benar harus disesuaikan dengan norma ekosistem (yang ada atau yang diharapkan).

Misalnya, dengan integrasi ESM, nilai JS yang diekspor oleh modul lain dapat kelebihan beban, tetapi WebAssembly tidak mendukung kelebihan beban, sehingga desain dekorasi ekspor-impor ESM harus menjembatani kesenjangan ini sehingga modul WebAssembly dapat menggantikan JS sebanyak mungkin. modul mungkin. Itu dapat dilakukan dengan melakukan impor duplikat dan paksaan yang diarahkan ke tipe untuk mengekstrak kelebihan beban yang berbeda dari suatu fungsi yang diimpor dari modul JS lain. Seseorang bahkan dapat mengizinkan ekspor duplikat selama jenis yang diekspor adalah semua fungsi dengan parameter yang cukup terpisah/dapat dibedakan sehingga dapat digabungkan menjadi satu fungsi JS yang kelebihan beban. Dan tentunya masih ada pilihan desain lainnya yang masing-masing memiliki kelebihan dan kekurangan.

Sebagai contoh yang kontras, anggaplah bahasa penyematan utama untuk WebAssembly terutama menggunakan parameter bernama untuk fungsi daripada parameter posisi. Kemudian dekorasi ekspor-impor akan terlihat agak berbeda, dengan ekspor fungsi yang menetapkan nama untuk setiap parameter. Tetapi pada level rendah, modul WebAssembly masih akan menjadi impor dan ekspor posisional.

Inilah sebabnya mengapa saya menyarankan agar masalah diselesaikan dengan mengambil langkah lebih rendah. Penautan modul WebAssembly "Inti", yaitu apa yang akan digunakan untuk menautkan bersama modul WebAssembly yang didefinisikan dalam file yang sama (misalnya untuk menautkan modul adaptor Tipe Antarmuka ke modul yang diadaptasinya), harus bersifat posisional. Penautan modul WebAssembly "Tersemat", yaitu apa yang akan digunakan untuk menautkan bersama baik WebAssembly dan modul khusus penyemat yang ditentukan dalam file terpisah dalam penyemat tertentu, akan menjadi bagian khusus penyemat dan sebagian besar akan bertanggung jawab untuk mendefinisikan konversi antara penyemat- konstruksi spesifik dan konstruksi WebAssembly, seperti fungsi pemaksaan, menambahkan dekorasi ke fungsi/instance/modul yang diekspor, atau mengaitkan nama (tunggal/ganda/daftar) dengan impor posisi. Kemudian WebAssembly "inti" tidak pernah mengkhawatirkan apa pun selain angka dan posisi, dan masalah seperti impor duplikat menjadi masalah khusus penyemat daripada masalah "inti".

Dengan mentalitas itu, masalah ini dapat disusun kembali sebagai "Untuk JS API atau untuk modul ES, haruskah kita mengizinkan dua impor dikaitkan dengan string yang sama?" dengan jawaban yang tidak memiliki arti penting bagi proposal penautan modul. Ini pertanyaan yang berguna, tetapi sulit untuk mendapatkan jawaban yang baik saat ini sementara argumen utama didasarkan pada kopling yang (saya pikir) seharusnya tidak ada.

Saya setuju bahwa impor/ekspor posisi menghindari duplikat seluruh pertanyaan. Masalah yang ingin saya hindari, bagaimanapun, adalah ketika Anda memiliki kompilasi terpisah pada waktu yang terpisah, sehingga Anda harus mulai peduli tentang versi, impor/ekspor posisi memiliki masalah kelas dasar rapuh klasik yang telah dirasakan secara nyata dalam sistem komponen seperti COM yang didasarkan pada tata letak (posisi) C++ vtable.

Sekarang, jika saya mengerti apa yang @RossTate dan @titzer usulkan, ini adalah masalah yang harus diselesaikan di lapisan Host, memungkinkan Host untuk memperkenalkan nama yang sesuai untuk Host itu . Masalah yang saya lihat tetap dengan jawaban itu adalah bahwa ia secara inheren mempartisi ekosistem perkakas wasm oleh Host. Misalnya, sekarang saya tidak bisa hanya memiliki "clang penargetan wasm" jika dentang ingin melakukan segala bentuk penautan (misalnya, untuk memfaktorkan libc (yang merupakan optimasi penting dalam kategori yang muncul dari sangat- platform eksekusi wasm multi-modul)) -- Saya perlu mengajari dentang tentang semua host konkret berbeda yang ditargetkan dan menjadikan Host sebagai parameter untuk dentang. Terlebih lagi, sekarang output yang dihasilkan hanya dapat dijalankan pada host tersebut, mencegah kemampuan untuk menghasilkan modul .wasm yang dapat digunakan kembali di seluruh host. Untuk mencapai alat bersama dan modul yang dapat digunakan kembali, kami memerlukan beberapa jenis target kompilasi abstrak umum yang berbicara tentang penautan (terutama yang tidak mengasumsikan hubungan 1: 1 antara nama dan instance, yang tidak cukup untuk sejumlah kasus penggunaan )) -- yang persis seperti yang diharapkan oleh proposal Penghubung Modul.

Karena itu, saya dapat membayangkan solusi hibrida di mana Penautan Modul ditambahkan sebagai lapisan spesifikasi host-agnostik di atas wasm inti dan di bawah JS API. Ini akan memungkinkan alat dan modul host-agnostik diproduksi (menargetkan lapisan spesifikasi host-agnostik ini) sementara memungkinkan penyematan host untuk mengesampingkan lapisan ini sama sekali, membuat instance modul inti secara langsung dengan skema penautan khusus.

Apakah itu terdengar seperti cara yang masuk akal untuk menyelesaikan tujuan yang saling bertentangan ini?

Terima kasih, @lukewagner , telah mendukung saya! Apa yang Anda katakan terdengar seperti pemahaman yang lebih akurat tentang dari mana saya berasal, dan pada saat yang sama saya mendengar kekhawatiran Anda tentang kerapuhan dan perkakas/ekosistem juga.

Saya pikir solusi hibrida/dua lapis adalah apa yang saya coba sarankan, di mana dua lapisan sesuai dengan tautan "internal" dan "eksternal". Tautan internal akan bersifat posisional dan menentukan instruksi untuk membangun/menghubungkan/membuat instance modul—itulah yang harus diterapkan oleh setiap mesin WebAssembly (dengan penautan modul). Menghubungkan eksternal akan embedder-spesifik dan menentukan bagaimana membangun (posisi) modul dari file lain dan sejenisnya, misalnya bergaul nama file dan / atau nama string untuk impor / ekspor-hal yang WebAssembly embedders harus melaksanakan. Pemisahan masalah ini akan mempermudah penggunaan kembali aspek "inti" dari program WebAssembly dan aspek "inti" dari mesin WebAssembly di berbagai ekosistem. (Saya juga berpikir pemisahan ini berpotensi membersihkan aspek penautan modul internal.)

Tetapi, seperti yang Anda sebutkan, memiliki dua penyesuaian "eksternal" yang banyak dapat menyebabkan keretakan yang parah. Jadi, sementara saya pikir tautan "internal" dan "eksternal" harus dipisahkan, menurut saya juga berguna untuk memiliki standar tautan eksternal "umum". Beberapa mungkin mengembangkan sistem tautan eksternal yang lebih khusus agar lebih cocok dengan atau mengambil keuntungan lebih dari spesifikasi ekosistem tertentu (menggunakan alat yang lebih khusus untuk melakukannya), tetapi banyak kebutuhan program akan sesuai dengan standar umum yang sederhana.

Jadi, untuk meringkas, saya pikir harus ada satu sistem penghubung "internal" (tingkat rendah, misalnya posisional), dan harus ada potensi untuk beberapa sistem penghubung "eksternal" yang berada di atasnya, tetapi dengan satu " umum" standar sistem tersebut di tempat. Apakah itu masuk akal? (Sayangnya, semua ini tidak berbicara tentang masalah impor duplikat saat ini, tetapi setidaknya mencoba untuk mengkarakterisasi di mana dalam ruang ini masalah itu berada, jika itu masuk akal.)

Oke, jadi pikirkan tentang apa arti perubahan semacam ini secara konkret dalam jangka pendek: membingkai ulang Module Linking sebagai lapisan "tautan umum" di atas spesifikasi inti (dan, jika kita mau, di bawah spesifikasi JS/Web) dapat berarti bahwa kita tidak perlu menambahkan apa pun ke spesifikasi inti sama sekali. Secara khusus, impor/ekspor modul inti dapat tetap pada posisi tertentu, sehingga lapisan Penautan Modul sepenuhnya mengabaikan nama-nama ini saat melakukan instantiasi. Berdasarkan itu, kita dapat menutup masalah ini dengan jawaban "Tidak", dalam hal ini, saya akan membahas poin "" , "a" , "b" , "c" ... mengekspor nama hanya untuk memenuhi validasi.

(Di masa depan, kita dapat berbicara tentang memperluas inti wasm dengan versi modul/instance posisional, tetapi saya tidak berpikir itu akan menjadi tambahan yang diperlukan untuk rangkaian awal kasus penggunaan dan persyaratan yang difokuskan oleh proposal Penautan Modul.)

@rossberg @titzer @tlively Pikiran?

Saya khawatir bahwa kodifikasi bahwa impor dan ekspor Wasm inti harus benar-benar posisional akan menutup pintu di https://github.com/WebAssembly/gc/issues/148 , yang menyarankan memperkenalkan mekanisme importexport baru untuk menyelesaikan masalah impor dan ekspor tentu menjadi asimetris. Mekanisme yang disarankan pada dasarnya memperkenalkan hubungan tipe yang lemah pada tingkat Wasm inti, dan saya tidak yakin bagaimana itu bisa bekerja secara posisional tanpa pengidentifikasi string.

Jelas ini hipotetis karena tidak ada konsensus untuk memindahkan proposal GC ke arah itu, tetapi saya pribadi merasa bahwa itu adalah opsi yang cukup menarik untuk proposal GC sehingga saya akan sedih melihatnya dibuat kurang layak oleh perkembangan yang tidak terkait seperti ini. sekarang. Apakah saya melewatkan cara agar perubahan yang diusulkan itu berfungsi secara posisional atau salah memahami masalah ini?

Ah, koneksi yang menarik, @tlively! Itu membuat saya memikirkan beberapa ide.

Satu ide relevan dengan penautan statis. Sama seperti impor bernama membantu dengan perubahan modul yang ditautkan secara eksternal, begitu juga impor default (seperti halnya dengan parameter bernama dan default untuk fungsi). Impor default memungkinkan untuk menambahkan opsi konfigurasi baru ke modul tanpa merusak kompatibilitas mundur. Dalam pendekatan penautan dua tingkat, di lapisan internal saya akan menyatakan ini sebagai dua modul (modul A memiliki impor dan modul B memiliki ekspor), dan di lapisan eksternal semantiknya adalah "jika diberikan argumen untuk impor ini , tautkan argumen itu ke A, jika tidak tautkan B ke A" sehingga B, yang mendefinisikan nilai default, hanya digunakan saat dibutuhkan.

Gagasan lain relevan dengan penautan dinamis. Di sini string digunakan sebagai kunci global. importexport pada dasarnya mengatakan "impor nilai yang terkait dengan kunci ini, dan jika nilai itu belum ditentukan, maka daftarkan secara global yang berikut sebagai nilai yang sesuai dengan kunci itu". (Sekali lagi, ini semua ada di lapisan tautan eksternal.)

Meskipun WebAssemby/gc#148 adalah tentang tipe nominal, saya perhatikan bahwa kedua ide di atas juga berlaku untuk pengecualian. Untuk penautan statis, saya berharap pola umum untuk sebuah modul adalah mengimpor peristiwa pengecualian yang secara default baru dibuat tetapi yang dapat dipakai untuk menggunakan peristiwa yang sama dengan modul lain (contoh?) untuk berbagi kontrol non-lokal dengan mereka. Untuk penautan dinamis, jika seseorang benar-benar ingin tidak ada modul run-time pusat (yang sudah diketahui orang tentang pemikiran saya), maka bahasa apa pun dengan pengecualian perlu mengoordinasikan peristiwa pengecualian di seluruh modul yang ditautkan secara dinamis dan importexport semantik tautan eksternal adalah cara yang baik untuk mencapai itu.

Rapi! Jika saya mengerti dengan benar, mekanisme importexport dapat dianggap sebagai bagian dari lapisan penautan modul yang berfungsi untuk mengimpor dan mengekspor posisi dengan secara implisit membuat modul ekspor "default" untuk mengimpor tipe yang ditentukan. Itu tampaknya masuk akal bagi saya, jadi saya tidak memiliki kekhawatiran lebih lanjut tentang arah ini.

Saya pikir argumen layering memotong dua arah. Anda juga dapat berargumen bahwa seharusnya menjadi tanggung jawab lapisan yang lebih tinggi untuk memetakan skema pasangan apa pun (nama tingkat tinggi, info tambahan) yang mereka gunakan untuk menyamarkan im/ekspor ke skema nama tingkat rendah yang tidak ambigu.

Untuk tingkat yang lebih rendah, tampaknya selalu lebih baik untuk menjadi sejelas dan sejelas mungkin. Hal ini membuat sistem dan antarmukanya tetap sederhana -- dan menempatkan beban untuk berurusan dengan skema yang lebih rumit pada ekosistem yang menginginkannya, daripada semua orang.

Adapun proposal penautan sebagai lapisan terpisah, kedengarannya bagus secara abstrak, tetapi saya agak skeptis bahwa kami dapat membuatnya bekerja dengan lancar. Misalnya, proposal saat ini memungkinkan modul dalam untuk merujuk ke ruang nama luar untuk entitas statis seperti modul atau tipe, yang tampaknya agak sentral, dan tidak dapat dipetakan ke spesifikasi inti (kecuali dengan transformasi yang setara dengan pengangkatan lambda, yang akan merusak pola komposisi yang dimaksud, kecuali jika kami juga memperkenalkan aplikasi/instansiasi impor sebagian, yaitu, suatu bentuk "penutupan modul").

Misalnya, proposal saat ini memungkinkan modul dalam untuk merujuk ke ruang nama luar untuk entitas statis seperti modul atau tipe

Ini adalah salah satu aspek yang saya rasa bisa menggunakan beberapa penyederhanaan.

kecuali jika kami juga memperkenalkan aplikasi/instansiasi impor sebagian, yaitu, suatu bentuk "penutupan modul"

Ini adalah salah satu teknik yang saya pikir dapat membantu mencapai penyederhanaan itu.

Saya biasanya mendukung gagasan untuk memindahkan spesifikasi penautan ke atas lapisan; itu pada dasarnya apa yang saya telah berdebat untuk. Mesin tidak perlu tahu nama.

@rossberg Saya biasanya berpikir bahwa "jelas dan tidak ambigu" bagus untuk lapisan bawah, tetapi contoh ini lebih tentang apakah akan preskriptif atau tidak, dan lapisan bawah harus melakukannya dengan baik untuk tidak preskriptif tentang hal-hal yang tidak menyangkut mereka, IMO.

Ada pengamatan terkait di https://github.com/WebAssembly/design/issues/1399#issuecomment -808401005 , di mana masalah tersebut menjelaskan masalah dengan panggilan yang gagal saat memanggil ekspor Wasm dengan argumen i64 dihilangkan, di yang memungkinkan ekspor duplikat dan memilih yang dengan arity yang cocok saat memanggil dari JS ke Wasm, akan menjadi solusi yang lebih disukai dalam konteks.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

chicoxyzzy picture chicoxyzzy  ·  5Komentar

JimmyVV picture JimmyVV  ·  4Komentar

nikhedonia picture nikhedonia  ·  7Komentar

jfbastien picture jfbastien  ·  6Komentar

aaabbbcccddd00001111 picture aaabbbcccddd00001111  ·  3Komentar