vendored in interesting macro, some config stuff

Orual 6b7587e4 354b93a1

+945 -21
+394 -3
Cargo.lock
··· 43 43 checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 44 44 45 45 [[package]] 46 + name = "ahash" 47 + version = "0.8.12" 48 + source = "registry+https://github.com/rust-lang/crates.io-index" 49 + checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" 50 + dependencies = [ 51 + "cfg-if", 52 + "once_cell", 53 + "version_check", 54 + "zerocopy", 55 + ] 56 + 57 + [[package]] 46 58 name = "aho-corasick" 47 59 version = "1.1.4" 48 60 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 144 156 checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 145 157 146 158 [[package]] 159 + name = "ar_archive_writer" 160 + version = "0.2.0" 161 + source = "registry+https://github.com/rust-lang/crates.io-index" 162 + checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" 163 + dependencies = [ 164 + "object 0.32.2", 165 + ] 166 + 167 + [[package]] 147 168 name = "arraydeque" 148 169 version = "0.5.1" 149 170 source = "registry+https://github.com/rust-lang/crates.io-index" 150 171 checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" 151 172 152 173 [[package]] 174 + name = "arrayvec" 175 + version = "0.7.6" 176 + source = "registry+https://github.com/rust-lang/crates.io-index" 177 + checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 178 + 179 + [[package]] 153 180 name = "ascii" 154 181 version = "1.1.0" 155 182 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 181 208 version = "0.13.0" 182 209 source = "registry+https://github.com/rust-lang/crates.io-index" 183 210 checksum = "3df27b8d5ddb458c5fb1bbc1ce172d4a38c614a97d550b0ac89003897fb01de4" 211 + 212 + [[package]] 213 + name = "ast_node" 214 + version = "3.0.4" 215 + source = "registry+https://github.com/rust-lang/crates.io-index" 216 + checksum = "0a184645bcc6f52d69d8e7639720699c6a99efb711f886e251ed1d16db8dd90e" 217 + dependencies = [ 218 + "quote", 219 + "swc_macros_common", 220 + "syn 2.0.110", 221 + ] 184 222 185 223 [[package]] 186 224 name = "async-broadcast" ··· 418 456 "cfg-if", 419 457 "libc", 420 458 "miniz_oxide", 421 - "object", 459 + "object 0.37.3", 422 460 "rustc-demangle", 423 461 "windows-link 0.2.1", 424 462 ] ··· 477 515 version = "1.8.0" 478 516 source = "registry+https://github.com/rust-lang/crates.io-index" 479 517 checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" 518 + 519 + [[package]] 520 + name = "better_scoped_tls" 521 + version = "1.0.1" 522 + source = "registry+https://github.com/rust-lang/crates.io-index" 523 + checksum = "7cd228125315b132eed175bf47619ac79b945b26e56b848ba203ae4ea8603609" 524 + dependencies = [ 525 + "scoped-tls", 526 + ] 480 527 481 528 [[package]] 482 529 name = "bincode" ··· 651 698 version = "3.19.0" 652 699 source = "registry+https://github.com/rust-lang/crates.io-index" 653 700 checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 701 + dependencies = [ 702 + "allocator-api2", 703 + ] 654 704 655 705 [[package]] 656 706 name = "byteorder" ··· 664 714 source = "registry+https://github.com/rust-lang/crates.io-index" 665 715 checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 666 716 dependencies = [ 717 + "serde", 718 + ] 719 + 720 + [[package]] 721 + name = "bytes-str" 722 + version = "0.2.7" 723 + source = "registry+https://github.com/rust-lang/crates.io-index" 724 + checksum = "7c60b5ce37e0b883c37eb89f79a1e26fbe9c1081945d024eee93e8d91a7e18b3" 725 + dependencies = [ 726 + "bytes", 667 727 "serde", 668 728 ] 669 729 ··· 1165 1225 checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" 1166 1226 dependencies = [ 1167 1227 "memchr", 1228 + ] 1229 + 1230 + [[package]] 1231 + name = "cow-replace" 1232 + version = "0.1.1" 1233 + source = "registry+https://github.com/rust-lang/crates.io-index" 1234 + checksum = "a6cab584c4b83b5b36f81a10bd15191fd77f70432d624787ee68ec64edd6d7ed" 1235 + dependencies = [ 1236 + "ascii", 1168 1237 ] 1169 1238 1170 1239 [[package]] ··· 2219 2288 ] 2220 2289 2221 2290 [[package]] 2291 + name = "dioxus-use-js-macro" 2292 + version = "0.1.0" 2293 + dependencies = [ 2294 + "proc-macro2", 2295 + "quote", 2296 + "swc_common", 2297 + "swc_ecma_ast", 2298 + "swc_ecma_parser", 2299 + "swc_ecma_visit", 2300 + "syn 2.0.110", 2301 + ] 2302 + 2303 + [[package]] 2222 2304 name = "dioxus-web" 2223 2305 version = "0.7.1" 2224 2306 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2789 2871 ] 2790 2872 2791 2873 [[package]] 2874 + name = "from_variant" 2875 + version = "2.0.2" 2876 + source = "registry+https://github.com/rust-lang/crates.io-index" 2877 + checksum = "308530a56b099da144ebc5d8e179f343ad928fa2b3558d1eb3db9af18d6eff43" 2878 + dependencies = [ 2879 + "swc_macros_common", 2880 + "syn 2.0.110", 2881 + ] 2882 + 2883 + [[package]] 2792 2884 name = "futf" 2793 2885 version = "0.1.5" 2794 2886 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3409 3501 version = "0.14.5" 3410 3502 source = "registry+https://github.com/rust-lang/crates.io-index" 3411 3503 checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 3504 + dependencies = [ 3505 + "ahash", 3506 + "allocator-api2", 3507 + ] 3412 3508 3413 3509 [[package]] 3414 3510 name = "hashbrown" ··· 3565 3661 ] 3566 3662 3567 3663 [[package]] 3664 + name = "hstr" 3665 + version = "1.1.6" 3666 + source = "registry+https://github.com/rust-lang/crates.io-index" 3667 + checksum = "b85186bc48d3c611ead052cc3f907748e40b63d73a99e4ed34d18063e2baaf1b" 3668 + dependencies = [ 3669 + "hashbrown 0.14.5", 3670 + "new_debug_unreachable", 3671 + "once_cell", 3672 + "rustc-hash 2.1.1", 3673 + "triomphe", 3674 + ] 3675 + 3676 + [[package]] 3568 3677 name = "html5ever" 3569 3678 version = "0.27.0" 3570 3679 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3983 4092 ] 3984 4093 3985 4094 [[package]] 4095 + name = "is-macro" 4096 + version = "0.3.7" 4097 + source = "registry+https://github.com/rust-lang/crates.io-index" 4098 + checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" 4099 + dependencies = [ 4100 + "heck 0.5.0", 4101 + "proc-macro2", 4102 + "quote", 4103 + "syn 2.0.110", 4104 + ] 4105 + 4106 + [[package]] 3986 4107 name = "is_ci" 3987 4108 version = "1.2.0" 3988 4109 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4193 4314 "serde_html_form", 4194 4315 "serde_json", 4195 4316 "sha2", 4196 - "signature", 4197 4317 "smol_str", 4198 4318 "thiserror 2.0.17", 4199 4319 "tokio", ··· 5162 5282 ] 5163 5283 5164 5284 [[package]] 5285 + name = "num-bigint" 5286 + version = "0.4.6" 5287 + source = "registry+https://github.com/rust-lang/crates.io-index" 5288 + checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 5289 + dependencies = [ 5290 + "num-integer", 5291 + "num-traits", 5292 + "serde", 5293 + ] 5294 + 5295 + [[package]] 5165 5296 name = "num-bigint-dig" 5166 5297 version = "0.8.6" 5167 5298 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5371 5502 5372 5503 [[package]] 5373 5504 name = "object" 5505 + version = "0.32.2" 5506 + source = "registry+https://github.com/rust-lang/crates.io-index" 5507 + checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 5508 + dependencies = [ 5509 + "memchr", 5510 + ] 5511 + 5512 + [[package]] 5513 + name = "object" 5374 5514 version = "0.37.3" 5375 5515 source = "registry+https://github.com/rust-lang/crates.io-index" 5376 5516 checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" ··· 5619 5759 source = "registry+https://github.com/rust-lang/crates.io-index" 5620 5760 checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" 5621 5761 dependencies = [ 5622 - "phf_macros", 5762 + "phf_macros 0.10.0", 5623 5763 "phf_shared 0.10.0", 5624 5764 "proc-macro-hack", 5625 5765 ] ··· 5630 5770 source = "registry+https://github.com/rust-lang/crates.io-index" 5631 5771 checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" 5632 5772 dependencies = [ 5773 + "phf_macros 0.11.3", 5633 5774 "phf_shared 0.11.3", 5634 5775 ] 5635 5776 ··· 5698 5839 ] 5699 5840 5700 5841 [[package]] 5842 + name = "phf_macros" 5843 + version = "0.11.3" 5844 + source = "registry+https://github.com/rust-lang/crates.io-index" 5845 + checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" 5846 + dependencies = [ 5847 + "phf_generator 0.11.3", 5848 + "phf_shared 0.11.3", 5849 + "proc-macro2", 5850 + "quote", 5851 + "syn 2.0.110", 5852 + ] 5853 + 5854 + [[package]] 5701 5855 name = "phf_shared" 5702 5856 version = "0.8.0" 5703 5857 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5962 6116 version = "2.0.11" 5963 6117 source = "registry+https://github.com/rust-lang/crates.io-index" 5964 6118 checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" 6119 + 6120 + [[package]] 6121 + name = "psm" 6122 + version = "0.1.28" 6123 + source = "registry+https://github.com/rust-lang/crates.io-index" 6124 + checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" 6125 + dependencies = [ 6126 + "ar_archive_writer", 6127 + "cc", 6128 + ] 5965 6129 5966 6130 [[package]] 5967 6131 name = "publicsuffix" ··· 6676 6840 ] 6677 6841 6678 6842 [[package]] 6843 + name = "seq-macro" 6844 + version = "0.3.6" 6845 + source = "registry+https://github.com/rust-lang/crates.io-index" 6846 + checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" 6847 + 6848 + [[package]] 6679 6849 name = "serde" 6680 6850 version = "1.0.228" 6681 6851 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7048 7218 checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 7049 7219 7050 7220 [[package]] 7221 + name = "smartstring" 7222 + version = "1.0.1" 7223 + source = "registry+https://github.com/rust-lang/crates.io-index" 7224 + checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" 7225 + dependencies = [ 7226 + "autocfg", 7227 + "static_assertions", 7228 + "version_check", 7229 + ] 7230 + 7231 + [[package]] 7051 7232 name = "smol_str" 7052 7233 version = "0.3.4" 7053 7234 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7150 7331 checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 7151 7332 7152 7333 [[package]] 7334 + name = "stacker" 7335 + version = "0.1.22" 7336 + source = "registry+https://github.com/rust-lang/crates.io-index" 7337 + checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" 7338 + dependencies = [ 7339 + "cc", 7340 + "cfg-if", 7341 + "libc", 7342 + "psm", 7343 + "windows-sys 0.59.0", 7344 + ] 7345 + 7346 + [[package]] 7153 7347 name = "static-regular-grammar" 7154 7348 version = "2.0.2" 7155 7349 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7198 7392 "phf_shared 0.11.3", 7199 7393 "proc-macro2", 7200 7394 "quote", 7395 + ] 7396 + 7397 + [[package]] 7398 + name = "string_enum" 7399 + version = "1.0.2" 7400 + source = "registry+https://github.com/rust-lang/crates.io-index" 7401 + checksum = "ae36a4951ca7bd1cfd991c241584a9824a70f6aff1e7d4f693fb3f2465e4030e" 7402 + dependencies = [ 7403 + "quote", 7404 + "swc_macros_common", 7405 + "syn 2.0.110", 7201 7406 ] 7202 7407 7203 7408 [[package]] ··· 7260 7465 version = "3.0.0" 7261 7466 source = "registry+https://github.com/rust-lang/crates.io-index" 7262 7467 checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" 7468 + 7469 + [[package]] 7470 + name = "swc_allocator" 7471 + version = "4.0.1" 7472 + source = "registry+https://github.com/rust-lang/crates.io-index" 7473 + checksum = "9d7eefd2c8b228a8c73056482b2ae4b3a1071fbe07638e3b55ceca8570cc48bb" 7474 + dependencies = [ 7475 + "allocator-api2", 7476 + "bumpalo", 7477 + "rustc-hash 2.1.1", 7478 + ] 7479 + 7480 + [[package]] 7481 + name = "swc_atoms" 7482 + version = "6.0.1" 7483 + source = "registry+https://github.com/rust-lang/crates.io-index" 7484 + checksum = "6fda66fe4175cddc27a79643ded7ce297b6b2bf133f038ec5907fb4673e4b2ba" 7485 + dependencies = [ 7486 + "hstr", 7487 + "once_cell", 7488 + "serde", 7489 + ] 7490 + 7491 + [[package]] 7492 + name = "swc_common" 7493 + version = "13.0.1" 7494 + source = "registry+https://github.com/rust-lang/crates.io-index" 7495 + checksum = "6865f71f363e63306cedec3f3cf1cb9e80acaa9229261ba2569467a19060c7c8" 7496 + dependencies = [ 7497 + "anyhow", 7498 + "ast_node", 7499 + "better_scoped_tls", 7500 + "bytes-str", 7501 + "cfg-if", 7502 + "either", 7503 + "from_variant", 7504 + "new_debug_unreachable", 7505 + "num-bigint", 7506 + "once_cell", 7507 + "rustc-hash 2.1.1", 7508 + "serde", 7509 + "siphasher 0.3.11", 7510 + "swc_allocator", 7511 + "swc_atoms", 7512 + "swc_eq_ignore_macros", 7513 + "swc_visit", 7514 + "tracing", 7515 + "unicode-width 0.1.14", 7516 + "url", 7517 + ] 7518 + 7519 + [[package]] 7520 + name = "swc_ecma_ast" 7521 + version = "13.0.0" 7522 + source = "registry+https://github.com/rust-lang/crates.io-index" 7523 + checksum = "f1ddc264ed13ae03aa30e1c89798502f9ddbe765a4ad695054add1074ffbc5cb" 7524 + dependencies = [ 7525 + "bitflags 2.10.0", 7526 + "is-macro", 7527 + "num-bigint", 7528 + "once_cell", 7529 + "phf 0.11.3", 7530 + "rustc-hash 2.1.1", 7531 + "scoped-tls", 7532 + "string_enum", 7533 + "swc_atoms", 7534 + "swc_common", 7535 + "swc_visit", 7536 + "unicode-id-start", 7537 + ] 7538 + 7539 + [[package]] 7540 + name = "swc_ecma_lexer" 7541 + version = "17.0.6" 7542 + source = "registry+https://github.com/rust-lang/crates.io-index" 7543 + checksum = "d8f318a247bc2c4662dc10dccd7a4f64834add015d216e977a58665b0aad9772" 7544 + dependencies = [ 7545 + "arrayvec", 7546 + "ascii", 7547 + "bitflags 2.10.0", 7548 + "cow-replace", 7549 + "either", 7550 + "new_debug_unreachable", 7551 + "num-bigint", 7552 + "num-traits", 7553 + "phf 0.11.3", 7554 + "rustc-hash 2.1.1", 7555 + "seq-macro", 7556 + "serde", 7557 + "smallvec", 7558 + "smartstring", 7559 + "stacker", 7560 + "swc_atoms", 7561 + "swc_common", 7562 + "swc_ecma_ast", 7563 + "tracing", 7564 + "typed-arena", 7565 + ] 7566 + 7567 + [[package]] 7568 + name = "swc_ecma_parser" 7569 + version = "17.0.1" 7570 + source = "registry+https://github.com/rust-lang/crates.io-index" 7571 + checksum = "3ff5b5fbe4316b7d1272ac6f204a871f0d5785755d6a14ddf38e7fa8af73be30" 7572 + dependencies = [ 7573 + "arrayvec", 7574 + "bitflags 2.10.0", 7575 + "either", 7576 + "new_debug_unreachable", 7577 + "num-bigint", 7578 + "num-traits", 7579 + "phf 0.11.3", 7580 + "rustc-hash 2.1.1", 7581 + "serde", 7582 + "smallvec", 7583 + "smartstring", 7584 + "swc_atoms", 7585 + "swc_common", 7586 + "swc_ecma_ast", 7587 + "swc_ecma_lexer", 7588 + "tracing", 7589 + "typed-arena", 7590 + ] 7591 + 7592 + [[package]] 7593 + name = "swc_ecma_visit" 7594 + version = "13.0.0" 7595 + source = "registry+https://github.com/rust-lang/crates.io-index" 7596 + checksum = "7ad28e3449b376bfe1f2bde28bfcf305961ba23c1e205bedb03a7c108a1d1ff6" 7597 + dependencies = [ 7598 + "new_debug_unreachable", 7599 + "num-bigint", 7600 + "swc_atoms", 7601 + "swc_common", 7602 + "swc_ecma_ast", 7603 + "swc_visit", 7604 + "tracing", 7605 + ] 7606 + 7607 + [[package]] 7608 + name = "swc_eq_ignore_macros" 7609 + version = "1.0.1" 7610 + source = "registry+https://github.com/rust-lang/crates.io-index" 7611 + checksum = "c16ce73424a6316e95e09065ba6a207eba7765496fed113702278b7711d4b632" 7612 + dependencies = [ 7613 + "proc-macro2", 7614 + "quote", 7615 + "syn 2.0.110", 7616 + ] 7617 + 7618 + [[package]] 7619 + name = "swc_macros_common" 7620 + version = "1.0.1" 7621 + source = "registry+https://github.com/rust-lang/crates.io-index" 7622 + checksum = "aae1efbaa74943dc5ad2a2fb16cbd78b77d7e4d63188f3c5b4df2b4dcd2faaae" 7623 + dependencies = [ 7624 + "proc-macro2", 7625 + "quote", 7626 + "syn 2.0.110", 7627 + ] 7628 + 7629 + [[package]] 7630 + name = "swc_visit" 7631 + version = "2.0.1" 7632 + source = "registry+https://github.com/rust-lang/crates.io-index" 7633 + checksum = "62fb71484b486c185e34d2172f0eabe7f4722742aad700f426a494bb2de232a2" 7634 + dependencies = [ 7635 + "either", 7636 + "new_debug_unreachable", 7637 + ] 7263 7638 7264 7639 [[package]] 7265 7640 name = "syn" ··· 8057 8432 version = "0.1.15" 8058 8433 source = "registry+https://github.com/rust-lang/crates.io-index" 8059 8434 checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" 8435 + dependencies = [ 8436 + "serde", 8437 + "stable_deref_trait", 8438 + ] 8060 8439 8061 8440 [[package]] 8062 8441 name = "try-lock" ··· 8130 8509 ] 8131 8510 8132 8511 [[package]] 8512 + name = "typed-arena" 8513 + version = "2.0.2" 8514 + source = "registry+https://github.com/rust-lang/crates.io-index" 8515 + checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" 8516 + 8517 + [[package]] 8133 8518 name = "typenum" 8134 8519 version = "1.19.0" 8135 8520 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 8151 8536 version = "2.8.1" 8152 8537 source = "registry+https://github.com/rust-lang/crates.io-index" 8153 8538 checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" 8539 + 8540 + [[package]] 8541 + name = "unicode-id-start" 8542 + version = "1.4.0" 8543 + source = "registry+https://github.com/rust-lang/crates.io-index" 8544 + checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" 8154 8545 8155 8546 [[package]] 8156 8547 name = "unicode-ident"
+22
crates/use-js-macro/Cargo.toml
··· 1 + [package] 2 + name = "dioxus-use-js-macro" 3 + version = { workspace = true } 4 + authors = ["Dillon Henry McMahon"] 5 + edition = "2021" 6 + description = "javascript use bridge macro for Dioxus" 7 + license = "MIT OR Apache-2.0" 8 + repository = "https://github.com/DioxusLabs/dioxus/" 9 + homepage = "https://dioxuslabs.com" 10 + keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 + 12 + [lib] 13 + proc-macro = true 14 + 15 + [dependencies] 16 + proc-macro2 = "1.0" 17 + quote = "1.0" 18 + syn = { version = "2.0", features = ["full"] } 19 + swc_ecma_parser = { version = "=17.0.1", default-features = false } 20 + swc_ecma_ast = { version = "=13.0.0", default-features = false } 21 + swc_ecma_visit = { version = "=13.0.0", default-features = false } 22 + swc_common = { version = "=13.0.1", default-features = false }
+481
crates/use-js-macro/src/lib.rs
··· 1 + use proc_macro::TokenStream; 2 + use proc_macro2::TokenStream as TokenStream2; 3 + use quote::{format_ident, quote}; 4 + use std::{fs, path::Path}; 5 + use swc_common::comments::{CommentKind, Comments}; 6 + use swc_common::Spanned; 7 + use swc_common::{comments::SingleThreadedComments, SourceMap, Span}; 8 + use swc_ecma_ast::{ 9 + Decl, ExportDecl, ExportSpecifier, FnDecl, ModuleExportName, NamedExport, Param, Pat, 10 + VarDeclarator, 11 + }; 12 + use swc_ecma_parser::EsSyntax; 13 + use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax}; 14 + use swc_ecma_visit::{Visit, VisitWith}; 15 + use syn::{ 16 + parse::{Parse, ParseStream}, 17 + parse_macro_input, Ident, LitStr, Result, Token, 18 + }; 19 + 20 + #[derive(Debug, Clone)] 21 + enum ImportSpec { 22 + /// * 23 + All, 24 + /// {greeting, other_func} 25 + Named(Vec<Ident>), 26 + /// greeting 27 + Single(Ident), 28 + } 29 + 30 + struct UseJsInput { 31 + asset_path: LitStr, 32 + import_spec: ImportSpec, 33 + } 34 + 35 + impl Parse for UseJsInput { 36 + fn parse(input: ParseStream) -> Result<Self> { 37 + let asset_path: LitStr = input.parse()?; 38 + input.parse::<Token![::]>()?; 39 + 40 + let import_spec = if input.peek(Token![*]) { 41 + input.parse::<Token![*]>()?; 42 + ImportSpec::All 43 + } else if input.peek(syn::token::Brace) { 44 + let content; 45 + syn::braced!(content in input); 46 + let mut functions = Vec::new(); 47 + 48 + loop { 49 + let ident: Ident = content.parse()?; 50 + functions.push(ident); 51 + 52 + if content.peek(Token![,]) { 53 + content.parse::<Token![,]>()?; 54 + if content.is_empty() { 55 + break; 56 + } 57 + } else { 58 + break; 59 + } 60 + } 61 + 62 + ImportSpec::Named(functions) 63 + } else { 64 + let ident: Ident = input.parse()?; 65 + ImportSpec::Single(ident) 66 + }; 67 + 68 + Ok(UseJsInput { 69 + asset_path, 70 + import_spec, 71 + }) 72 + } 73 + } 74 + 75 + #[derive(Debug, Clone)] 76 + struct FunctionInfo { 77 + name: String, 78 + /// If specified in the use declaration 79 + name_ident: Option<Ident>, 80 + params: Vec<String>, 81 + is_exported: bool, 82 + /// The stripped lines 83 + doc_comment: Vec<String>, 84 + } 85 + 86 + struct FunctionVisitor { 87 + functions: Vec<FunctionInfo>, 88 + comments: SingleThreadedComments, 89 + } 90 + 91 + impl FunctionVisitor { 92 + fn new(comments: SingleThreadedComments) -> Self { 93 + Self { 94 + functions: Vec::new(), 95 + comments, 96 + } 97 + } 98 + 99 + fn extract_doc_comment(&self, span: Span) -> Vec<String> { 100 + // Get leading comments for the span 101 + let leading_comment = self.comments.get_leading(span.lo()); 102 + 103 + if let Some(comments) = leading_comment { 104 + let mut doc_lines = Vec::new(); 105 + 106 + for comment in comments.iter() { 107 + let comment_text = &comment.text; 108 + match comment.kind { 109 + // Handle `///`. `//` is already stripped 110 + CommentKind::Line => { 111 + if let Some(content) = comment_text.strip_prefix("/") { 112 + let cleaned = content.trim_start(); 113 + doc_lines.push(cleaned.to_string()); 114 + } 115 + } 116 + // Handle `/*` `*/`. `/*` `*/` is already stripped 117 + CommentKind::Block => { 118 + for line in comment_text.lines() { 119 + if let Some(cleaned) = line.trim_start().strip_prefix("*") { 120 + doc_lines.push(cleaned.to_string()); 121 + } 122 + } 123 + } 124 + }; 125 + } 126 + 127 + doc_lines 128 + } else { 129 + Vec::new() 130 + } 131 + } 132 + } 133 + 134 + fn function_params_to_names(params: &[Param]) -> Vec<String> { 135 + params 136 + .iter() 137 + .enumerate() 138 + .map(|(i, param)| { 139 + if let Some(ident) = param.pat.as_ident() { 140 + ident.id.sym.to_string() 141 + } else { 142 + format!("arg{}", i) 143 + } 144 + }) 145 + .collect() 146 + } 147 + 148 + fn function_pat_to_names(pats: &[Pat]) -> Vec<String> { 149 + pats.iter() 150 + .enumerate() 151 + .map(|(i, pat)| { 152 + if let Some(ident) = pat.as_ident() { 153 + ident.id.sym.to_string() 154 + } else { 155 + format!("arg{}", i) 156 + } 157 + }) 158 + .collect() 159 + } 160 + 161 + impl Visit for FunctionVisitor { 162 + /// Visit function declarations: function foo() {} 163 + fn visit_fn_decl(&mut self, node: &FnDecl) { 164 + let doc_comment = self.extract_doc_comment(node.span()); 165 + 166 + self.functions.push(FunctionInfo { 167 + name: node.ident.sym.to_string(), 168 + name_ident: None, 169 + params: function_params_to_names(&node.function.params), 170 + is_exported: false, 171 + doc_comment, 172 + }); 173 + node.visit_children_with(self); 174 + } 175 + 176 + /// Visit function expressions: const foo = function() {} 177 + fn visit_var_declarator(&mut self, node: &VarDeclarator) { 178 + if let swc_ecma_ast::Pat::Ident(ident) = &node.name { 179 + if let Some(init) = &node.init { 180 + let doc_comment = self.extract_doc_comment(node.span()); 181 + 182 + match &**init { 183 + swc_ecma_ast::Expr::Fn(fn_expr) => { 184 + self.functions.push(FunctionInfo { 185 + name: ident.id.sym.to_string(), 186 + name_ident: None, 187 + params: function_params_to_names(&fn_expr.function.params), 188 + is_exported: false, 189 + doc_comment, 190 + }); 191 + } 192 + swc_ecma_ast::Expr::Arrow(arrow_fn) => { 193 + self.functions.push(FunctionInfo { 194 + name: ident.id.sym.to_string(), 195 + name_ident: None, 196 + params: function_pat_to_names(&arrow_fn.params), 197 + is_exported: false, 198 + doc_comment, 199 + }); 200 + } 201 + _ => {} 202 + } 203 + } 204 + } 205 + node.visit_children_with(self); 206 + } 207 + 208 + /// Visit export declarations: export function foo() {} 209 + fn visit_export_decl(&mut self, node: &ExportDecl) { 210 + if let Decl::Fn(fn_decl) = &node.decl { 211 + let doc_comment = self.extract_doc_comment(node.span()); 212 + 213 + self.functions.push(FunctionInfo { 214 + name: fn_decl.ident.sym.to_string(), 215 + name_ident: None, 216 + params: function_params_to_names(&fn_decl.function.params), 217 + is_exported: true, 218 + doc_comment, 219 + }); 220 + } 221 + node.visit_children_with(self); 222 + } 223 + 224 + /// Visit named exports: export { foo } 225 + fn visit_named_export(&mut self, node: &NamedExport) { 226 + for spec in &node.specifiers { 227 + if let ExportSpecifier::Named(named) = spec { 228 + let name = match &named.orig { 229 + ModuleExportName::Ident(ident) => ident.sym.to_string(), 230 + ModuleExportName::Str(str_lit) => str_lit.value.to_string(), 231 + }; 232 + 233 + if let Some(func) = self.functions.iter_mut().find(|f| f.name == name) { 234 + func.is_exported = true; 235 + } 236 + } 237 + } 238 + node.visit_children_with(self); 239 + } 240 + } 241 + 242 + fn parse_js_file(file_path: &Path) -> Result<Vec<FunctionInfo>> { 243 + let js_content = fs::read_to_string(file_path).map_err(|e| { 244 + syn::Error::new( 245 + proc_macro2::Span::call_site(), 246 + format!( 247 + "Could not read JavaScript file '{}': {}", 248 + file_path.display(), 249 + e 250 + ), 251 + ) 252 + })?; 253 + 254 + let cm = SourceMap::default(); 255 + let fm = cm.new_source_file( 256 + swc_common::FileName::Custom(file_path.display().to_string()).into(), 257 + js_content.clone(), 258 + ); 259 + let comments = SingleThreadedComments::default(); 260 + let lexer = Lexer::new( 261 + Syntax::Es(EsSyntax::default()), 262 + Default::default(), 263 + StringInput::from(&*fm), 264 + Some(&comments), 265 + ); 266 + 267 + let mut parser = Parser::new_from(lexer); 268 + 269 + let module = parser.parse_module().map_err(|e| { 270 + syn::Error::new( 271 + proc_macro2::Span::call_site(), 272 + format!( 273 + "Failed to parse JavaScript file '{}': {:?}", 274 + file_path.display(), 275 + e 276 + ), 277 + ) 278 + })?; 279 + 280 + let mut visitor = FunctionVisitor::new(comments); 281 + module.visit_with(&mut visitor); 282 + 283 + // Functions are added twice for some reason 284 + visitor 285 + .functions 286 + .dedup_by(|e1, e2| e1.name.as_str() == e2.name.as_str()); 287 + Ok(visitor.functions) 288 + } 289 + 290 + fn remove_function_info(name: &str, functions: &mut Vec<FunctionInfo>) -> Result<FunctionInfo> { 291 + if let Some(pos) = functions.iter().position(|f| f.name == name) { 292 + Ok(functions.remove(pos)) 293 + } else { 294 + Err(syn::Error::new( 295 + proc_macro2::Span::call_site(), 296 + format!("Function '{}' not found in JavaScript file", name), 297 + )) 298 + } 299 + } 300 + 301 + fn get_functions_to_generate( 302 + mut functions: Vec<FunctionInfo>, 303 + import_spec: ImportSpec, 304 + ) -> Result<Vec<FunctionInfo>> { 305 + match import_spec { 306 + ImportSpec::All => Ok(functions), 307 + ImportSpec::Single(name) => { 308 + let mut func = remove_function_info(name.to_string().as_str(), &mut functions)?; 309 + func.name_ident.replace(name); 310 + Ok(vec![func]) 311 + } 312 + ImportSpec::Named(names) => { 313 + let mut result = Vec::new(); 314 + for name in names { 315 + let mut func = remove_function_info(name.to_string().as_str(), &mut functions)?; 316 + func.name_ident.replace(name); 317 + result.push(func); 318 + } 319 + Ok(result) 320 + } 321 + } 322 + } 323 + 324 + fn generate_function_wrapper(func: &FunctionInfo, asset_path: &LitStr) -> TokenStream2 { 325 + let send_calls: Vec<TokenStream2> = func 326 + .params 327 + .iter() 328 + .map(|param| { 329 + let param = format_ident!("{}", param); 330 + quote! { 331 + eval.send(#param)?; 332 + } 333 + }) 334 + .collect(); 335 + 336 + let js_func_name = &func.name; 337 + let mut js_format = format!(r#"const {{{{ {js_func_name} }}}} = await import("{{}}");"#); 338 + for param in func.params.iter() { 339 + js_format.push_str(&format!("\nlet {} = await dioxus.recv();", param)); 340 + } 341 + js_format.push_str(&format!("\nreturn {}(", js_func_name)); 342 + for (i, param) in func.params.iter().enumerate() { 343 + if i > 0 { 344 + js_format.push_str(", "); 345 + } 346 + js_format.push_str(param.as_str()); 347 + } 348 + js_format.push_str(");"); 349 + 350 + let param_types: Vec<_> = func 351 + .params 352 + .iter() 353 + .map(|param| { 354 + let param = format_ident!("{}", param); 355 + quote! { #param: impl serde::Serialize } 356 + }) 357 + .collect(); 358 + 359 + // Generate documentation comment if available - preserve original JSDoc format 360 + let doc_comment = if func.doc_comment.is_empty() { 361 + quote! {} 362 + } else { 363 + let doc_lines: Vec<_> = func 364 + .doc_comment 365 + .iter() 366 + .map(|line| quote! { #[doc = #line] }) 367 + .collect(); 368 + quote! { #(#doc_lines)* } 369 + }; 370 + 371 + let func_name = func 372 + .name_ident 373 + .clone() 374 + // Can not exist if `::*` 375 + .unwrap_or_else(|| Ident::new(func.name.as_str(), proc_macro2::Span::call_site())); 376 + quote! { 377 + #doc_comment 378 + pub async fn #func_name(#(#param_types),*) -> Result<serde_json::Value, document::EvalError> { 379 + const MODULE: Asset = asset!(#asset_path); 380 + let js = format!(#js_format, MODULE); 381 + let eval = document::eval(js.as_str()); 382 + #(#send_calls)* 383 + eval.await 384 + } 385 + } 386 + } 387 + 388 + /// A macro to create rust binding to javascript functions. 389 + ///```rust,ignore 390 + /// use dioxus::prelude::*; 391 + /// 392 + /// // Generate the greeting function at compile time 393 + /// use_js!("examples/assets/example.js"::greeting); 394 + /// 395 + /// // Or generate multiple functions: 396 + /// // use_js!("examples/assets/example.js"::{greeting, add}); 397 + /// 398 + /// // Or generate all exported functions: 399 + /// // use_js!("examples/assets/example.js"::*); 400 + /// 401 + /// fn main() { 402 + /// launch(App); 403 + /// } 404 + /// 405 + /// #[component] 406 + /// fn App() -> Element { 407 + /// let future = use_resource(|| async move { 408 + /// let from = "dave"; 409 + /// let to = "john"; 410 + /// 411 + /// // Now we can call the generated function directly! 412 + /// let greeting_result = greeting(from, to) 413 + /// .await 414 + /// .map_err(Box::<dyn std::error::Error>::from)?; 415 + /// let greeting: String = 416 + /// serde_json::from_value(greeting_result).map_err(Box::<dyn std::error::Error>::from)?; 417 + /// Ok::<String, Box<dyn std::error::Error>>(greeting) 418 + /// }); 419 + /// 420 + /// rsx!( 421 + /// div { 422 + /// h1 { "Dioxus `use_js!` macro example!" } 423 + /// { 424 + /// match &*future.read() { 425 + /// Some(Ok(greeting)) => rsx! { 426 + /// p { "Greeting from JavaScript: {greeting}" } 427 + /// }, 428 + /// Some(Err(e)) => rsx! { 429 + /// p { "Error: {e}" } 430 + /// }, 431 + /// None => rsx! { 432 + /// p { "Running js..." } 433 + /// }, 434 + /// } 435 + /// } 436 + /// } 437 + /// ) 438 + /// } 439 + /// ``` 440 + #[proc_macro] 441 + pub fn use_js(input: TokenStream) -> TokenStream { 442 + let input = parse_macro_input!(input as UseJsInput); 443 + 444 + let manifest_dir = match std::env::var("CARGO_MANIFEST_DIR") { 445 + Ok(dir) => dir, 446 + Err(_) => { 447 + return TokenStream::from( 448 + syn::Error::new( 449 + proc_macro2::Span::call_site(), 450 + "CARGO_MANIFEST_DIR environment variable not found", 451 + ) 452 + .to_compile_error(), 453 + ); 454 + } 455 + }; 456 + 457 + let asset_path = &input.asset_path; 458 + let js_file_path = std::path::Path::new(&manifest_dir).join(asset_path.value()); 459 + 460 + let all_functions = match parse_js_file(&js_file_path) { 461 + Ok(funcs) => funcs, 462 + Err(e) => return TokenStream::from(e.to_compile_error()), 463 + }; 464 + 465 + let import_spec = input.import_spec; 466 + let functions_to_generate = match get_functions_to_generate(all_functions, import_spec) { 467 + Ok(funcs) => funcs, 468 + Err(e) => return TokenStream::from(e.to_compile_error()), 469 + }; 470 + 471 + let function_wrappers: Vec<TokenStream2> = functions_to_generate 472 + .iter() 473 + .map(|func| generate_function_wrapper(func, asset_path)) 474 + .collect(); 475 + 476 + let expanded = quote! { 477 + #(#function_wrappers)* 478 + }; 479 + 480 + TokenStream::from(expanded) 481 + }
+4 -2
crates/weaver-app/Cargo.toml
··· 21 21 dashmap = "6.1.0" 22 22 23 23 dioxus = { version = "0.7.1", features = ["router"] } 24 - #dioxus-router = { version = "0.7.1", features = ["wasm-split"] } 25 24 weaver-common = { path = "../weaver-common" } 26 25 jacquard = { workspace = true}#, features = ["streaming"] } 27 26 jacquard-lexicon = { workspace = true } ··· 40 39 humansize = "2.0.0" 41 40 base64 = "0.22" 42 41 http = "1.3" 43 - reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } 42 + reqwest = { version = "0.12", default-features = false, features = ["json"] } 43 + 44 44 dioxus-free-icons = { version = "0.10.0" } 45 45 # diesel = { version = "2.3", features = ["sqlite", "returning_clauses_for_sqlite_3_35", "chrono", "serde_json"] } 46 46 # diesel_migrations = { version = "2.3", features = ["sqlite"] } ··· 50 50 51 51 [target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dependencies] 52 52 webbrowser = "1.0.6" 53 + reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } 53 54 54 55 [target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies] 56 + reqwest = { version = "0.12", default-features = false, features = ["json"] } 55 57 #sqlite-wasm-rs = { version = "0.4", default-features = false, features = ["precompiled", "relaxed-idb"] } 56 58 time = { version = "0.3", features = ["wasm-bindgen"] } 57 59 console_error_panic_hook = "0.1"
+1 -1
crates/weaver-app/src/auth/mod.rs
··· 11 11 use jacquard::oauth::types::OAuthClientMetadata; 12 12 13 13 #[cfg(all(feature = "fullstack-server", feature = "server"))] 14 - #[get("/client-metadata.json")] 14 + #[get("/oauth-client-metadata.json")] 15 15 pub async fn client_metadata() -> Result<axum::Json<serde_json::Value>> { 16 16 use jacquard::oauth::atproto::atproto_client_metadata; 17 17
+1 -1
crates/weaver-app/src/config.rs
··· 130 130 ) 131 131 } else { 132 132 let host = env::WEAVER_APP_HOST; 133 - let client_id = format!("{host}/client-metadata.json"); 133 + let client_id = format!("{host}/oauth-client-metadata.json"); 134 134 let redirect_uri = format!("{host}/callback"); 135 135 let logo_uri = if env::WEAVER_LOGO_URI.is_empty() { 136 136 None
+4 -4
crates/weaver-app/src/fetch.rs
··· 84 84 85 85 impl XrpcClient for Client { 86 86 #[doc = " Get the base URI for the client."] 87 - fn base_uri(&self) -> impl Future<Output = jacquard::url::Url> + Send { 87 + fn base_uri(&self) -> impl Future<Output = CowStr<'static>> + Send { 88 88 async { 89 89 let guard = self.session.read().await; 90 90 if let Some(session) = guard.clone() { ··· 294 294 } 295 295 296 296 #[doc = " Current base endpoint."] 297 - async fn endpoint(&self) -> jacquard::url::Url { 297 + async fn endpoint(&self) -> CowStr<'static> { 298 298 let guard = self.session.read().await; 299 299 if let Some(session) = guard.clone() { 300 300 session.endpoint().await ··· 647 647 648 648 impl XrpcClient for CachedFetcher { 649 649 #[doc = " Get the base URI for the client."] 650 - fn base_uri(&self) -> impl Future<Output = jacquard::url::Url> + Send { 650 + fn base_uri(&self) -> impl Future<Output = CowStr<'static>> + Send { 651 651 self.client.base_uri() 652 652 } 653 653 ··· 795 795 self.client.session_info().await 796 796 } 797 797 798 - async fn endpoint(&self) -> jacquard::url::Url { 798 + async fn endpoint(&self) -> CowStr<'static> { 799 799 self.client.endpoint().await 800 800 } 801 801
+38 -10
crates/weaver-app/src/main.rs
··· 129 129 let blob_cache = Arc::new(BlobCache::new(Arc::new( 130 130 UnauthenticatedSession::new_public(), 131 131 ))); 132 - dioxus::server::router(App).layer(middleware::from_fn({ 133 - let blob_cache = blob_cache.clone(); 134 - let fetcher = fetcher.clone(); 135 - move |mut req: Request, next: Next| { 132 + axum::Router::new() 133 + // Server side render the application, serve static assets, and register server functions 134 + .serve_dioxus_application( 135 + ServeConfig::builder() 136 + // Enable incremental rendering 137 + .incremental( 138 + dioxus::server::IncrementalRendererConfig::new() 139 + .static_dir( 140 + std::env::current_exe() 141 + .unwrap() 142 + .parent() 143 + .unwrap() 144 + .join("public"), 145 + ) 146 + .clear_cache(false), 147 + ) 148 + .enable_out_of_order_streaming(), 149 + App, 150 + ) 151 + .layer(middleware::from_fn({ 136 152 let blob_cache = blob_cache.clone(); 137 153 let fetcher = fetcher.clone(); 138 - async move { 139 - req.extensions_mut().insert(blob_cache); 140 - req.extensions_mut().insert(fetcher); 141 - Ok::<_, Infallible>(next.run(req).await) 154 + move |mut req: Request, next: Next| { 155 + let blob_cache = blob_cache.clone(); 156 + let fetcher = fetcher.clone(); 157 + async move { 158 + req.extensions_mut().insert(blob_cache); 159 + req.extensions_mut().insert(fetcher); 160 + Ok::<_, Infallible>(next.run(req).await) 161 + } 142 162 } 143 - } 144 - })) 163 + })) 145 164 }; 146 165 Ok(router) 147 166 }); ··· 240 259 Err(CapturedError::from_display("no blob")) 241 260 } 242 261 } 262 + 263 + #[server(endpoint = "static_routes", output = server_fn::codec::Json)] 264 + async fn static_routes() -> Result<Vec<String>, ServerFnError> { 265 + // The `Routable` trait has a `static_routes` method that returns all static routes in the enum 266 + Ok(Route::static_routes() 267 + .iter() 268 + .map(ToString::to_string) 269 + .collect()) 270 + }