diff --git a/CHANGELOG.md b/CHANGELOG.md index a79c532a..708d96ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changed +- Incremental support for Component Model async types `stream` and `future`. - Dropped support for TinyGo v0.32.0. ## [v0.5.0] — 2024-12-14 diff --git a/internal/wasmtools/Cargo.lock b/internal/wasmtools/Cargo.lock index f8349ee9..9d42ac8b 100644 --- a/internal/wasmtools/Cargo.lock +++ b/internal/wasmtools/Cargo.lock @@ -131,12 +131,34 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "comfy-table" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f165e7b643266ea80cb858aed492ad9280e3e05ce24d4a99d7d7b889b6a4d9" +dependencies = [ + "strum", + "strum_macros", + "unicode-width", +] + [[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_filter" version = "0.1.2" @@ -194,6 +216,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "gimli" version = "0.30.0" @@ -226,17 +257,156 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "id-arena" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -273,6 +443,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "log" version = "0.4.22" @@ -291,6 +467,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pretty_assertions" version = "1.4.1" @@ -361,6 +543,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + [[package]] name = "ryu" version = "1.0.18" @@ -435,6 +623,25 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "2.0.89" @@ -446,6 +653,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tempfile" version = "3.14.0" @@ -478,6 +696,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "unicode-ident" version = "1.0.14" @@ -496,6 +724,29 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -504,9 +755,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wasm-encoder" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de35b6c3ef1f53ac7a31b5e69bc00f1542ea337e7e7162dc34c68b537ff82690" +checksum = "3432682105d7e994565ef928ccf5856cf6af4ba3dddebedb737f61caed70f956" dependencies = [ "leb128", "wasmparser", @@ -514,9 +765,9 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fca0d366d1be722f23e9e918e3b926945b21343424bb7a56e845beed82377bf" +checksum = "5eb09677e9412cb0dca2fec2cfdb49e5dfe8d82bf869c6d031bdf2ab73324f9d" dependencies = [ "anyhow", "indexmap", @@ -524,18 +775,20 @@ dependencies = [ "serde_derive", "serde_json", "spdx", + "url", "wasm-encoder", "wasmparser", ] [[package]] name = "wasm-tools" -version = "1.221.0" +version = "1.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f493321aefc926ad54a0c60859eafd3a426418b41132f6bbe0148f816cdd0735" +checksum = "4a7442163a6c96b467166438054d2ede9895f45b885cd2333b3523ac7817432d" dependencies = [ "anyhow", "clap", + "comfy-table", "env_logger", "log", "serde_json", @@ -560,9 +813,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8659e755615170cfe20da468865c989da78c5da16d8652e69a75acda02406a92" +checksum = "4adf50fde1b1a49c1add6a80d47aea500c88db70551805853aa8b88f3ea27ab5" dependencies = [ "bitflags", "hashbrown", @@ -572,9 +825,9 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4234d0682f373b1878cefd5b3d99843312478ee4f603b2cea34cc2135f0a65" +checksum = "1ba6d67c6ccf1c6771f167c682510fd1cb8e1f252d2641ec4143e6d9ddda4ec8" dependencies = [ "anyhow", "termcolor", @@ -583,9 +836,9 @@ dependencies = [ [[package]] name = "wast" -version = "221.0.0" +version = "222.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d8eb1933d493dd07484a255c3f52236123333f5befaa3be36182a50d393ec54" +checksum = "5ce7191f4b7da0dd300cc32476abae6457154e4625d9b1bc26890828a9a26f6e" dependencies = [ "bumpalo", "gimli", @@ -597,9 +850,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.221.0" +version = "1.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c813fd4e5b2b97242830b56e7b7dc5479bc17aaa8730109be35e61909af83993" +checksum = "8fde61b4b52f9a84ae31b5e8902a2cd3162ea45d8bf564c729c3288fe52f4334" dependencies = [ "wast", ] @@ -697,9 +950,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "wit-component" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6af482af5d64ecae38fe2cbd973c2fda25c4ce6d1cc2abc71c2f3ea81838ed" +checksum = "a7ce0f2820a7fdca09e9a0cbbd39513abf2d722479b28c73d81bccd61bb21499" dependencies = [ "anyhow", "bitflags", @@ -718,9 +971,9 @@ dependencies = [ [[package]] name = "wit-encoder" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c7064427baef19f7645f4e18f30437b3d1946a1e1cd17d0f9f37d4984cf12" +checksum = "00cbdaefdbe242f1080bd821293c0d720d960b2ed0c1f2f0312eb28d4e821b4c" dependencies = [ "id-arena", "pretty_assertions", @@ -731,9 +984,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.221.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f5b0a971faff0855a827ef06b25528263a718907bed4056992382316f1e68e" +checksum = "533abd14901514db88e4107655345fdd8ab8a72fb61e85d871bd361509744c35" dependencies = [ "anyhow", "id-arena", @@ -748,8 +1001,87 @@ dependencies = [ "wat", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "yansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/internal/wasmtools/Cargo.toml b/internal/wasmtools/Cargo.toml index 0def84af..35dfd22a 100644 --- a/internal/wasmtools/Cargo.toml +++ b/internal/wasmtools/Cargo.toml @@ -3,7 +3,7 @@ name = 'wasm-tools-go' edition = '2021' [dependencies] -wasm-tools = { version = '1.221.0', default-features = false, features = [ +wasm-tools = { version = '1.222.0', default-features = false, features = [ 'component', ] } diff --git a/internal/wasmtools/wasm-tools.wasm.gz b/internal/wasmtools/wasm-tools.wasm.gz index 928f430e..c11dd708 100644 Binary files a/internal/wasmtools/wasm-tools.wasm.gz and b/internal/wasmtools/wasm-tools.wasm.gz differ diff --git a/testdata/wasi/clocks-imports.wit.json.golden.wit b/testdata/wasi/clocks-imports.wit.json.golden.wit index d4d75c07..dfb81a43 100644 --- a/testdata/wasi/clocks-imports.wit.json.golden.wit +++ b/testdata/wasi/clocks-imports.wit.json.golden.wit @@ -1,92 +1,94 @@ -package wasi:clocks@0.2.0; +package wasi:cli@0.2.0; -/// WASI Monotonic Clock is a clock API intended to let users measure elapsed -/// time. -/// -/// It is intended to be portable at least between Unix-family platforms and -/// Windows. -/// -/// A monotonic clock is a clock which has an unspecified initial value, and -/// successive reads of the clock will produce non-decreasing values. -/// -/// It is intended for measuring elapsed time. -interface monotonic-clock { - use wasi:io/poll@0.2.0.{pollable}; - - /// An instant in time, in nanoseconds. An instant is relative to an - /// unspecified initial value, and can only be compared to instances from - /// the same monotonic-clock. - type instant = u64; +package wasi:clocks@0.2.0 { + /// WASI Monotonic Clock is a clock API intended to let users measure elapsed + /// time. + /// + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. + /// + /// A monotonic clock is a clock which has an unspecified initial value, and + /// successive reads of the clock will produce non-decreasing values. + /// + /// It is intended for measuring elapsed time. + interface monotonic-clock { + use wasi:io/poll@0.2.0.{pollable}; - /// A duration of time, in nanoseconds. - type duration = u64; + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + type instant = u64; - /// Read the current value of the clock. - /// - /// The clock is monotonic, therefore calling this function repeatedly will - /// produce a sequence of non-decreasing values. - now: func() -> instant; + /// A duration of time, in nanoseconds. + type duration = u64; - /// Query the resolution of the clock. Returns the duration of time - /// corresponding to a clock tick. - resolution: func() -> duration; + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + now: func() -> instant; - /// Create a `pollable` which will resolve once the specified instant - /// occured. - subscribe-instant: func(when: instant) -> pollable; + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + resolution: func() -> duration; - /// Create a `pollable` which will resolve once the given duration has - /// elapsed, starting at the time at which this function was called. - /// occured. - subscribe-duration: func(when: duration) -> pollable; -} + /// Create a `pollable` which will resolve once the specified instant + /// occured. + subscribe-instant: func(when: instant) -> pollable; -/// WASI Wall Clock is a clock API intended to let users query the current -/// time. The name "wall" makes an analogy to a "clock on the wall", which -/// is not necessarily monotonic as it may be reset. -/// -/// It is intended to be portable at least between Unix-family platforms and -/// Windows. -/// -/// A wall clock is a clock which measures the date and time according to -/// some external reference. -/// -/// External references may be reset, so this clock is not necessarily -/// monotonic, making it unsuitable for measuring elapsed time. -/// -/// It is intended for reporting the current date and time for humans. -interface wall-clock { - /// A time and date in seconds plus nanoseconds. - record datetime { - seconds: u64, - nanoseconds: u32, + /// Create a `pollable` which will resolve once the given duration has + /// elapsed, starting at the time at which this function was called. + /// occured. + subscribe-duration: func(when: duration) -> pollable; } - /// Read the current value of the clock. + /// WASI Wall Clock is a clock API intended to let users query the current + /// time. The name "wall" makes an analogy to a "clock on the wall", which + /// is not necessarily monotonic as it may be reset. /// - /// This clock is not monotonic, therefore calling this function repeatedly - /// will not necessarily produce a sequence of non-decreasing values. + /// It is intended to be portable at least between Unix-family platforms and + /// Windows. /// - /// The returned timestamps represent the number of seconds since - /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], - /// also known as [Unix Time]. + /// A wall clock is a clock which measures the date and time according to + /// some external reference. /// - /// The nanoseconds field of the output is always less than 1000000000. + /// External references may be reset, so this clock is not necessarily + /// monotonic, making it unsuitable for measuring elapsed time. /// - /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 - /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time - now: func() -> datetime; + /// It is intended for reporting the current date and time for humans. + interface wall-clock { + /// A time and date in seconds plus nanoseconds. + record datetime { + seconds: u64, + nanoseconds: u32, + } - /// Query the resolution of the clock. - /// - /// The nanoseconds field of the output is always less than 1000000000. - resolution: func() -> datetime; -} + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + now: func() -> datetime; -world imports { - import wasi:io/poll@0.2.0; - import monotonic-clock; - import wall-clock; + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + resolution: func() -> datetime; + } + + world imports { + import wasi:io/poll@0.2.0; + import monotonic-clock; + import wall-clock; + } } package wasi:io@0.2.0 { diff --git a/testdata/wit-parser/comments.wit.json b/testdata/wit-parser/comments.wit.json index f2a04f9d..7c7a44e1 100644 --- a/testdata/wit-parser/comments.wit.json +++ b/testdata/wit-parser/comments.wit.json @@ -27,10 +27,7 @@ { "name": "bar", "kind": { - "stream": { - "element": 0, - "end": null - } + "stream": 0 }, "owner": { "interface": 0 diff --git a/testdata/wit-parser/feature-types.wit.json b/testdata/wit-parser/feature-types.wit.json new file mode 100644 index 00000000..e8e5263a --- /dev/null +++ b/testdata/wit-parser/feature-types.wit.json @@ -0,0 +1,70 @@ +{ + "worlds": [], + "interfaces": [ + { + "name": "foo", + "types": { + "bar": 0 + }, + "functions": { + "my-stable": { + "name": "my-stable", + "kind": "freestanding", + "params": [ + { + "name": "p", + "type": 0 + } + ], + "results": [ + { + "type": 1 + } + ] + } + }, + "package": 0 + } + ], + "types": [ + { + "name": "bar", + "kind": { + "variant": { + "cases": [ + { + "name": "x", + "type": null + }, + { + "name": "y", + "type": null + } + ] + } + }, + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "result": { + "ok": null, + "err": 0 + } + }, + "owner": null + } + ], + "packages": [ + { + "name": "a:b", + "interfaces": { + "foo": 0 + }, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/feature-types.wit.json.golden.wit b/testdata/wit-parser/feature-types.wit.json.golden.wit new file mode 100644 index 00000000..077f3d30 --- /dev/null +++ b/testdata/wit-parser/feature-types.wit.json.golden.wit @@ -0,0 +1,6 @@ +package a:b; + +interface foo { + variant bar { x, y } + my-stable: func(p: bar) -> result<_, bar>; +} diff --git a/testdata/wit-parser/foreign-deps-union.wit.json b/testdata/wit-parser/foreign-deps-union.wit.json index 419d62e7..a6b2d44a 100644 --- a/testdata/wit-parser/foreign-deps-union.wit.json +++ b/testdata/wit-parser/foreign-deps-union.wit.json @@ -3,31 +3,31 @@ { "name": "wasi", "imports": { - "interface-8": { + "interface-5": { "interface": { - "id": 8 + "id": 5 } }, - "interface-7": { + "interface-4": { "interface": { - "id": 7 + "id": 4 } } }, "exports": {}, - "package": 5 + "package": 4 }, { "name": "my-world", "imports": { - "interface-8": { + "interface-5": { "interface": { - "id": 8 + "id": 5 } }, - "interface-7": { + "interface-4": { "interface": { - "id": 7 + "id": 4 } } }, @@ -43,14 +43,14 @@ { "name": "my-world2", "imports": { - "interface-8": { + "interface-5": { "interface": { - "id": 8 + "id": 5 } }, - "interface-7": { + "interface-4": { "interface": { - "id": 7 + "id": 4 } } }, @@ -71,9 +71,9 @@ { "name": "bars-world", "imports": { - "interface-4": { + "interface-6": { "interface": { - "id": 4 + "id": 6 } }, "interface-0": { @@ -88,14 +88,14 @@ { "name": "unionw-world", "imports": { - "interface-8": { + "interface-5": { "interface": { - "id": 8 + "id": 5 } }, - "interface-7": { + "interface-4": { "interface": { - "id": 7 + "id": 4 } } }, @@ -142,41 +142,41 @@ "package": 3 }, { - "name": "the-default", + "name": "clocks", "types": { - "from-default": 1 + "timestamp": 1 }, "functions": {}, "package": 4 }, { - "name": "some-interface", + "name": "filesystem", "types": { - "another-type": 2 + "stat": 2 }, "functions": {}, "package": 4 }, { - "name": "another-interface", + "name": "the-default", "types": { - "yet-another-type": 3 + "from-default": 3 }, "functions": {}, - "package": 4 + "package": 5 }, { - "name": "clocks", + "name": "some-interface", "types": { - "timestamp": 4 + "another-type": 4 }, "functions": {}, "package": 5 }, { - "name": "filesystem", + "name": "another-interface", "types": { - "stat": 5 + "yet-another-type": 5 }, "functions": {}, "package": 5 @@ -228,52 +228,52 @@ } }, { - "name": "from-default", + "name": "timestamp", "kind": { - "type": "string" + "type": "u64" }, "owner": { "interface": 4 } }, { - "name": "another-type", + "name": "stat", "kind": { - "type": "u32" + "record": { + "fields": [ + { + "name": "ino", + "type": "u64" + } + ] + } }, "owner": { "interface": 5 } }, { - "name": "yet-another-type", + "name": "from-default", "kind": { - "type": "u8" + "type": "string" }, "owner": { "interface": 6 } }, { - "name": "timestamp", + "name": "another-type", "kind": { - "type": "u64" + "type": "u32" }, "owner": { "interface": 7 } }, { - "name": "stat", + "name": "yet-another-type", "kind": { - "record": { - "fields": [ - { - "name": "ino", - "type": "u64" - } - ] - } + "type": "u8" }, "owner": { "interface": 8 @@ -282,7 +282,7 @@ { "name": "timestamp", "kind": { - "type": 4 + "type": 1 }, "owner": { "interface": 9 @@ -291,7 +291,7 @@ { "name": "stat", "kind": { - "type": 5 + "type": 2 }, "owner": { "interface": 9 @@ -300,7 +300,7 @@ { "name": "from-default", "kind": { - "type": 1 + "type": 3 }, "owner": { "interface": 10 @@ -309,7 +309,7 @@ { "name": "another-type", "kind": { - "type": 2 + "type": 4 }, "owner": { "interface": 10 @@ -318,7 +318,7 @@ { "name": "yet-another-type", "kind": { - "type": 3 + "type": 5 }, "owner": { "interface": 10 @@ -372,25 +372,25 @@ }, "worlds": {} }, - { - "name": "foo:some-pkg", - "interfaces": { - "the-default": 4, - "some-interface": 5, - "another-interface": 6 - }, - "worlds": {} - }, { "name": "foo:wasi", "interfaces": { - "clocks": 7, - "filesystem": 8 + "clocks": 4, + "filesystem": 5 }, "worlds": { "wasi": 0 } }, + { + "name": "foo:some-pkg", + "interfaces": { + "the-default": 6, + "some-interface": 7, + "another-interface": 8 + }, + "worlds": {} + }, { "name": "foo:root", "interfaces": { diff --git a/testdata/wit-parser/foreign-deps.wit.json b/testdata/wit-parser/foreign-deps.wit.json index 503c1b32..f24404d8 100644 --- a/testdata/wit-parser/foreign-deps.wit.json +++ b/testdata/wit-parser/foreign-deps.wit.json @@ -3,14 +3,14 @@ { "name": "my-world", "imports": { - "interface-8": { + "interface-5": { "interface": { - "id": 8 + "id": 5 } }, - "interface-7": { + "interface-4": { "interface": { - "id": 7 + "id": 4 } } }, @@ -26,14 +26,14 @@ { "name": "my-world2", "imports": { - "interface-8": { + "interface-5": { "interface": { - "id": 8 + "id": 5 } }, - "interface-7": { + "interface-4": { "interface": { - "id": 7 + "id": 4 } } }, @@ -54,9 +54,9 @@ { "name": "bars-world", "imports": { - "interface-4": { + "interface-6": { "interface": { - "id": 4 + "id": 6 } }, "interface-0": { @@ -97,41 +97,41 @@ "package": 3 }, { - "name": "the-default", + "name": "clocks", "types": { - "from-default": 1 + "timestamp": 1 }, "functions": {}, "package": 4 }, { - "name": "some-interface", + "name": "filesystem", "types": { - "another-type": 2 + "stat": 2 }, "functions": {}, "package": 4 }, { - "name": "another-interface", + "name": "the-default", "types": { - "yet-another-type": 3 + "from-default": 3 }, "functions": {}, - "package": 4 + "package": 5 }, { - "name": "clocks", + "name": "some-interface", "types": { - "timestamp": 4 + "another-type": 4 }, "functions": {}, "package": 5 }, { - "name": "filesystem", + "name": "another-interface", "types": { - "stat": 5 + "yet-another-type": 5 }, "functions": {}, "package": 5 @@ -183,52 +183,52 @@ } }, { - "name": "from-default", + "name": "timestamp", "kind": { - "type": "string" + "type": "u64" }, "owner": { "interface": 4 } }, { - "name": "another-type", + "name": "stat", "kind": { - "type": "u32" + "record": { + "fields": [ + { + "name": "ino", + "type": "u64" + } + ] + } }, "owner": { "interface": 5 } }, { - "name": "yet-another-type", + "name": "from-default", "kind": { - "type": "u8" + "type": "string" }, "owner": { "interface": 6 } }, { - "name": "timestamp", + "name": "another-type", "kind": { - "type": "u64" + "type": "u32" }, "owner": { "interface": 7 } }, { - "name": "stat", + "name": "yet-another-type", "kind": { - "record": { - "fields": [ - { - "name": "ino", - "type": "u64" - } - ] - } + "type": "u8" }, "owner": { "interface": 8 @@ -237,7 +237,7 @@ { "name": "timestamp", "kind": { - "type": 4 + "type": 1 }, "owner": { "interface": 9 @@ -246,7 +246,7 @@ { "name": "stat", "kind": { - "type": 5 + "type": 2 }, "owner": { "interface": 9 @@ -255,7 +255,7 @@ { "name": "from-default", "kind": { - "type": 1 + "type": 3 }, "owner": { "interface": 10 @@ -264,7 +264,7 @@ { "name": "another-type", "kind": { - "type": 2 + "type": 4 }, "owner": { "interface": 10 @@ -273,7 +273,7 @@ { "name": "yet-another-type", "kind": { - "type": 3 + "type": 5 }, "owner": { "interface": 10 @@ -328,19 +328,19 @@ "worlds": {} }, { - "name": "foo:some-pkg", + "name": "foo:wasi", "interfaces": { - "the-default": 4, - "some-interface": 5, - "another-interface": 6 + "clocks": 4, + "filesystem": 5 }, "worlds": {} }, { - "name": "foo:wasi", + "name": "foo:some-pkg", "interfaces": { - "clocks": 7, - "filesystem": 8 + "the-default": 6, + "some-interface": 7, + "another-interface": 8 }, "worlds": {} }, diff --git a/testdata/wit-parser/multi-file-multi-package.wit.json b/testdata/wit-parser/multi-file-multi-package.wit.json index a2dea317..2d0132c8 100644 --- a/testdata/wit-parser/multi-file-multi-package.wit.json +++ b/testdata/wit-parser/multi-file-multi-package.wit.json @@ -49,7 +49,7 @@ } }, "exports": {}, - "package": 2 + "package": 3 }, { "name": "w4", @@ -66,7 +66,7 @@ } }, "exports": {}, - "package": 3 + "package": 4 } ], "interfaces": [ @@ -108,7 +108,7 @@ "a": 4 }, "functions": {}, - "package": 2 + "package": 3 }, { "name": null, @@ -116,7 +116,7 @@ "a": 5 }, "functions": {}, - "package": 2 + "package": 3 }, { "name": "i4", @@ -124,7 +124,7 @@ "b": 6 }, "functions": {}, - "package": 3 + "package": 4 }, { "name": null, @@ -132,7 +132,7 @@ "b": 7 }, "functions": {}, - "package": 3 + "package": 4 } ], "types": [ @@ -228,6 +228,11 @@ "w3": 1 } }, + { + "name": "foo:main", + "interfaces": {}, + "worlds": {} + }, { "name": "foo:name", "interfaces": { diff --git a/testdata/wit-parser/multi-file-multi-package.wit.json.golden.wit b/testdata/wit-parser/multi-file-multi-package.wit.json.golden.wit index fe2bb026..15be1010 100644 --- a/testdata/wit-parser/multi-file-multi-package.wit.json.golden.wit +++ b/testdata/wit-parser/multi-file-multi-package.wit.json.golden.wit @@ -24,6 +24,8 @@ package baz:name { } } +package foo:main {} + package foo:name { interface i1 { type a = u32; diff --git a/testdata/wit-parser/multi-package-deps.wit.json b/testdata/wit-parser/multi-package-deps.wit.json new file mode 100644 index 00000000..427c1bdf --- /dev/null +++ b/testdata/wit-parser/multi-package-deps.wit.json @@ -0,0 +1,161 @@ +{ + "worlds": [], + "interfaces": [ + { + "name": "i2", + "types": { + "t": 0 + }, + "functions": {}, + "package": 0 + }, + { + "name": "i1", + "types": { + "t": 1, + "o": 2 + }, + "functions": {}, + "package": 1 + }, + { + "name": "nesty", + "types": { + "o": 3, + "l": 4 + }, + "functions": {}, + "package": 2 + }, + { + "name": "i0", + "types": { + "o": 5, + "l": 6, + "r": 7, + "r1": 8 + }, + "functions": {}, + "package": 3 + } + ], + "types": [ + { + "name": "t", + "kind": { + "type": "string" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "t", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + }, + { + "name": "o", + "kind": { + "option": 1 + }, + "owner": { + "interface": 1 + } + }, + { + "name": "o", + "kind": { + "type": 2 + }, + "owner": { + "interface": 2 + } + }, + { + "name": "l", + "kind": { + "list": 3 + }, + "owner": { + "interface": 2 + } + }, + { + "name": "o", + "kind": { + "type": 2 + }, + "owner": { + "interface": 3 + } + }, + { + "name": "l", + "kind": { + "type": 4 + }, + "owner": { + "interface": 3 + } + }, + { + "name": "r", + "kind": { + "result": { + "ok": 5, + "err": null + } + }, + "owner": { + "interface": 3 + } + }, + { + "name": "r1", + "kind": { + "result": { + "ok": 6, + "err": null + } + }, + "owner": { + "interface": 3 + } + } + ], + "packages": [ + { + "name": "foo:dep2", + "interfaces": { + "i2": 0 + }, + "worlds": {} + }, + { + "name": "foo:dep1", + "interfaces": { + "i1": 1 + }, + "worlds": {} + }, + { + "name": "foo:nest", + "interfaces": { + "nesty": 2 + }, + "worlds": {} + }, + { + "name": "foo:root", + "interfaces": { + "i0": 3 + }, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/multi-package-deps.wit.json.golden.wit b/testdata/wit-parser/multi-package-deps.wit.json.golden.wit new file mode 100644 index 00000000..ff6d0b24 --- /dev/null +++ b/testdata/wit-parser/multi-package-deps.wit.json.golden.wit @@ -0,0 +1,28 @@ +package foo:root; + +interface i0 { + use foo:dep1/i1.{o}; + use foo:nest/nesty.{l}; + type r = result; + type r1 = result; +} + +package foo:nest { + interface nesty { + use foo:dep1/i1.{o}; + type l = list; + } +} + +package foo:dep1 { + interface i1 { + use foo:dep2/i2.{t}; + type o = option; + } +} + +package foo:dep2 { + interface i2 { + type t = string; + } +} diff --git a/testdata/wit-parser/multi-package-shared-deps.wit.json b/testdata/wit-parser/multi-package-shared-deps.wit.json index d3434da0..8076d195 100644 --- a/testdata/wit-parser/multi-package-shared-deps.wit.json +++ b/testdata/wit-parser/multi-package-shared-deps.wit.json @@ -38,18 +38,185 @@ "interfaces": [ { "name": "types", - "types": {}, + "types": { + "type1": 0 + }, "functions": {}, "package": 0 }, { "name": "types", - "types": {}, + "types": { + "type2": 1 + }, "functions": {}, "package": 1 + }, + { + "name": "i0", + "types": { + "type1": 2, + "type2": 3, + "rec0": 4 + }, + "functions": {}, + "package": 2 + }, + { + "name": "i1", + "types": { + "type1": 5, + "type2": 6, + "rec1": 7 + }, + "functions": {}, + "package": 3 + }, + { + "name": "root", + "types": { + "rec0": 8, + "rec1": 9, + "rec": 10 + }, + "functions": {}, + "package": 4 + } + ], + "types": [ + { + "name": "type1", + "kind": { + "type": "string" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "type2", + "kind": { + "type": "string" + }, + "owner": { + "interface": 1 + } + }, + { + "name": "type1", + "kind": { + "type": 0 + }, + "owner": { + "interface": 2 + } + }, + { + "name": "type2", + "kind": { + "type": 1 + }, + "owner": { + "interface": 2 + } + }, + { + "name": "rec0", + "kind": { + "record": { + "fields": [ + { + "name": "foo", + "type": 2 + }, + { + "name": "bar", + "type": 3 + } + ] + } + }, + "owner": { + "interface": 2 + } + }, + { + "name": "type1", + "kind": { + "type": 0 + }, + "owner": { + "interface": 3 + } + }, + { + "name": "type2", + "kind": { + "type": 1 + }, + "owner": { + "interface": 3 + } + }, + { + "name": "rec1", + "kind": { + "record": { + "fields": [ + { + "name": "foo", + "type": 5 + }, + { + "name": "bar", + "type": 6 + } + ] + } + }, + "owner": { + "interface": 3 + } + }, + { + "name": "rec0", + "kind": { + "type": 4 + }, + "owner": { + "interface": 4 + } + }, + { + "name": "rec1", + "kind": { + "type": 7 + }, + "owner": { + "interface": 4 + } + }, + { + "name": "rec", + "kind": { + "record": { + "fields": [ + { + "name": "first", + "type": 8 + }, + { + "name": "second", + "type": 9 + } + ] + } + }, + "owner": { + "interface": 4 + } } ], - "types": [], "packages": [ { "name": "foo:dep1", @@ -67,17 +234,28 @@ }, { "name": "foo:bar", - "interfaces": {}, + "interfaces": { + "i0": 2 + }, "worlds": { "w-bar": 0 } }, { "name": "foo:qux", - "interfaces": {}, + "interfaces": { + "i1": 3 + }, "worlds": { "w-qux": 1 } + }, + { + "name": "foo:root", + "interfaces": { + "root": 4 + }, + "worlds": {} } ] } \ No newline at end of file diff --git a/testdata/wit-parser/multi-package-shared-deps.wit.json.golden.wit b/testdata/wit-parser/multi-package-shared-deps.wit.json.golden.wit index 9aae55c0..181f354a 100644 --- a/testdata/wit-parser/multi-package-shared-deps.wit.json.golden.wit +++ b/testdata/wit-parser/multi-package-shared-deps.wit.json.golden.wit @@ -1,11 +1,31 @@ -package foo:bar; +package foo:root; -world w-bar { - import foo:dep1/types; - import foo:dep2/types; +interface root { + use foo:bar/i0.{rec0}; + use foo:qux/i1.{rec1}; + record rec { first: rec0, second: rec1 } +} + +package foo:bar { + interface i0 { + use foo:dep1/types.{type1}; + use foo:dep2/types.{type2}; + record rec0 { foo: type1, bar: type2 } + } + + world w-bar { + import foo:dep1/types; + import foo:dep2/types; + } } package foo:qux { + interface i1 { + use foo:dep1/types.{type1}; + use foo:dep2/types.{type2}; + record rec1 { foo: type1, bar: type2 } + } + world w-qux { import foo:dep1/types; import foo:dep2/types; @@ -13,9 +33,13 @@ package foo:qux { } package foo:dep1 { - interface types {} + interface types { + type type1 = string; + } } package foo:dep2 { - interface types {} + interface types { + type type2 = string; + } } diff --git a/testdata/wit-parser/multi-package-transitive-deps.wit.json b/testdata/wit-parser/multi-package-transitive-deps.wit.json index ece4cdad..ed79fcc0 100644 --- a/testdata/wit-parser/multi-package-transitive-deps.wit.json +++ b/testdata/wit-parser/multi-package-transitive-deps.wit.json @@ -12,10 +12,15 @@ "interface": { "id": 1 } + }, + "interface-2": { + "interface": { + "id": 2 + } } }, "exports": {}, - "package": 2 + "package": 3 }, { "name": "w-qux", @@ -24,17 +29,22 @@ "interface": { "id": 0 } + }, + "interface-1": { + "interface": { + "id": 1 + } } }, "exports": {}, - "package": 3 + "package": 4 } ], "interfaces": [ { "name": "types", "types": { - "a": 0 + "t2": 0 }, "functions": {}, "package": 0 @@ -42,23 +52,34 @@ { "name": "types", "types": { - "a": 1, - "r": 2 + "t2": 1, + "a": 2 }, "functions": {}, "package": 1 + }, + { + "name": "types", + "types": { + "a": 3, + "b": 4 + }, + "functions": {}, + "package": 2 } ], "types": [ { - "name": "a", - "kind": "resource", + "name": "t2", + "kind": { + "type": "string" + }, "owner": { "interface": 0 } }, { - "name": "a", + "name": "t2", "kind": { "type": 0 }, @@ -67,13 +88,13 @@ } }, { - "name": "r", + "name": "a", "kind": { "record": { "fields": [ { - "name": "f", - "type": "u8" + "name": "foo", + "type": 1 } ] } @@ -81,23 +102,55 @@ "owner": { "interface": 1 } + }, + { + "name": "a", + "kind": { + "type": 2 + }, + "owner": { + "interface": 2 + } + }, + { + "name": "b", + "kind": { + "record": { + "fields": [ + { + "name": "r", + "type": 3 + } + ] + } + }, + "owner": { + "interface": 2 + } } ], "packages": [ { - "name": "foo:dep2", + "name": "foo:nest", "interfaces": { "types": 0 }, "worlds": {} }, { - "name": "foo:dep1", + "name": "foo:dep2", "interfaces": { "types": 1 }, "worlds": {} }, + { + "name": "foo:dep1", + "interfaces": { + "types": 2 + }, + "worlds": {} + }, { "name": "foo:bar", "interfaces": {}, @@ -111,6 +164,11 @@ "worlds": { "w-qux": 1 } + }, + { + "name": "foo:root", + "interfaces": {}, + "worlds": {} } ] } \ No newline at end of file diff --git a/testdata/wit-parser/multi-package-transitive-deps.wit.json.golden.wit b/testdata/wit-parser/multi-package-transitive-deps.wit.json.golden.wit index d4e125ee..196d8700 100644 --- a/testdata/wit-parser/multi-package-transitive-deps.wit.json.golden.wit +++ b/testdata/wit-parser/multi-package-transitive-deps.wit.json.golden.wit @@ -1,6 +1,7 @@ package foo:bar; world w-bar { + import foo:nest/types; import foo:dep2/types; import foo:dep1/types; } @@ -8,18 +9,28 @@ world w-bar { package foo:dep1 { interface types { use foo:dep2/types.{a}; - record r { f: u8 } + record b { r: a } } } package foo:qux { world w-qux { + import foo:nest/types; import foo:dep2/types; } } package foo:dep2 { interface types { - resource a; + use foo:nest/types.{t2}; + record a { foo: t2 } } } + +package foo:nest { + interface types { + type t2 = string; + } +} + +package foo:root {} diff --git a/testdata/wit-parser/packages-multiple-nested.wit.json b/testdata/wit-parser/packages-multiple-nested.wit.json new file mode 100644 index 00000000..f2c8d6b0 --- /dev/null +++ b/testdata/wit-parser/packages-multiple-nested.wit.json @@ -0,0 +1,184 @@ +{ + "worlds": [ + { + "name": "w2", + "imports": { + "interface-0": { + "interface": { + "id": 0 + } + }, + "imp2": { + "interface": { + "id": 1 + } + } + }, + "exports": {}, + "package": 0 + }, + { + "name": "w1", + "imports": { + "interface-2": { + "interface": { + "id": 2 + } + }, + "imp1": { + "interface": { + "id": 3 + } + } + }, + "exports": {}, + "package": 1 + }, + { + "name": "w0", + "imports": { + "interface-2": { + "interface": { + "id": 2 + } + } + }, + "exports": { + "interface-4": { + "interface": { + "id": 4 + } + } + }, + "package": 2 + } + ], + "interfaces": [ + { + "name": "i2", + "types": { + "b": 0 + }, + "functions": {}, + "package": 0 + }, + { + "name": null, + "types": { + "b": 1 + }, + "functions": {}, + "package": 0 + }, + { + "name": "i1", + "types": { + "a": 2 + }, + "functions": {}, + "package": 1 + }, + { + "name": null, + "types": { + "a": 3 + }, + "functions": {}, + "package": 1 + }, + { + "name": "i0", + "types": { + "a": 4, + "c": 5 + }, + "functions": {}, + "package": 2 + } + ], + "types": [ + { + "name": "b", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "b", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + }, + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 2 + } + }, + { + "name": "a", + "kind": { + "type": 2 + }, + "owner": { + "interface": 3 + } + }, + { + "name": "a", + "kind": { + "type": 2 + }, + "owner": { + "interface": 4 + } + }, + { + "name": "c", + "kind": { + "option": 4 + }, + "owner": { + "interface": 4 + } + } + ], + "packages": [ + { + "name": "bar:name", + "interfaces": { + "i2": 0 + }, + "worlds": { + "w2": 0 + } + }, + { + "name": "foo:name", + "interfaces": { + "i1": 2 + }, + "worlds": { + "w1": 1 + } + }, + { + "name": "foo:root", + "interfaces": { + "i0": 4 + }, + "worlds": { + "w0": 2 + } + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/packages-multiple-nested.wit.json.golden.wit b/testdata/wit-parser/packages-multiple-nested.wit.json.golden.wit new file mode 100644 index 00000000..2cf3327b --- /dev/null +++ b/testdata/wit-parser/packages-multiple-nested.wit.json.golden.wit @@ -0,0 +1,37 @@ +package bar:name; + +interface i2 { + type b = u32; +} + +world w2 { + import i2; + import imp2: interface { + use i2.{b}; + } +} + +package foo:root { + interface i0 { + use foo:name/i1.{a}; + type c = option; + } + + world w0 { + import foo:name/i1; + export i0; + } +} + +package foo:name { + interface i1 { + type a = u32; + } + + world w1 { + import i1; + import imp1: interface { + use i1.{a}; + } + } +} diff --git a/testdata/wit-parser/packages-nested-colliding-decl-names.wit.json b/testdata/wit-parser/packages-nested-colliding-decl-names.wit.json new file mode 100644 index 00000000..3a9dc3b0 --- /dev/null +++ b/testdata/wit-parser/packages-nested-colliding-decl-names.wit.json @@ -0,0 +1,135 @@ +{ + "worlds": [ + { + "name": "w", + "imports": { + "interface-0": { + "interface": { + "id": 0 + } + }, + "imp": { + "interface": { + "id": 1 + } + } + }, + "exports": {}, + "package": 0 + }, + { + "name": "w", + "imports": { + "interface-2": { + "interface": { + "id": 2 + } + }, + "imp": { + "interface": { + "id": 3 + } + } + }, + "exports": {}, + "package": 1 + } + ], + "interfaces": [ + { + "name": "i", + "types": { + "a": 0 + }, + "functions": {}, + "package": 0 + }, + { + "name": null, + "types": { + "a": 1 + }, + "functions": {}, + "package": 0 + }, + { + "name": "i", + "types": { + "a": 2 + }, + "functions": {}, + "package": 1 + }, + { + "name": null, + "types": { + "a": 3 + }, + "functions": {}, + "package": 1 + } + ], + "types": [ + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "a", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + }, + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 2 + } + }, + { + "name": "a", + "kind": { + "type": 2 + }, + "owner": { + "interface": 3 + } + } + ], + "packages": [ + { + "name": "bar:name", + "interfaces": { + "i": 0 + }, + "worlds": { + "w": 0 + } + }, + { + "name": "foo:name", + "interfaces": { + "i": 2 + }, + "worlds": { + "w": 1 + } + }, + { + "name": "foo:root", + "interfaces": {}, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/packages-nested-colliding-decl-names.wit.json.golden.wit b/testdata/wit-parser/packages-nested-colliding-decl-names.wit.json.golden.wit new file mode 100644 index 00000000..0a65c6de --- /dev/null +++ b/testdata/wit-parser/packages-nested-colliding-decl-names.wit.json.golden.wit @@ -0,0 +1,27 @@ +package bar:name; + +interface i { + type a = u32; +} + +world w { + import i; + import imp: interface { + use i.{a}; + } +} + +package foo:name { + interface i { + type a = u32; + } + + world w { + import i; + import imp: interface { + use i.{a}; + } + } +} + +package foo:root {} diff --git a/testdata/wit-parser/packages-nested-internal-references.wit.json b/testdata/wit-parser/packages-nested-internal-references.wit.json new file mode 100644 index 00000000..0c26221a --- /dev/null +++ b/testdata/wit-parser/packages-nested-internal-references.wit.json @@ -0,0 +1,92 @@ +{ + "worlds": [ + { + "name": "w1", + "imports": { + "interface-0": { + "interface": { + "id": 0 + } + }, + "imp1": { + "interface": { + "id": 1 + } + } + }, + "exports": {}, + "package": 1 + } + ], + "interfaces": [ + { + "name": "i1", + "types": { + "a": 0 + }, + "functions": {}, + "package": 0 + }, + { + "name": null, + "types": { + "a": 1 + }, + "functions": { + "fn": { + "name": "fn", + "kind": "freestanding", + "params": [ + { + "name": "a", + "type": 1 + } + ], + "results": [] + } + }, + "package": 1 + } + ], + "types": [ + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "a", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + } + ], + "packages": [ + { + "name": "foo:name", + "interfaces": { + "i1": 0 + }, + "worlds": {} + }, + { + "name": "bar:name", + "interfaces": {}, + "worlds": { + "w1": 0 + } + }, + { + "name": "foo:root", + "interfaces": {}, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/packages-nested-internal-references.wit.json.golden.wit b/testdata/wit-parser/packages-nested-internal-references.wit.json.golden.wit new file mode 100644 index 00000000..4b5f308c --- /dev/null +++ b/testdata/wit-parser/packages-nested-internal-references.wit.json.golden.wit @@ -0,0 +1,17 @@ +package bar:name; + +world w1 { + import foo:name/i1; + import imp1: interface { + use foo:name/i1.{a}; + fn: func(a: a); + } +} + +package foo:name { + interface i1 { + type a = u32; + } +} + +package foo:root {} diff --git a/testdata/wit-parser/packages-nested-with-semver.wit.json b/testdata/wit-parser/packages-nested-with-semver.wit.json new file mode 100644 index 00000000..ecd0fe37 --- /dev/null +++ b/testdata/wit-parser/packages-nested-with-semver.wit.json @@ -0,0 +1,135 @@ +{ + "worlds": [ + { + "name": "w1", + "imports": { + "interface-0": { + "interface": { + "id": 0 + } + }, + "imp1": { + "interface": { + "id": 1 + } + } + }, + "exports": {}, + "package": 0 + }, + { + "name": "w1", + "imports": { + "interface-2": { + "interface": { + "id": 2 + } + }, + "imp1": { + "interface": { + "id": 3 + } + } + }, + "exports": {}, + "package": 1 + } + ], + "interfaces": [ + { + "name": "i1", + "types": { + "a": 0 + }, + "functions": {}, + "package": 0 + }, + { + "name": null, + "types": { + "a": 1 + }, + "functions": {}, + "package": 0 + }, + { + "name": "i1", + "types": { + "a": 2 + }, + "functions": {}, + "package": 1 + }, + { + "name": null, + "types": { + "a": 3 + }, + "functions": {}, + "package": 1 + } + ], + "types": [ + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "a", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + }, + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 2 + } + }, + { + "name": "a", + "kind": { + "type": 2 + }, + "owner": { + "interface": 3 + } + } + ], + "packages": [ + { + "name": "foo:name@1.0.0", + "interfaces": { + "i1": 0 + }, + "worlds": { + "w1": 0 + } + }, + { + "name": "foo:name@1.0.1", + "interfaces": { + "i1": 2 + }, + "worlds": { + "w1": 1 + } + }, + { + "name": "foo:root", + "interfaces": {}, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/packages-nested-with-semver.wit.json.golden.wit b/testdata/wit-parser/packages-nested-with-semver.wit.json.golden.wit new file mode 100644 index 00000000..2f649238 --- /dev/null +++ b/testdata/wit-parser/packages-nested-with-semver.wit.json.golden.wit @@ -0,0 +1,27 @@ +package foo:name@1.0.0; + +interface i1 { + type a = u32; +} + +world w1 { + import i1; + import imp1: interface { + use i1.{a}; + } +} + +package foo:name@1.0.1 { + interface i1 { + type a = u32; + } + + world w1 { + import i1; + import imp1: interface { + use i1.{a}; + } + } +} + +package foo:root {} diff --git a/testdata/wit-parser/packages-single-nested.wit.json b/testdata/wit-parser/packages-single-nested.wit.json new file mode 100644 index 00000000..c67c2a78 --- /dev/null +++ b/testdata/wit-parser/packages-single-nested.wit.json @@ -0,0 +1,75 @@ +{ + "worlds": [ + { + "name": "w1", + "imports": { + "interface-0": { + "interface": { + "id": 0 + } + }, + "imp1": { + "interface": { + "id": 1 + } + } + }, + "exports": {}, + "package": 0 + } + ], + "interfaces": [ + { + "name": "i1", + "types": { + "a": 0 + }, + "functions": {}, + "package": 0 + }, + { + "name": null, + "types": { + "a": 1 + }, + "functions": {}, + "package": 0 + } + ], + "types": [ + { + "name": "a", + "kind": { + "type": "u32" + }, + "owner": { + "interface": 0 + } + }, + { + "name": "a", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + } + ], + "packages": [ + { + "name": "foo:name", + "interfaces": { + "i1": 0 + }, + "worlds": { + "w1": 0 + } + }, + { + "name": "foo:root", + "interfaces": {}, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/packages-single-nested.wit.json.golden.wit b/testdata/wit-parser/packages-single-nested.wit.json.golden.wit new file mode 100644 index 00000000..f1eccb6e --- /dev/null +++ b/testdata/wit-parser/packages-single-nested.wit.json.golden.wit @@ -0,0 +1,14 @@ +package foo:name; + +interface i1 { + type a = u32; +} + +world w1 { + import i1; + import imp1: interface { + use i1.{a}; + } +} + +package foo:root {} diff --git a/testdata/wit-parser/streams-and-futures.wit.json b/testdata/wit-parser/streams-and-futures.wit.json new file mode 100644 index 00000000..a422a21a --- /dev/null +++ b/testdata/wit-parser/streams-and-futures.wit.json @@ -0,0 +1,199 @@ +{ + "worlds": [], + "interfaces": [ + { + "name": "streams-and-futures", + "types": { + "t1": 0, + "t2": 2, + "t3": 3, + "t4": 5, + "t5": 8, + "r1": 9, + "t6": 11, + "t7": 13 + }, + "functions": { + "foo": { + "name": "foo", + "kind": "freestanding", + "params": [ + { + "name": "x", + "type": 14 + }, + { + "name": "y", + "type": 11 + } + ], + "results": [ + { + "type": 17 + } + ] + } + }, + "package": 0 + } + ], + "types": [ + { + "name": "t1", + "kind": { + "stream": "u8" + }, + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "stream": "string" + }, + "owner": null + }, + { + "name": "t2", + "kind": { + "stream": 1 + }, + "owner": { + "interface": 0 + } + }, + { + "name": "t3", + "kind": { + "future": null + }, + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "list": "u8" + }, + "owner": null + }, + { + "name": "t4", + "kind": { + "future": 4 + }, + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "future": null + }, + "owner": null + }, + { + "name": null, + "kind": { + "stream": 6 + }, + "owner": null + }, + { + "name": "t5", + "kind": { + "option": 7 + }, + "owner": { + "interface": 0 + } + }, + { + "name": "r1", + "kind": "resource", + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "handle": { + "own": 9 + } + }, + "owner": null + }, + { + "name": "t6", + "kind": { + "stream": 10 + }, + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "result": { + "ok": 10, + "err": null + } + }, + "owner": null + }, + { + "name": "t7", + "kind": { + "future": 12 + }, + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "stream": "u32" + }, + "owner": null + }, + { + "name": null, + "kind": { + "list": "string" + }, + "owner": null + }, + { + "name": null, + "kind": { + "result": { + "ok": 15, + "err": "string" + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "future": 16 + }, + "owner": null + } + ], + "packages": [ + { + "name": "foo:streams-and-futures", + "interfaces": { + "streams-and-futures": 0 + }, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/streams-and-futures.wit.json.golden.wit b/testdata/wit-parser/streams-and-futures.wit.json.golden.wit new file mode 100644 index 00000000..537c8bea --- /dev/null +++ b/testdata/wit-parser/streams-and-futures.wit.json.golden.wit @@ -0,0 +1,13 @@ +package foo:streams-and-futures; + +interface streams-and-futures { + type t1 = stream; + type t2 = stream>; + type t3 = future; + type t4 = future>; + type t5 = option>; + resource r1; + type t6 = stream; + type t7 = future>; + foo: func(x: stream, y: t6) -> future, string>>; +} diff --git a/testdata/wit-parser/types.wit.json b/testdata/wit-parser/types.wit.json index 8874e354..1b5e70e5 100644 --- a/testdata/wit-parser/types.wit.json +++ b/testdata/wit-parser/types.wit.json @@ -53,11 +53,8 @@ "t48": 49, "t49": 50, "t50": 51, - "t51": 52, - "t52": 53, - "t53": 54, - "bar": 55, - "foo": 56 + "bar": 52, + "foo": 53 }, "functions": {}, "package": 0 @@ -677,10 +674,7 @@ { "name": "t48", "kind": { - "stream": { - "element": "u32", - "end": "u32" - } + "stream": "u32" }, "owner": { "interface": 0 @@ -688,42 +682,6 @@ }, { "name": "t49", - "kind": { - "stream": { - "element": null, - "end": "u32" - } - }, - "owner": { - "interface": 0 - } - }, - { - "name": "t50", - "kind": { - "stream": { - "element": "u32", - "end": null - } - }, - "owner": { - "interface": 0 - } - }, - { - "name": "t51", - "kind": { - "stream": { - "element": null, - "end": null - } - }, - "owner": { - "interface": 0 - } - }, - { - "name": "t52", "kind": { "future": "u32" }, @@ -732,7 +690,7 @@ } }, { - "name": "t53", + "name": "t50", "kind": { "future": null }, @@ -752,7 +710,7 @@ { "name": "foo", "kind": { - "type": 55 + "type": 52 }, "owner": { "interface": 0 diff --git a/testdata/wit-parser/types.wit.json.golden.wit b/testdata/wit-parser/types.wit.json.golden.wit index 199f2332..25cfb9f3 100644 --- a/testdata/wit-parser/types.wit.json.golden.wit +++ b/testdata/wit-parser/types.wit.json.golden.wit @@ -47,12 +47,9 @@ interface types { type t45 = list>>; type t46 = t44; type t47 = t44; - type t48 = stream; - type t49 = stream<_, u32>; - type t50 = stream; - type t51 = stream; - type t52 = future; - type t53 = future; + type t48 = stream; + type t49 = future; + type t50 = future; type bar = u32; /// type order doesn't matter diff --git a/testdata/wit-parser/version-syntax.wit.json b/testdata/wit-parser/version-syntax.wit.json new file mode 100644 index 00000000..a31d7153 --- /dev/null +++ b/testdata/wit-parser/version-syntax.wit.json @@ -0,0 +1,57 @@ +{ + "worlds": [], + "interfaces": [], + "types": [], + "packages": [ + { + "name": "a:b@1.0.0-11-a", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.0-11ab", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.0-a1.1-a", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.0", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.1-1+1", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.1--", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.1-1a+1a", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.1-a+a", + "interfaces": {}, + "worlds": {} + }, + { + "name": "a:b@1.0.1", + "interfaces": {}, + "worlds": {} + }, + { + "name": "foo:root", + "interfaces": {}, + "worlds": {} + } + ] +} \ No newline at end of file diff --git a/testdata/wit-parser/version-syntax.wit.json.golden.wit b/testdata/wit-parser/version-syntax.wit.json.golden.wit new file mode 100644 index 00000000..c6acac8c --- /dev/null +++ b/testdata/wit-parser/version-syntax.wit.json.golden.wit @@ -0,0 +1,19 @@ +package a:b@1.0.0; + +package a:b@1.0.0-11-a {} + +package a:b@1.0.0-11ab {} + +package a:b@1.0.0-a1.1-a {} + +package a:b@1.0.1 {} + +package a:b@1.0.1-- {} + +package a:b@1.0.1-1+1 {} + +package a:b@1.0.1-1a+1a {} + +package a:b@1.0.1-a+a {} + +package foo:root {} diff --git a/wit/codec.go b/wit/codec.go index b97ad54d..28cb7af7 100644 --- a/wit/codec.go +++ b/wit/codec.go @@ -377,7 +377,7 @@ func (c *typeDefKindCodec) DecodeField(dec codec.Decoder, name string) error { *c.v = v case "stream": v := &Stream{} - err = dec.Decode(v) + err = dec.Decode(&v.Type) *c.v = v case "type": var v Type @@ -556,18 +556,6 @@ func (r *Result) DecodeField(dec codec.Decoder, name string) error { return nil } -// DecodeField implements the [codec.FieldDecoder] interface -// to decode a struct or JSON object. -func (s *Stream) DecodeField(dec codec.Decoder, name string) error { - switch name { - case "element": - return dec.Decode(&s.Element) - case "end": - return dec.Decode(&s.End) - } - return nil -} - // DecodeField implements the [codec.FieldDecoder] interface // to decode a struct or JSON object. func (c *EnumCase) DecodeField(dec codec.Decoder, name string) error { diff --git a/wit/stream.go b/wit/stream.go index 36532dc3..cc5dea40 100644 --- a/wit/stream.go +++ b/wit/stream.go @@ -7,8 +7,7 @@ package wit // [WASI Preview 3]: https://bytecodealliance.org/articles/webassembly-the-updated-roadmap-for-developers type Stream struct { _typeDefKind - Element Type // optional associated Type (can be nil) - End Type // optional associated Type (can be nil) + Type Type // associated Type (must not be nil) } // Size returns the [ABI byte size] for a [Stream]. @@ -29,9 +28,9 @@ func (*Stream) Align() uintptr { return 0 } // [flattened]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening func (*Stream) Flat() []Type { return nil } -func (s *Stream) hasPointer() bool { return HasPointer(s.Element) || HasPointer(s.End) } -func (s *Stream) hasBorrow() bool { return HasBorrow(s.Element) || HasBorrow(s.End) } -func (s *Stream) hasResource() bool { return HasResource(s.Element) || HasResource(s.End) } +func (s *Stream) hasPointer() bool { return HasPointer(s.Type) } +func (s *Stream) hasBorrow() bool { return HasBorrow(s.Type) } +func (s *Stream) hasResource() bool { return HasResource(s.Type) } func (s *Stream) dependsOn(dep Node) bool { - return dep == s || DependsOn(s.Element, dep) || DependsOn(s.End, dep) + return dep == s || DependsOn(s.Type, dep) } diff --git a/wit/testdata_test.go b/wit/testdata_test.go index 44acb0f5..01aa7ceb 100644 --- a/wit/testdata_test.go +++ b/wit/testdata_test.go @@ -84,9 +84,10 @@ func TestGoldenWITRoundTrip(t *testing.T) { args := []string{"component", "wit", "-j", "--all-features"} stdin := strings.NewReader(data) stdout := &bytes.Buffer{} - err := wasmTools.Run(ctx, stdin, stdout, nil, nil, args...) + stderr := &bytes.Buffer{} + err := wasmTools.Run(ctx, stdin, stdout, stderr, nil, args...) if err != nil { - t.Errorf("wasm-tools: %v", err) + t.Errorf("wasm-tools: %v\n%s\n", err, stderr.String()) return } diff --git a/wit/wit.go b/wit/wit.go index 9a74350f..aef8df4d 100644 --- a/wit/wit.go +++ b/wit/wit.go @@ -138,7 +138,7 @@ func (r *Resolve) WIT(ctx Node, _ string) string { name = p.Name.WIT(ctx, "") } wit := p.WIT(ctx, name) - if len(packages) == 1 || strings.Count(wit, "\n") > 1 { + if ctx == nil || len(packages) == 1 || strings.Count(wit, "\n") > 1 { if hasContent { b.WriteString("\n") } @@ -944,20 +944,8 @@ func (s *Stream) WIT(_ Node, name string) string { b.WriteString(escape(name)) b.WriteString(" = ") } - b.WriteString("stream") - if s.Element == nil && s.End == nil { - return b.String() - } - b.WriteRune('<') - if s.Element != nil { - b.WriteString(s.Element.WIT(s, "")) - } else { - b.WriteRune('_') - } - if s.End != nil { - b.WriteString(", ") - b.WriteString(s.End.WIT(s, "")) - } + b.WriteString("stream<") + b.WriteString(s.Type.WIT(s, "")) b.WriteRune('>') return b.String() }