From 1c11684da5146db5c38d3e5fae240002c8c05efd Mon Sep 17 00:00:00 2001 From: jedel1043 Date: Fri, 2 Jun 2023 20:34:09 -0600 Subject: [PATCH] Add example for async module fetches --- Cargo.lock | 725 ++++++++++++++++++++++++++- boa_examples/Cargo.toml | 3 + boa_examples/src/bin/module_fetch.rs | 249 +++++++++ 3 files changed, 953 insertions(+), 24 deletions(-) create mode 100644 boa_examples/src/bin/module_fetch.rs diff --git a/Cargo.lock b/Cargo.lock index 8345fcb91ac..64d9049715c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,26 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + [[package]] name = "aes" version = "0.7.5" @@ -24,18 +44,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if 1.0.0", - "cipher", + "cipher 0.3.0", "cpufeatures", "opaque-debug", ] +[[package]] +name = "aes-gcm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" +dependencies = [ + "aead", + "aes 0.6.0", + "cipher 0.2.5", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + [[package]] name = "ahash" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom", + "getrandom 0.2.9", "once_cell", "version_check", ] @@ -130,6 +184,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + [[package]] name = "arbitrary" version = "1.3.0" @@ -139,6 +199,12 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "async-channel" version = "1.8.0" @@ -150,6 +216,16 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-dup" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" +dependencies = [ + "futures-io", + "simple-mutex", +] + [[package]] name = "async-executor" version = "1.5.1" @@ -176,6 +252,37 @@ dependencies = [ "futures-lite", ] +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-h1" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8101020758a4fc3a7c326cb42aa99e9fa77cbfb76987c128ad956406fe1f70a7" +dependencies = [ + "async-channel", + "async-dup", + "async-std", + "futures-core", + "http-types", + "httparse", + "log", + "pin-project", +] + [[package]] name = "async-io" version = "1.13.0" @@ -235,12 +342,62 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + [[package]] name = "async-task" version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +[[package]] +name = "async-tls" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85a97c4a0ecce878efd3f945f119c78a646d8975340bca0398f9bb05c30cc52" +dependencies = [ + "futures-core", + "futures-io", + "rustls", + "webpki", + "webpki-roots", +] + +[[package]] +name = "async-trait" +version = "0.1.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "atomic-polyfill" version = "1.0.2" @@ -294,6 +451,18 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.0" @@ -339,6 +508,15 @@ dependencies = [ "serde", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -435,7 +613,7 @@ dependencies = [ "num_enum", "once_cell", "pollster", - "rand", + "rand 0.8.5", "regress", "rustc-hash", "ryu-js", @@ -465,6 +643,7 @@ dependencies = [ "boa_runtime", "futures-util", "smol", + "surf", ] [[package]] @@ -605,7 +784,7 @@ dependencies = [ "boa_engine", "chrono", "console_error_panic_hook", - "getrandom", + "getrandom 0.2.9", "wasm-bindgen", ] @@ -681,11 +860,11 @@ dependencies = [ "glob", "indicatif", "log", - "rand", + "rand 0.8.5", "reqwest", "serde", "serde_json", - "sha2", + "sha2 0.10.6", "tar", "tempfile", "thiserror", @@ -761,6 +940,15 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + [[package]] name = "cipher" version = "0.3.0" @@ -925,6 +1113,17 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "config" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" +dependencies = [ + "lazy_static", + "nom", + "serde", +] + [[package]] name = "console" version = "0.15.5" @@ -959,6 +1158,23 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "cookie" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" +dependencies = [ + "aes-gcm", + "base64 0.13.1", + "hkdf", + "hmac 0.10.1", + "percent-encoding", + "rand 0.8.5", + "sha2 0.9.9", + "time 0.2.27", + "version_check", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -997,6 +1213,12 @@ dependencies = [ "libc", ] +[[package]] +name = "cpuid-bool" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + [[package]] name = "crc32fast" version = "1.3.2" @@ -1088,6 +1310,16 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.15" @@ -1132,6 +1364,25 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher 0.2.5", +] + [[package]] name = "cxx" version = "1.0.94" @@ -1247,6 +1498,20 @@ dependencies = [ "synstructure 0.12.6", ] +[[package]] +name = "deadpool" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d126179d86aee4556e54f5f3c6bf6d9884e7cc52cef82f77ee6f90a7747616d" +dependencies = [ + "async-trait", + "config", + "crossbeam-queue", + "num_cpus", + "serde", + "tokio", +] + [[package]] name = "deduplicating_array" version = "0.1.4" @@ -1267,13 +1532,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "crypto-common", "subtle", ] @@ -1589,6 +1863,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -1596,6 +1885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1604,6 +1894,17 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.28" @@ -1654,9 +1955,11 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", + "futures-sink", "futures-task", "memchr", "pin-project-lite", @@ -1692,6 +1995,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.9" @@ -1705,6 +2019,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ghash" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.26.2" @@ -1728,6 +2052,18 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.3.18" @@ -1816,13 +2152,33 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "hkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" +dependencies = [ + "digest 0.9.0", + "hmac 0.10.1", +] + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.6", ] [[package]] @@ -1847,6 +2203,47 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-client" +version = "6.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1947510dc91e2bf586ea5ffb412caad7673264e14bb39fb9078da114a94ce1a5" +dependencies = [ + "async-h1", + "async-std", + "async-tls", + "async-trait", + "cfg-if 1.0.0", + "dashmap", + "deadpool", + "futures", + "http-types", + "log", + "rustls", +] + +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel", + "async-std", + "base64 0.13.1", + "cookie", + "futures-lite", + "infer", + "pin-project-lite", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", +] + [[package]] name = "httparse" version = "1.8.0" @@ -2401,6 +2798,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f2cb48b81b1dc9f39676bf99f5499babfec7cd8fe14307f7b3d747208fb5690" +[[package]] +name = "infer" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" + [[package]] name = "instant" version = "0.1.12" @@ -2492,6 +2895,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2504,6 +2916,19 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.142" @@ -2565,6 +2990,9 @@ name = "log" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +dependencies = [ + "value-bag", +] [[package]] name = "loupe" @@ -2667,6 +3095,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -2746,6 +3184,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "nom" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" +dependencies = [ + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -2994,7 +3443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -3004,10 +3453,10 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest", - "hmac", + "digest 0.10.6", + "hmac 0.12.1", "password-hash", - "sha2", + "sha2 0.10.6", ] [[package]] @@ -3042,7 +3491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -3067,6 +3516,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -3135,6 +3604,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" +[[package]] +name = "polyval" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" +dependencies = [ + "cpuid-bool", + "opaque-debug", + "universal-hash", +] + [[package]] name = "postcard" version = "1.0.4" @@ -3239,6 +3719,19 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -3246,8 +3739,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -3257,7 +3760,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -3266,7 +3778,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.9", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -3321,7 +3842,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.9", "redox_syscall 0.2.16", "thiserror", ] @@ -3396,7 +3917,7 @@ version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ - "base64", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -3427,6 +3948,21 @@ dependencies = [ "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "rkyv" version = "0.7.41" @@ -3487,6 +4023,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustls" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" +dependencies = [ + "base64 0.12.3", + "log", + "ring", + "sct", + "webpki", +] + [[package]] name = "rustversion" version = "1.0.12" @@ -3570,6 +4119,16 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "seahash" version = "4.1.0" @@ -3674,6 +4233,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_qs" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror", +] + [[package]] name = "serde_repr" version = "0.1.12" @@ -3736,7 +4306,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.10.6", ] [[package]] @@ -3745,6 +4315,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.6" @@ -3753,7 +4336,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.10.6", ] [[package]] @@ -3801,6 +4384,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +[[package]] +name = "simple-mutex" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" +dependencies = [ + "event-listener", +] + [[package]] name = "simple_logger" version = "4.1.0" @@ -3871,6 +4463,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "sptr" version = "0.3.2" @@ -3984,6 +4582,28 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "surf" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718b1ae6b50351982dedff021db0def601677f2120938b070eadb10ba4038dd7" +dependencies = [ + "async-std", + "async-trait", + "cfg-if 1.0.0", + "futures-util", + "getrandom 0.2.9", + "http-client", + "http-types", + "log", + "mime_guess", + "once_cell", + "pin-project-lite", + "rustls", + "serde", + "serde_json", +] + [[package]] name = "syn" version = "1.0.109" @@ -4418,6 +5038,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -4473,12 +5102,28 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "unsafe-libyaml" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.3.1" @@ -4488,6 +5133,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4514,6 +5160,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4552,6 +5204,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -4878,7 +5536,7 @@ checksum = "fadbe31e3c1b6f3e398ad172b169152ae1a743ae6efd5f9ffb34019983319d99" dependencies = [ "cfg-if 1.0.0", "generational-arena", - "getrandom", + "getrandom 0.2.9", "libc", "thiserror", "tracing", @@ -4916,6 +5574,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" +dependencies = [ + "webpki", +] + [[package]] name = "which" version = "4.4.0" @@ -5272,14 +5949,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" dependencies = [ - "aes", + "aes 0.7.5", "byteorder", "bzip2", "constant_time_eq", "crc32fast", "crossbeam-utils", "flate2", - "hmac", + "hmac 0.12.1", "pbkdf2", "sha1 0.10.5", "time 0.3.20", diff --git a/boa_examples/Cargo.toml b/boa_examples/Cargo.toml index fde260b8c0a..c3f9814f388 100644 --- a/boa_examples/Cargo.toml +++ b/boa_examples/Cargo.toml @@ -18,3 +18,6 @@ boa_parser.workspace = true boa_runtime.workspace = true smol = "1.3.0" futures-util = "0.3.28" +surf = { version = "2.3.2", default-features = false, features = [ + "h1-client-rustls", +] } diff --git a/boa_examples/src/bin/module_fetch.rs b/boa_examples/src/bin/module_fetch.rs new file mode 100644 index 00000000000..1c081874f9b --- /dev/null +++ b/boa_examples/src/bin/module_fetch.rs @@ -0,0 +1,249 @@ +use std::{ + cell::{Cell, RefCell}, + collections::VecDeque, + rc::Rc, +}; + +use boa_engine::{ + builtins::promise::PromiseState, + job::{FutureJob, JobQueue, NativeJob}, + module::ModuleLoader, + string::utf16, + Context, JsNativeError, JsResult, JsString, JsValue, Module, +}; +use boa_parser::Source; +use futures_util::{stream::FuturesUnordered, StreamExt}; +use smol::{future, LocalExecutor}; +use surf::{middleware::Redirect, Client}; + +// Most of the boilerplate is taken from the `futures.rs` example. +// This file only explains what is exclusive of async module loading. + +#[derive(Debug, Default)] +struct HttpModuleLoader; + +impl ModuleLoader for HttpModuleLoader { + fn load_imported_module( + &self, + _referrer: boa_engine::module::Referrer, + specifier: JsString, + finish_load: Box, &mut Context<'_>)>, + context: &mut Context<'_>, + ) { + let url = specifier.to_std_string_escaped(); + + let fetch = async move { + // `surf` requires to manually specify following redirects. + let client = Client::default().with(Redirect::default()); + + // Adding some prints to show the non-deterministic nature of the async fetches. + // Try to run the example several times to see how sometimes the fetches start in order + // but finish in disorder. + println!("Fetching `{url}`..."); + // This could also retry fetching in case there's an error while requesting the module. + let body = client.get(&url).recv_string().await; + println!("Finished fetching `{url}`!"); + + // Since the async context cannot take the `context` by ref, we have to continue + // parsing inside a new `NativeJob` that will be enqueued into the promise job queue. + NativeJob::new(move |context| -> JsResult { + let body = match body { + Ok(body) => body, + Err(err) => { + // On error we always call `finish_load` to notify the load promise about the + // error. + finish_load( + Err(JsNativeError::typ().with_message(err.to_string()).into()), + context, + ); + + // Just returns anything to comply with `NativeJob::new`'s signature. + return Ok(JsValue::undefined()); + } + }; + + // Could also add a path if needed. + let source = Source::from_bytes(body.as_bytes()); + + let module = Module::parse(source, None, context); + + // We don't do any error handling, `finish_load` takes care of that for us. + finish_load(module, context); + + // Also needed to match `NativeJob::new`. + Ok(JsValue::undefined()) + }) + }; + + // Just enqueue the future for now. We'll advance all the enqueued futures inside our custom + // `JobQueue`. + context + .job_queue() + .enqueue_future_job(Box::pin(fetch), context) + } +} + +fn main() { + // A simple snippet that imports modules from the web instead of the file system. + const SRC: &str = r#" + import YAML from 'https://esm.run/yaml'; + import fromAsync from 'https://esm.run/array-from-async'; + import { Base64 } from 'https://esm.run/js-base64'; + + const data = ` + object: + array: ["hello", "world"] + key: "value" + `; + + const object = YAML.parse(data).object; + + let result = await fromAsync([ + Promise.resolve(Base64.encode(object.array[0])), + Promise.resolve(Base64.encode(object.array[1])), + ]); + + export default result; + "#; + + let executor = LocalExecutor::new(); + let loader: &dyn ModuleLoader = &HttpModuleLoader; + let queue: Rc = Rc::new(Queue::new(executor)); + let context = &mut Context::builder() + .job_queue(queue) + // NEW: sets the context module loader to our custom loader + .module_loader(loader) + .build() + .unwrap(); + + let module = Module::parse(Source::from_bytes(SRC.as_bytes()), None, context).unwrap(); + + // Calling `Module::load_link_evaluate` takes care of having to define promise handlers for + // `Module::load` and `Module::evaluate`. + let promise = module.load_link_evaluate(context).unwrap(); + + // Important to call `Context::run_jobs`, or else all the futures and promises won't be + // pushed forward by the job queue. + context.run_jobs(); + + match promise.state().unwrap() { + // Our job queue guarantees that all promises and futures are finished after returning + // from `Context::run_jobs`. + // Some other job queue designs only execute a "microtick" or a single pass through the + // pending promises and futures. In that case, you can pass this logic as a promise handler + // for `promise` instead. + PromiseState::Pending => panic!("module didn't execute!"), + // All modules after successfully evaluating return `JsValue::undefined()`. + PromiseState::Fulfilled(v) => { + assert_eq!(v, JsValue::undefined()) + } + PromiseState::Rejected(err) => { + panic!("{}", err.display()); + } + } + + let default = module.namespace(context).get("default", context).unwrap(); + // `default` should contain the result of our calculations. + let default = default.as_object().unwrap(); + + assert_eq!( + default.get(0, context).unwrap().as_string().unwrap(), + utf16!("aGVsbG8=") + ); + assert_eq!( + default.get(1, context).unwrap().as_string().unwrap(), + utf16!("d29ybGQ=") + ); +} + +// Taken from the `futures.rs` example. +struct Queue<'a> { + executor: LocalExecutor<'a>, + futures: RefCell>, + jobs: RefCell>, +} + +impl<'a> Queue<'a> { + fn new(executor: LocalExecutor<'a>) -> Self { + Self { + executor, + futures: RefCell::default(), + jobs: RefCell::default(), + } + } +} + +impl<'a> JobQueue for Queue<'a> { + fn enqueue_promise_job(&self, job: NativeJob, _context: &mut boa_engine::Context<'_>) { + self.jobs.borrow_mut().push_back(job); + } + + fn enqueue_future_job(&self, future: FutureJob, _context: &mut boa_engine::Context<'_>) { + self.futures.borrow().push(future) + } + + fn run_jobs(&self, context: &mut boa_engine::Context<'_>) { + // Early return in case there were no jobs scheduled. + if self.jobs.borrow().is_empty() && self.futures.borrow().is_empty() { + return; + } + + let context = RefCell::new(context); + + future::block_on(self.executor.run(async move { + // Used to sync the finalization of both tasks + let finished = Cell::new(0b00u8); + + let fqueue = async { + loop { + if self.futures.borrow().is_empty() { + finished.set(finished.get() | 0b01); + if finished.get() >= 0b11 { + // All possible futures and jobs were completed. Exit. + return; + } + // All possible jobs were completed, but `jqueue` could have + // pending jobs. Yield to the executor to try to progress on + // `jqueue` until we have more pending futures. + future::yield_now().await; + continue; + } + finished.set(finished.get() & 0b10); + + let futures = &mut std::mem::take(&mut *self.futures.borrow_mut()); + while let Some(job) = futures.next().await { + self.enqueue_promise_job(job, &mut context.borrow_mut()); + } + } + }; + + let jqueue = async { + loop { + if self.jobs.borrow().is_empty() { + finished.set(finished.get() | 0b10); + if finished.get() >= 0b11 { + // All possible futures and jobs were completed. Exit. + return; + } + // All possible jobs were completed, but `fqueue` could have + // pending futures. Yield to the executor to try to progress on + // `fqueue` until we have more pending jobs. + future::yield_now().await; + continue; + }; + finished.set(finished.get() & 0b01); + + let jobs = std::mem::take(&mut *self.jobs.borrow_mut()); + for job in jobs { + if let Err(e) = job.call(&mut context.borrow_mut()) { + eprintln!("Uncaught {e}"); + } + future::yield_now().await; + } + } + }; + + future::zip(fqueue, jqueue).await; + })) + } +}