diff --git a/Cargo.lock b/Cargo.lock index 8d07a0dcd4c77f..bbacda3e77adb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,11 +26,11 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" [[package]] name = "ahash" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f200cbb1e856866d9eade941cf3aa0c5d7dd36f74311c4273b494f4ef036957" +checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.3", "once_cell", "version_check", ] @@ -100,7 +100,7 @@ checksum = "f93f52ce8fac3d0e6720a92b0576d737c01b1b5db4dd786e962e5925f00bf755" dependencies = [ "darling", "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "swc_macros_common", "syn 1.0.65", @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a26cb53174ddd320edfff199a853f93d571f48eeb4dde75e67a9a3dbb7b7e5e" +checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" dependencies = [ "async-stream-impl", "futures-core", @@ -132,11 +132,11 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db134ba52475c060f3329a8ef0f8786d6b872ed01515d4b79c162e5798da1340" +checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -147,7 +147,7 @@ version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -170,7 +170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cbf586c80ada5e5ccdecae80d3ef0854f224e2dd74435f8d87e6831b8d0a38" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -270,9 +270,9 @@ checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" [[package]] name = "bumpalo" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" +checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" [[package]] name = "byteorder" @@ -288,9 +288,9 @@ checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" [[package]] name = "cc" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" dependencies = [ "jobserver", ] @@ -341,6 +341,17 @@ dependencies = [ "vec_map", ] +[[package]] +name = "clipboard-win" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4ea1881992efc993e4dc50a324cdbd03216e41bdc8385720ff47efc9bd2ca8" +dependencies = [ + "error-code", + "str-buf", + "winapi 0.3.9", +] + [[package]] name = "cocoa-foundation" version = "0.1.0" @@ -408,9 +419,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" +checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" dependencies = [ "libc", ] @@ -445,11 +456,10 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "autocfg 1.0.1", "cfg-if 1.0.0", "lazy_static", ] @@ -483,7 +493,7 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "strsim 0.9.3", "syn 1.0.65", @@ -721,12 +731,15 @@ dependencies = [ name = "deno_net" version = "0.1.0" dependencies = [ + "base64 0.13.0", "bytes", "deno_core", + "deno_websocket", "http", "hyper", "lazy_static", "log", + "ring", "rustls", "serde", "tokio", @@ -842,6 +855,7 @@ version = "0.15.1" dependencies = [ "deno_core", "http", + "hyper", "serde", "tokio", "tokio-rustls", @@ -867,7 +881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" dependencies = [ "convert_case", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -1009,7 +1023,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -1021,16 +1035,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b940da354ae81ef0926c5eaa428207b8f4f091d3956c891dfbd124162bed99" dependencies = [ "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "swc_macros_common", "syn 1.0.65", ] [[package]] name = "env_logger" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", "humantime", @@ -1071,6 +1085,16 @@ dependencies = [ "libc", ] +[[package]] +name = "error-code" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "exec" version = "0.3.1" @@ -1113,6 +1137,16 @@ dependencies = [ "regex", ] +[[package]] +name = "fd-lock" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0010f02effd88c702318c5dde0463206be67495d0b4d906ba7c0a8f166cc7f06" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "filetime" version = "0.2.14" @@ -1181,36 +1215,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0951635027ca477be98f8774abd6f0345233439d63f307e47101acb40c7cc63d" dependencies = [ "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "swc_macros_common", "syn 1.0.65", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "fsevent" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97f347202c95c98805c216f9e1df210e8ebaec9fdb2365700a43c10797a35e63" -dependencies = [ - "bitflags", - "fsevent-sys", -] - [[package]] name = "fsevent-sys" -version = "3.1.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6f5e6817058771c10f0eb0f05ddf1e35844266f972004fe8e4b21fda295bd5" +checksum = "5c0e564d24da983c053beff1bb7178e237501206840a3e6bf4e267b9e8ae734a" dependencies = [ "libc", ] @@ -1281,7 +1295,7 @@ checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" dependencies = [ "autocfg 1.0.1", "proc-macro-hack", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -1367,9 +1381,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1552,9 +1566,9 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76088804bb65a6f3b880bea9306fdaeffb25ebb453105fafa691282ee9fdba" +checksum = "cbc1b6ca374e81862526786d9cb42357ce03706ed1b8761730caafd02ab91f3a" dependencies = [ "bitflags", "gpu-alloc-types", @@ -1623,7 +1637,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.2", + "ahash 0.7.4", ] [[package]] @@ -1637,18 +1651,18 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] @@ -1694,9 +1708,9 @@ checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" [[package]] name = "httpdate" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" +checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" [[package]] name = "humantime" @@ -1706,9 +1720,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.9" +version = "0.14.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d6baa1b441335f3ce5098ac421fb6547c46dda735ca1bc6d0153c838f9dd83" +checksum = "7728a72c4c7d72665fde02204bcbd93b247721025b222ef78606f14513e0fd03" dependencies = [ "bytes", "futures-channel", @@ -1768,12 +1782,12 @@ checksum = "1f7280c75fb2e2fc47080ec80ccc481376923acb04501957fc38f935c3de5088" [[package]] name = "indexmap" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg 1.0.1", - "hashbrown 0.9.1", + "hashbrown 0.11.2", "serde", ] @@ -1835,9 +1849,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" [[package]] name = "is-macro" @@ -1847,7 +1861,7 @@ checksum = "a322dd16d960e322c3d92f541b4c1a4f0a2e81e1fdeee430d8cecc8b72e8015f" dependencies = [ "Inflector", "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -1939,9 +1953,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.94" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "libloading" @@ -2006,9 +2020,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.89.0" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07731ecd4ee0654728359a5b95e2a254c857876c04b85225496a35d60345daa7" +checksum = "852e0dedfd52cc32325598b2631e0eba31b7b708959676a9f837042f276b09a2" dependencies = [ "bitflags", "serde", @@ -2049,7 +2063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca1d48da0e4a6100b4afd52fae99f36d47964a209624021280ad9ffdd410e83d" dependencies = [ "heck", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -2113,9 +2127,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" dependencies = [ "libc", "log", @@ -2180,14 +2194,13 @@ dependencies = [ [[package]] name = "notify" -version = "5.0.0-pre.8" +version = "5.0.0-pre.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bbbcd078f1f00ddb7a9abe70b96e91229b44b0b3afdec610f8e5137f8f014b" +checksum = "51f18203a26893ca1d3526cf58084025d5639f91c44f8b70ab3b724f60e819a0" dependencies = [ "bitflags", "crossbeam-channel", "filetime", - "fsevent", "fsevent-sys", "inotify", "libc", @@ -2308,9 +2321,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "opaque-debug" @@ -2428,7 +2441,7 @@ dependencies = [ "phf_generator", "phf_shared", "proc-macro-hack", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -2457,16 +2470,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] [[package]] name = "pin-project-lite" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" [[package]] name = "pin-utils" @@ -2486,7 +2499,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -2510,7 +2523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", "version_check", @@ -2522,7 +2535,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "version_check", ] @@ -2550,18 +2563,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ "unicode-xid 0.2.2", ] [[package]] name = "profiling" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6" +checksum = "87dfd5592a8eed7e74f56ad7b125f8234763b805c30f0c7c95c486920026a6ec" [[package]] name = "pty" @@ -2605,7 +2618,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", ] [[package]] @@ -2645,9 +2658,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", ] [[package]] @@ -2662,12 +2675,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -2681,11 +2694,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.3", ] [[package]] @@ -2699,11 +2712,11 @@ dependencies = [ [[package]] name = "rand_hc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -2732,9 +2745,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" dependencies = [ "bitflags", ] @@ -2780,9 +2793,9 @@ checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" [[package]] name = "reqwest" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124" +checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22" dependencies = [ "async-compression", "base64 0.13.0", @@ -2938,13 +2951,14 @@ dependencies = [ [[package]] name = "rustyline" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e1b597fcd1eeb1d6b25b493538e5aa19629eb08932184b85fef931ba87e893" +checksum = "fbd4eaf7a7738f76c98e4f0395253ae853be3eb018f7b0bb57fe1b6c17e31874" dependencies = [ "bitflags", "cfg-if 1.0.0", - "fs2", + "clipboard-win", + "fd-lock", "libc", "log", "memchr", @@ -3044,7 +3058,7 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -3067,7 +3081,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -3128,9 +3142,9 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" [[package]] name = "signal-hook-registry" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] @@ -3256,6 +3270,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "str-buf" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" + [[package]] name = "string_cache" version = "0.8.1" @@ -3277,7 +3297,7 @@ checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97" dependencies = [ "phf_generator", "phf_shared", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", ] @@ -3288,7 +3308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f584cc881e9e5f1fd6bf827b0444aa94c30d8fe6378cf241071b5f5700b2871f" dependencies = [ "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "swc_macros_common", "syn 1.0.65", @@ -3328,7 +3348,7 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a893fda61ad72583351e97313439b9cdd200ffb6b2ae75f363e03a39df935086" dependencies = [ - "ahash 0.7.2", + "ahash 0.7.4", "anyhow", "crc", "fxhash", @@ -3412,7 +3432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51af418026cb4ea588e2b15fa206c44e09a3184b718e12a0919729c7c3ad20d3" dependencies = [ "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "swc_macros_common", "syn 1.0.65", @@ -3649,7 +3669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c8f200a2eaed938e7c1a685faaa66e6d42fa9e17da5f62572d3cbc335898f5e" dependencies = [ "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -3661,7 +3681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08ed2e930f5a1a4071fe62c90fd3a296f6030e5d94bfe13993244423caf59a78" dependencies = [ "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -3684,7 +3704,7 @@ checksum = "e3b2825fee79f10d0166e8e650e79c7a862fb991db275743083f07555d7641f0" dependencies = [ "Inflector", "pmutil", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "swc_macros_common", "syn 1.0.65", @@ -3707,7 +3727,7 @@ version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "unicode-xid 0.2.2", ] @@ -3718,7 +3738,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", "unicode-xid 0.2.2", @@ -3795,20 +3815,20 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -3880,7 +3900,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", ] @@ -4127,9 +4147,9 @@ dependencies = [ [[package]] name = "twoway" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" +checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47" dependencies = [ "memchr", "unchecked-index", @@ -4173,9 +4193,9 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] @@ -4241,15 +4261,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.3", "serde", ] [[package]] name = "vcpkg" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vec_map" @@ -4317,7 +4337,7 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", "wasm-bindgen-shared", @@ -4351,7 +4371,7 @@ version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", "wasm-bindgen-backend", @@ -4544,7 +4564,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" dependencies = [ - "proc-macro2 1.0.26", + "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.65", "synstructure", diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index ad78e1e44060db..21325ff77e6b4e 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -9,6 +9,7 @@ import { assertThrowsAsync, deferred, delay, + fail, unitTest, } from "./test_util.ts"; @@ -631,3 +632,33 @@ unitTest( await promise; }, ); + +unitTest({ perms: { net: true } }, async function httpServerWebSocket() { + const promise = (async () => { + const listener = Deno.listen({ port: 4501 }); + for await (const conn of listener) { + const httpConn = Deno.serveHttp(conn); + const { request, respondWith } = (await httpConn.nextRequest())!; + const { + response, + websocket, + } = await Deno.upgradeWebSocket(request); + websocket.onerror = () => fail(); + websocket.onmessage = (m) => { + websocket.send(m.data); + websocket.close(); + }; + await respondWith(response); + break; + } + })(); + + const def = deferred(); + const ws = new WebSocket("ws://localhost:4501"); + ws.onmessage = (m) => assertEquals(m.data, "foo"); + ws.onerror = () => fail(); + ws.onclose = () => def.resolve(); + ws.onopen = () => ws.send("foo"); + await def; + await promise; +}); diff --git a/extensions/fetch/23_response.js b/extensions/fetch/23_response.js index 32a9b466c48d20..11eb13570fffa2 100644 --- a/extensions/fetch/23_response.js +++ b/extensions/fetch/23_response.js @@ -437,6 +437,7 @@ window.__bootstrap.fetch ??= {}; window.__bootstrap.fetch.Response = Response; + window.__bootstrap.fetch.newInnerResponse = newInnerResponse; window.__bootstrap.fetch.toInnerResponse = toInnerResponse; window.__bootstrap.fetch.fromInnerResponse = fromInnerResponse; window.__bootstrap.fetch.redirectStatus = redirectStatus; diff --git a/extensions/net/03_http.js b/extensions/net/03_http.js index 343b305a691c45..db2d0a3b1226c9 100644 --- a/extensions/net/03_http.js +++ b/extensions/net/03_http.js @@ -2,21 +2,34 @@ "use strict"; ((window) => { + const webidl = window.__bootstrap.webidl; const { InnerBody } = window.__bootstrap.fetchBody; - const { Response, fromInnerRequest, toInnerResponse, newInnerRequest } = - window.__bootstrap.fetch; + const { setEventTargetData } = window.__bootstrap.eventTarget; + const { + Response, + fromInnerRequest, + toInnerResponse, + newInnerRequest, + newInnerResponse, + fromInnerResponse, + } = window.__bootstrap.fetch; const core = window.Deno.core; const { BadResource, Interrupted } = core; const { ReadableStream } = window.__bootstrap.streams; const abortSignal = window.__bootstrap.abortSignal; + const { WebSocket, _rid, _readyState, _eventLoop, _protocol } = + window.__bootstrap.webSocket; const { - Symbol, - Uint8Array, + ArrayPrototypeIncludes, + ArrayPrototypePush, Promise, StringPrototypeIncludes, + StringPrototypeSplit, + Symbol, SymbolAsyncIterator, - TypeError, TypedArrayPrototypeSubarray, + TypeError, + Uint8Array, } = window.__bootstrap.primordials; function serveHttp(conn) { @@ -65,7 +78,7 @@ if (nextRequest === null) return null; const [ - requestBodyRid, + requestRid, responseSenderRid, method, headersList, @@ -74,8 +87,8 @@ /** @type {ReadableStream | undefined} */ let body = null; - if (typeof requestBodyRid === "number") { - body = createRequestBodyStream(requestBodyRid); + if (typeof requestRid === "number") { + body = createRequestBodyStream(requestRid); } const innerRequest = newInnerRequest( @@ -87,7 +100,11 @@ const signal = abortSignal.newSignal(); const request = fromInnerRequest(innerRequest, signal, "immutable"); - const respondWith = createRespondWith(this, responseSenderRid); + const respondWith = createRespondWith( + this, + responseSenderRid, + requestRid, + ); return { request, respondWith }; } @@ -118,7 +135,7 @@ ); } - function createRespondWith(httpConn, responseSenderRid) { + function createRespondWith(httpConn, responseSenderRid, requestRid) { return async function respondWith(resp) { if (resp instanceof Promise) { resp = await resp; @@ -222,10 +239,51 @@ } catch { /* pass */ } } } + + const ws = resp[_ws]; + if (ws) { + if (typeof requestRid !== "number") { + throw new TypeError( + "This request can not be upgraded to a websocket connection.", + ); + } + + const wsRid = await core.opAsync( + "op_http_upgrade_websocket", + requestRid, + ); + ws[_rid] = wsRid; + ws[_protocol] = resp.headers.get("sec-websocket-protocol"); + + if (ws[_readyState] === WebSocket.CLOSING) { + await core.opAsync("op_ws_close", { rid: wsRid }); + + ws[_readyState] = WebSocket.CLOSED; + + const errEvent = new ErrorEvent("error"); + ws.dispatchEvent(errEvent); + + const event = new CloseEvent("close"); + ws.dispatchEvent(event); + + try { + core.close(wsRid); + } catch (err) { + // Ignore error if the socket has already been closed. + if (!(err instanceof Deno.errors.BadResource)) throw err; + } + } else { + ws[_readyState] = WebSocket.OPEN; + const event = new Event("open"); + ws.dispatchEvent(event); + + ws[_eventLoop](); + } + } }; } - function createRequestBodyStream(requestBodyRid) { + function createRequestBodyStream(requestRid) { return new ReadableStream({ type: "bytes", async pull(controller) { @@ -234,7 +292,7 @@ // stream. const chunk = new Uint8Array(16 * 1024 + 256); const read = await readRequest( - requestBodyRid, + requestRid, chunk, ); if (read > 0) { @@ -243,23 +301,79 @@ } else { // We have reached the end of the body, so we close the stream. controller.close(); - core.close(requestBodyRid); + core.close(requestRid); } } catch (err) { // There was an error while reading a chunk of the body, so we // error. controller.error(err); controller.close(); - core.close(requestBodyRid); + core.close(requestRid); } }, cancel() { - core.close(requestBodyRid); + core.close(requestRid); }, }); } + const _ws = Symbol("[[associated_ws]]"); + + function upgradeWebSocket(request, options = {}) { + if (request.headers.get("upgrade") !== "websocket") { + throw new TypeError( + "Invalid Header: 'upgrade' header must be 'websocket'", + ); + } + + if (request.headers.get("connection") !== "Upgrade") { + throw new TypeError( + "Invalid Header: 'connection' header must be 'Upgrade'", + ); + } + + const websocketKey = request.headers.get("sec-websocket-key"); + if (websocketKey === null) { + throw new TypeError( + "Invalid Header: 'sec-websocket-key' header must be set", + ); + } + + const accept = core.opSync("op_http_websocket_accept_header", websocketKey); + + const r = newInnerResponse(101); + r.headerList = [ + ["upgrade", "websocket"], + ["connection", "Upgrade"], + ["sec-websocket-accept", accept], + ]; + + const protocolsStr = request.headers.get("sec-websocket-protocol") || ""; + const protocols = StringPrototypeSplit(protocolsStr, ", "); + if (protocols && options.protocol) { + if (ArrayPrototypeIncludes(protocols, options.protocol)) { + ArrayPrototypePush(r.headerList, [ + "sec-websocket-protocol", + options.protocol, + ]); + } else { + throw new TypeError( + `Protocol '${options.protocol}' not in the request's protocol list (non negotiable)`, + ); + } + } + + const response = fromInnerResponse(r, "immutable"); + + const websocket = webidl.createBranded(WebSocket); + setEventTargetData(websocket); + response[_ws] = websocket; + + return { response, websocket }; + } + window.__bootstrap.http = { serveHttp, + upgradeWebSocket, }; })(this); diff --git a/extensions/net/Cargo.toml b/extensions/net/Cargo.toml index e39c5c4886a76c..de84dd8515a800 100644 --- a/extensions/net/Cargo.toml +++ b/extensions/net/Cargo.toml @@ -15,12 +15,15 @@ path = "lib.rs" [dependencies] deno_core = { version = "0.92.0", path = "../../core" } +deno_websocket = { version = "0.15.0", path = "../websocket" } +base64 = "0.13.0" bytes = "1" log = "0.4.14" lazy_static = "1.4.0" http = "0.2.3" hyper = { version = "0.14.9", features = ["server", "stream", "http1", "http2", "runtime"] } +ring = "0.16.20" rustls = "0.19.0" serde = { version = "1.0.125", features = ["derive"] } tokio = { version = "1.8.0", features = ["full"] } diff --git a/extensions/net/lib.deno_net.unstable.d.ts b/extensions/net/lib.deno_net.unstable.d.ts index 905a7acc1760d9..c47558edc91dc6 100644 --- a/extensions/net/lib.deno_net.unstable.d.ts +++ b/extensions/net/lib.deno_net.unstable.d.ts @@ -259,4 +259,18 @@ declare namespace Deno { * then the underlying HttpConn resource is closed automatically. */ export function serveHttp(conn: Conn): HttpConn; + + export interface WebSocketUpgrade { + response: Response; + websocket: WebSocket; + } + + export interface UpgradeWebSocketOptions { + protocol?: string; + } + + export function upgradeWebSocket( + request: Request, + options?: UpgradeWebSocketOptions, + ): WebSocketUpgrade; } diff --git a/extensions/net/ops_http.rs b/extensions/net/ops_http.rs index 54e06c3a7a8c24..782ec91d013fa4 100644 --- a/extensions/net/ops_http.rs +++ b/extensions/net/ops_http.rs @@ -2,7 +2,6 @@ use crate::io::TcpStreamResource; use crate::io::TlsStreamResource; -use crate::ops_tls::TlsStream; use deno_core::error::bad_resource_id; use deno_core::error::null_opbuf; use deno_core::error::type_error; @@ -25,7 +24,6 @@ use deno_core::ResourceId; use deno_core::ZeroCopyBuf; use hyper::body::HttpBody; use hyper::http; -use hyper::server::conn::Connection; use hyper::server::conn::Http; use hyper::service::Service as HyperService; use hyper::Body; @@ -42,7 +40,6 @@ use std::rc::Rc; use std::task::Context; use std::task::Poll; use tokio::io::AsyncReadExt; -use tokio::net::TcpStream; use tokio::sync::oneshot; use tokio_util::io::StreamReader; @@ -54,6 +51,14 @@ pub fn init() -> Vec { ("op_http_response", op_async(op_http_response)), ("op_http_response_write", op_async(op_http_response_write)), ("op_http_response_close", op_async(op_http_response_close)), + ( + "op_http_websocket_accept_header", + op_sync(op_http_websocket_accept_header), + ), + ( + "op_http_upgrade_websocket", + op_async(op_http_upgrade_websocket), + ), ] } @@ -97,13 +102,15 @@ impl HyperService> for Service { } } -enum ConnType { - Tcp(Rc>>), - Tls(Rc>>), +type ConnFuture = Pin>>>; + +struct Conn { + scheme: &'static str, + conn: Rc>, } struct ConnResource { - hyper_connection: ConnType, + hyper_connection: Conn, deno_service: Service, addr: SocketAddr, cancel: CancelHandle, @@ -112,11 +119,12 @@ struct ConnResource { impl ConnResource { // TODO(ry) impl Future for ConnResource? fn poll(&self, cx: &mut Context<'_>) -> Poll> { - match &self.hyper_connection { - ConnType::Tcp(c) => c.borrow_mut().poll_unpin(cx), - ConnType::Tls(c) => c.borrow_mut().poll_unpin(cx), - } - .map_err(AnyError::from) + self + .hyper_connection + .conn + .borrow_mut() + .poll_unpin(cx) + .map_err(AnyError::from) } } @@ -134,7 +142,7 @@ impl Resource for ConnResource { #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct NextRequestResponse( - // request_body_rid: + // request_rid: Option, // response_sender_rid: ResourceId, @@ -207,12 +215,7 @@ async fn op_http_request_next( } let url = { - let scheme = { - match conn_resource.hyper_connection { - ConnType::Tcp(_) => "http", - ConnType::Tls(_) => "https", - } - }; + let scheme = &conn_resource.hyper_connection.scheme; let host: Cow = if let Some(host) = req.uri().host() { Cow::Borrowed(host) } else if let Some(host) = req.headers().get("HOST") { @@ -224,24 +227,35 @@ async fn op_http_request_next( format!("{}://{}{}", scheme, host, path) }; + let is_websocket_request = req + .headers() + .get(hyper::header::CONNECTION) + .and_then(|v| { + v.to_str().ok().map(|s| "Upgrade".eq_ignore_ascii_case(s)) + }) + .unwrap_or(false) + && req + .headers() + .get(hyper::header::UPGRADE) + .and_then(|v| { + v.to_str().ok().map(|s| "websocket".eq_ignore_ascii_case(s)) + }) + .unwrap_or(false); + let has_body = if let Some(exact_size) = req.size_hint().exact() { exact_size > 0 } else { true }; - let maybe_request_body_rid = if has_body { - let stream: BytesStream = Box::pin(req.into_body().map(|r| { - r.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)) - })); - let stream_reader = StreamReader::new(stream); + let maybe_request_rid = if is_websocket_request || has_body { let mut state = state.borrow_mut(); - let request_body_rid = state.resource_table.add(RequestBodyResource { + let request_rid = state.resource_table.add(RequestResource { conn_rid, - reader: AsyncRefCell::new(stream_reader), + inner: AsyncRefCell::new(RequestOrStreamReader::Request(Some(req))), cancel: CancelHandle::default(), }); - Some(request_body_rid) + Some(request_rid) } else { None }; @@ -254,7 +268,7 @@ async fn op_http_request_next( }); Poll::Ready(Ok(Some(NextRequestResponse( - maybe_request_body_rid, + maybe_request_rid, response_sender_rid, method, headers, @@ -303,9 +317,14 @@ fn op_http_start( let addr = tcp_stream.local_addr()?; let hyper_connection = Http::new() .with_executor(LocalExecutor) - .serve_connection(tcp_stream, deno_service.clone()); + .serve_connection(tcp_stream, deno_service.clone()) + .with_upgrades(); + let conn = Pin::new(Box::new(hyper_connection)); let conn_resource = ConnResource { - hyper_connection: ConnType::Tcp(Rc::new(RefCell::new(hyper_connection))), + hyper_connection: Conn { + conn: Rc::new(RefCell::new(conn)), + scheme: "http", + }, deno_service, addr, cancel: CancelHandle::default(), @@ -326,9 +345,14 @@ fn op_http_start( let hyper_connection = Http::new() .with_executor(LocalExecutor) - .serve_connection(tls_stream, deno_service.clone()); + .serve_connection(tls_stream, deno_service.clone()) + .with_upgrades(); + let conn = Pin::new(Box::new(hyper_connection)); let conn_resource = ConnResource { - hyper_connection: ConnType::Tls(Rc::new(RefCell::new(hyper_connection))), + hyper_connection: Conn { + conn: Rc::new(RefCell::new(conn)), + scheme: "https", + }, deno_service, addr, cancel: CancelHandle::default(), @@ -367,10 +391,12 @@ async fn op_http_response( .ok() .expect("multiple op_http_respond ongoing"); + let conn_rid = response_sender.conn_rid; + let conn_resource = state .borrow() .resource_table - .get::(response_sender.conn_rid) + .get::(conn_rid) .ok_or_else(bad_resource_id)?; let mut builder = Response::builder().status(status); @@ -393,7 +419,7 @@ async fn op_http_response( let response_body_rid = state.borrow_mut().resource_table.add(ResponseBodyResource { body: AsyncRefCell::new(sender), - conn_rid: response_sender.conn_rid, + conn_rid, }); Some(response_body_rid) @@ -407,7 +433,10 @@ async fn op_http_response( } poll_fn(|cx| match conn_resource.poll(cx) { - Poll::Ready(x) => Poll::Ready(x), + Poll::Ready(x) => { + state.borrow_mut().resource_table.close(conn_rid); + Poll::Ready(x) + } Poll::Pending => Poll::Ready(Ok(())), }) .await?; @@ -455,7 +484,7 @@ async fn op_http_request_read( let resource = state .borrow() .resource_table - .get::(rid as u32) + .get::(rid as u32) .ok_or_else(bad_resource_id)?; let conn_resource = state @@ -464,8 +493,26 @@ async fn op_http_request_read( .get::(resource.conn_rid) .ok_or_else(bad_resource_id)?; - let mut reader = RcRef::map(&resource, |r| &r.reader).borrow_mut().await; + let mut inner = RcRef::map(resource.clone(), |r| &r.inner) + .borrow_mut() + .await; + + if let RequestOrStreamReader::Request(req) = &mut *inner { + let req = req.take().unwrap(); + let stream: BytesStream = Box::pin(req.into_body().map(|r| { + r.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)) + })); + let reader = StreamReader::new(stream); + *inner = RequestOrStreamReader::StreamReader(reader); + }; + + let reader = match &mut *inner { + RequestOrStreamReader::StreamReader(reader) => reader, + _ => unreachable!(), + }; + let cancel = RcRef::map(resource, |r| &r.cancel); + let mut read_fut = reader.read(&mut data).try_or_cancel(cancel).boxed_local(); poll_fn(|cx| { @@ -521,18 +568,77 @@ async fn op_http_response_write( Ok(()) } +fn op_http_websocket_accept_header( + _: &mut OpState, + key: String, + _: (), +) -> Result { + let digest = ring::digest::digest( + &ring::digest::SHA1_FOR_LEGACY_USE_ONLY, + format!("{}258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key).as_bytes(), + ); + Ok(base64::encode(digest)) +} + +async fn op_http_upgrade_websocket( + state: Rc>, + rid: ResourceId, + _: (), +) -> Result { + let req_resource = state + .borrow_mut() + .resource_table + .take::(rid) + .ok_or_else(bad_resource_id)?; + + let mut inner = RcRef::map(&req_resource, |r| &r.inner).borrow_mut().await; + + if let RequestOrStreamReader::Request(req) = inner.as_mut() { + let upgraded = hyper::upgrade::on(req.as_mut().unwrap()).await?; + let stream = + deno_websocket::tokio_tungstenite::WebSocketStream::from_raw_socket( + upgraded, + deno_websocket::tokio_tungstenite::tungstenite::protocol::Role::Server, + None, + ) + .await; + + let (ws_tx, ws_rx) = stream.split(); + let rid = + state + .borrow_mut() + .resource_table + .add(deno_websocket::WsStreamResource { + stream: deno_websocket::WebSocketStreamType::Server { + rx: AsyncRefCell::new(ws_rx), + tx: AsyncRefCell::new(ws_tx), + }, + cancel: Default::default(), + }); + + Ok(rid) + } else { + Err(bad_resource_id()) + } +} + type BytesStream = Pin> + Unpin>>; -struct RequestBodyResource { +enum RequestOrStreamReader { + Request(Option>), + StreamReader(StreamReader), +} + +struct RequestResource { conn_rid: ResourceId, - reader: AsyncRefCell>, + inner: AsyncRefCell, cancel: CancelHandle, } -impl Resource for RequestBodyResource { +impl Resource for RequestResource { fn name(&self) -> Cow { - "requestBody".into() + "request".into() } fn close(self: Rc) { diff --git a/extensions/websocket/01_websocket.js b/extensions/websocket/01_websocket.js index f6e285b7653f54..7caff579e78c4c 100644 --- a/extensions/websocket/01_websocket.js +++ b/extensions/websocket/01_websocket.js @@ -124,6 +124,7 @@ const _protocol = Symbol("[[protocol]]"); const _binaryType = Symbol("[[binaryType]]"); const _bufferedAmount = Symbol("[[bufferedAmount]]"); + const _eventLoop = Symbol("[[eventLoop]]"); class WebSocket extends EventTarget { [_rid]; @@ -294,7 +295,7 @@ const event = new Event("open"); this.dispatchEvent(event); - this.#eventLoop(); + this[_eventLoop](); } }, (err) => { @@ -427,7 +428,7 @@ } } - async #eventLoop() { + async [_eventLoop]() { while (this[_readyState] === OPEN) { const { kind, value } = await core.opAsync( "op_ws_next_event", @@ -518,5 +519,11 @@ webidl.configurePrototype(WebSocket); - window.__bootstrap.webSocket = { WebSocket }; + window.__bootstrap.webSocket = { + WebSocket, + _rid, + _readyState, + _eventLoop, + _protocol, + }; })(this); diff --git a/extensions/websocket/Cargo.toml b/extensions/websocket/Cargo.toml index 81b57d3f22afcf..0ca38e7732da75 100644 --- a/extensions/websocket/Cargo.toml +++ b/extensions/websocket/Cargo.toml @@ -20,5 +20,6 @@ serde = { version = "1.0.125", features = ["derive"] } tokio = { version = "1.8.0", features = ["full"] } tokio-rustls = "0.22.0" tokio-tungstenite = { version = "0.14.0", features = ["rustls-tls"] } +hyper = { version = "0.14.9" } webpki = "0.21.4" webpki-roots = "0.21.1" diff --git a/extensions/websocket/lib.rs b/extensions/websocket/lib.rs index c6752d23bec45b..f5bf15c79b97c3 100644 --- a/extensions/websocket/lib.rs +++ b/extensions/websocket/lib.rs @@ -64,13 +64,81 @@ impl WebSocketPermissions for NoWebSocketPermissions { } type WsStream = WebSocketStream>; -struct WsStreamResource { - tx: AsyncRefCell>, - rx: AsyncRefCell>, +pub enum WebSocketStreamType { + Client { + tx: AsyncRefCell>, + rx: AsyncRefCell>, + }, + Server { + tx: AsyncRefCell< + SplitSink, Message>, + >, + rx: AsyncRefCell>>, + }, +} + +pub struct WsStreamResource { + pub stream: WebSocketStreamType, // When a `WsStreamResource` resource is closed, all pending 'read' ops are // canceled, while 'write' ops are allowed to complete. Therefore only // 'read' futures are attached to this cancel handle. - cancel: CancelHandle, + pub cancel: CancelHandle, +} + +impl WsStreamResource { + async fn send(self: &Rc, message: Message) -> Result<(), AnyError> { + match self.stream { + WebSocketStreamType::Client { .. } => { + let mut tx = RcRef::map(self, |r| match &r.stream { + WebSocketStreamType::Client { tx, .. } => tx, + WebSocketStreamType::Server { .. } => unreachable!(), + }) + .borrow_mut() + .await; + tx.send(message).await?; + } + WebSocketStreamType::Server { .. } => { + let mut tx = RcRef::map(self, |r| match &r.stream { + WebSocketStreamType::Client { .. } => unreachable!(), + WebSocketStreamType::Server { tx, .. } => tx, + }) + .borrow_mut() + .await; + tx.send(message).await?; + } + } + + Ok(()) + } + + async fn next_message( + self: &Rc, + cancel: RcRef, + ) -> Result< + Option>, + AnyError, + > { + match &self.stream { + WebSocketStreamType::Client { .. } => { + let mut rx = RcRef::map(self, |r| match &r.stream { + WebSocketStreamType::Client { rx, .. } => rx, + WebSocketStreamType::Server { .. } => unreachable!(), + }) + .borrow_mut() + .await; + rx.next().or_cancel(cancel).await.map_err(AnyError::from) + } + WebSocketStreamType::Server { .. } => { + let mut rx = RcRef::map(self, |r| match &r.stream { + WebSocketStreamType::Client { .. } => unreachable!(), + WebSocketStreamType::Server { rx, .. } => rx, + }) + .borrow_mut() + .await; + rx.next().or_cancel(cancel).await.map_err(AnyError::from) + } + } + } } impl Resource for WsStreamResource { @@ -79,8 +147,6 @@ impl Resource for WsStreamResource { } } -impl WsStreamResource {} - // This op is needed because creating a WS instance in JavaScript is a sync // operation and should throw error when permissions are not fulfilled, // but actual op that connects WS is async. @@ -184,8 +250,10 @@ where let (ws_tx, ws_rx) = stream.split(); let resource = WsStreamResource { - rx: AsyncRefCell::new(ws_rx), - tx: AsyncRefCell::new(ws_tx), + stream: WebSocketStreamType::Client { + rx: AsyncRefCell::new(ws_rx), + tx: AsyncRefCell::new(ws_tx), + }, cancel: Default::default(), }; let mut state = state.borrow_mut(); @@ -227,15 +295,13 @@ pub async fn op_ws_send( "pong" => Message::Pong(vec![]), _ => unreachable!(), }; - let rid = args.rid; let resource = state .borrow_mut() .resource_table - .get::(rid) + .get::(args.rid) .ok_or_else(bad_resource_id)?; - let mut tx = RcRef::map(&resource, |r| &r.tx).borrow_mut().await; - tx.send(msg).await?; + resource.send(msg).await?; Ok(()) } @@ -266,8 +332,7 @@ pub async fn op_ws_close( .resource_table .get::(rid) .ok_or_else(bad_resource_id)?; - let mut tx = RcRef::map(&resource, |r| &r.tx).borrow_mut().await; - tx.send(msg).await?; + resource.send(msg).await?; Ok(()) } @@ -294,9 +359,8 @@ pub async fn op_ws_next_event( .get::(rid) .ok_or_else(bad_resource_id)?; - let mut rx = RcRef::map(&resource, |r| &r.rx).borrow_mut().await; - let cancel = RcRef::map(resource, |r| &r.cancel); - let val = rx.next().or_cancel(cancel).await?; + let cancel = RcRef::map(&resource, |r| &r.cancel); + let val = resource.next_message(cancel).await?; let res = match val { Some(Ok(Message::Text(text))) => NextEventResponse::String(text), Some(Ok(Message::Binary(data))) => NextEventResponse::Binary(data.into()), diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 85631cd553e93a..89c9ef06001778 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -128,6 +128,7 @@ serveHttp: __bootstrap.http.serveHttp, startTls: __bootstrap.tls.startTls, umask: __bootstrap.fs.umask, + upgradeWebSocket: __bootstrap.http.upgradeWebSocket, futime: __bootstrap.fs.futime, futimeSync: __bootstrap.fs.futimeSync, utime: __bootstrap.fs.utime,