diff --git a/CHANGELOG.md b/CHANGELOG.md index b3069e03d..323693fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,46 @@ + +## 0.8.15 + +`2024-10-10` + +* feat: disable webp to base64 by [@Jinbao1001](https://github.com/Jinbao1001) in [#1602](https://github.com/umijs/mako/pull/1602) +* feat: add resolve_id plugin hook by [@sorrycc](https://github.com/sorrycc) in [#1625](https://github.com/umijs/mako/pull/1625) +* refactor: napi threadsafe function by [@xusd320](https://github.com/xusd320) in [#1608](https://github.com/umijs/mako/pull/1608) +* refactor: config codes organization by [@xusd320](https://github.com/xusd320) in [#1618](https://github.com/umijs/mako/pull/1618) +* fix(bundler-mako): experimental config should be merged deeply by [@sorrycc](https://github.com/sorrycc) in [#1617](https://github.com/umijs/mako/pull/1617) +* fix: clickToComponent don't work by [@sorrycc](https://github.com/sorrycc) in [#1620](https://github.com/umijs/mako/pull/1620) +* fix: duplicate_package_checker panic when no package.json is supplied by [@sorrycc](https://github.com/sorrycc) in [#1621](https://github.com/umijs/mako/pull/1621) +* fix: file_stem index out of bound by [@Jinbao1001](https://github.com/Jinbao1001) in [#1623](https://github.com/umijs/mako/pull/1623) + +## 0.8.14 + +`2024-09-25` + +* fix: bundler-mako dev server load chunks failed with 504 error code by [@stormslowly](https://github.com/stormslowly) in [#1612](https://github.com/umijs/mako/pull/1612) + +## 0.8.13 + +`2024-09-23` + +* fix: chunk_loading_global by [@xusd320](https://github.com/xusd320) in [#1590](https://github.com/umijs/mako/pull/1590) +* fix: devServer put static serve proxy after umi proxy middleware by [@whyer11](https://github.com/whyer11) in [#1558](https://github.com/umijs/mako/pull/1558) +* revert: import namespace optimize by [@stormslowly](https://github.com/stormslowly) in [#1606](https://github.com/umijs/mako/pull/1606) + ## 0.8.12 `2024-09-13` -* fix(tree-shaking): detect export var side effects by @stormslowly in https://github.com/umijs/mako/pull/1579 -* fix: bad output when chunk_loading_global containing quotation mark by @xusd320 in https://github.com/umijs/mako/pull/1582 -* chore: ➕ add a subdot cli tool script for debug module/chunk graph by @stormslowly in https://github.com/umijs/mako/pull/1585 -* fix(win): copy don't work under windows by @sorrycc in https://github.com/umijs/mako/pull/1587 -* fix(win): module id should be win_pathed by @sorrycc in https://github.com/umijs/mako/pull/1588 -* feat(tree-shaking): optimize import namespace used all exports to partial used of source modules by @stormslowly in https://github.com/umijs/mako/pull/1584 -* fix: merge mako config by @hualigushi in https://github.com/umijs/mako/pull/1578 -* fix:clear deps should not panic when module not found by @Jinbao1001 in https://github.com/umijs/mako/pull/1581 -* Revert "fix: merge mako config" by @stormslowly in https://github.com/umijs/mako/pull/1589 -* fix: watch too many file error by @Jinbao1001 in https://github.com/umijs/mako/pull/1550 -* feat: support numeric module Id by @Jinbao1001 in https://github.com/umijs/mako/pull/1561 +* fix(tree-shaking): detect export var side effects by [@stormslowly](https://github.com/stormslowly) in [#1579](https://github.com/umijs/mako/pull/1579) +* fix: bad output when chunk_loading_global containing quotation mark by [@xusd320](https://github.com/xusd320) in [#1582](https://github.com/umijs/mako/pull/1582) +* chore: ➕ add a subdot cli tool script for debug module/chunk graph by [@stormslowly](https://github.com/stormslowly) in [#1585](https://github.com/umijs/mako/pull/1585) +* fix(win): copy don't work under windows by [@sorrycc](https://github.com/sorrycc) in [#1587](https://github.com/umijs/mako/pull/1587) +* fix(win): module id should be win_pathed by [@sorrycc](https://github.com/sorrycc) in [#1588](https://github.com/umijs/mako/pull/1588) +* feat(tree-shaking): optimize import namespace used all exports to partial used of source modules by [@stormslowly](https://github.com/stormslowly) in [#1584](https://github.com/umijs/mako/pull/1584) +* fix: merge mako config by [@hualigushi](https://github.com/hualigushi) in [#1578](https://github.com/umijs/mako/pull/1578) +* fix:clear deps should not panic when module not found by [@Jinbao1001](https://github.com/Jinbao1001) in [#1581](https://github.com/umijs/mako/pull/1581) +* Revert "fix: merge mako config" by [@stormslowly](https://github.com/stormslowly) in [#1589](https://github.com/umijs/mako/pull/1589) +* fix: watch too many file error by [@Jinbao1001](https://github.com/Jinbao1001) in [#1550](https://github.com/umijs/mako/pull/1550) +* feat: support numeric module Id by [@Jinbao1001](https://github.com/Jinbao1001) in [#1561](https://github.com/umijs/mako/pull/1561) ## 0.8.11 @@ -80,12 +108,12 @@ `2024-08-22` -- fix: wrong file extension for map file paths in stat.json by [@stormslowly](https://github.com/stormslowly) in https://github.com/umijs/mako/pull/1506 -- fix: resolve failed when package use `node` as key by [@sorrycc](https://github.com/sorrycc) in https://github.com/umijs/mako/pull/1516 -- perf: merge source map, speed up generation by 800% by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1509 -- perf: optimize group_chunks, speed up group_chunks by 500% by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1475 -- refactor: improve regex convention for px2rem config by [@xiaohuoni](https://github.com/xiaohuoni) in https://github.com/umijs/mako/pull/1469 -- refactor: improve behavior of define config by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1505 +- fix: wrong file extension for map file paths in stat.json by [@stormslowly](https://github.com/stormslowly) in [#1506](https://github.com/umijs/mako/pull/1506) +- fix: resolve failed when package use `node` as key by [@sorrycc](https://github.com/sorrycc) in [#1516](https://github.com/umijs/mako/pull/1516) +- perf: merge source map, speed up generation by 800% by [@xusd320](https://github.com/xusd320) in [#1509](https://github.com/umijs/mako/pull/1509) +- perf: optimize group_chunks, speed up group_chunks by 500% by [@xusd320](https://github.com/xusd320) in [#1475](https://github.com/umijs/mako/pull/1475) +- refactor: improve regex convention for px2rem config by [@xiaohuoni](https://github.com/xiaohuoni) in [#1469](https://github.com/umijs/mako/pull/1469) +- refactor: improve behavior of define config by [@xusd320](https://github.com/xusd320) in [#1505](https://github.com/umijs/mako/pull/1505) ## 0.8.2 @@ -110,10 +138,10 @@ `2024-08-08` -* [Breaking Change] refactor: not write stats.json anymore by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1485 -* feat: less support "globalVars" by [@gin-lsl](https://github.com/gin-lsl) in https://github.com/umijs/mako/pull/1465 -* feat(bundler-mako): generate dynamicImportToRequire from babel and webpack config by [@PeachScript](https://github.com/PeachScript) in https://github.com/umijs/mako/pull/1479 -* refactor: avoid underscore prefix for chunk file name by [@PeachScript](https://github.com/PeachScript) in https://github.com/umijs/mako/pull/1471 +* [Breaking Change] refactor: not write stats.json anymore by [@xusd320](https://github.com/xusd320) in [#1485](https://github.com/umijs/mako/pull/1485) +* feat: less support "globalVars" by [@gin-lsl](https://github.com/gin-lsl) in [#1465](https://github.com/umijs/mako/pull/1465) +* feat(bundler-mako): generate dynamicImportToRequire from babel and webpack config by [@PeachScript](https://github.com/PeachScript) in [#1479](https://github.com/umijs/mako/pull/1479) +* refactor: avoid underscore prefix for chunk file name by [@PeachScript](https://github.com/PeachScript) in [#1471](https://github.com/umijs/mako/pull/1471) ## 0.7.9 @@ -124,7 +152,7 @@ - feat: sass option support function by [@xiaohuoni](https://github.com/xiaohuoni) in [#1461](https://github.com/umijs/mako/pull/1461) - fix: double value lose by [@xiaohuoni](https://github.com/xiaohuoni) in [#1462](https://github.com/umijs/mako/pull/1462) - perf: use hashlink, speed up codeSplitting by 300% when building big project by [@xusd320](https://github.com/xusd320) in [#1460](https://github.com/umijs/mako/pull/1460) -- perf(tree-shaking): parallelize tree shaking module map init by [@stormslowly](https://github.com/stormslowly) in https://github.com/umijs/mako/pull/1452 +- perf(tree-shaking): parallelize tree shaking module map init by [@stormslowly](https://github.com/stormslowly) in [#1452](https://github.com/umijs/mako/pull/1452) ## 0.7.8 diff --git a/CHANGELOG_zh-CN.md b/CHANGELOG_zh-CN.md index 78fa9fc40..d4f043735 100644 --- a/CHANGELOG_zh-CN.md +++ b/CHANGELOG_zh-CN.md @@ -1,17 +1,45 @@ + +## 0.8.15 + +`2024-10-10` + +* 功能:禁用 webp 转 base64 功能 by [@Jinbao1001](https://github.com/Jinbao1001) in [#1602](https://github.com/umijs/mako/pull/1602) +* 功能:添加 resolve_id 插件钩子 by [@sorrycc](https://github.com/sorrycc) in [#1625](https://github.com/umijs/mako/pull/1625) +* 重构:napi 线程安全函数 by [@xusd320](https://github.com/xusd320) in [#1608](https://github.com/umijs/mako/pull/1608) +* 重构:配置代码的组织方式 by [@xusd320](https://github.com/xusd320) in [#1618](https://github.com/umijs/mako/pull/1618) +* 修复(bundler-mako):实验性配置应进行深度合并 by [@sorrycc](https://github.com/sorrycc) in [#1617](https://github.com/umijs/mako/pull/1617) +* 修复:clickToComponent 功能失效 by [@sorrycc](https://github.com/sorrycc) in [#1620](https://github.com/umijs/mako/pull/1620) +* 修复:在没有 package.json 文件时 duplicate_package_checker 会崩溃 by [@sorrycc](https://github.com/sorrycc) in [#1621](https://github.com/umijs/mako/pull/1621) +* 修复:file_stem 索引超出范围问题 by [@Jinbao1001](https://github.com/Jinbao1001) in [#1623](https://github.com/umijs/mako/pull/1623) + +## 0.8.14 + +`2024-09-25` + +* 修复: dev 服务器加载 chunk 文件 504 错误 by [@stormslowly](https://github.com/stormslowly) in [#1612](https://github.com/umijs/mako/pull/1612) + +## 0.8.13 + +`2024-09-23` + +* 修复: chunk_loading_global dev 内容未转义问题 by [@xusd320](https://github.com/xusd320) in [#1590](https://github.com/umijs/mako/pull/1590) +* 修复: mako-bundler devServer 静态文件服务和 umi proxy 中间件执行顺序 by [@whyer11](https://github.com/whyer11) in [#1558](https://github.com/umijs/mako/pull/1558) +* 回滚: `import * as` 的 tree shaking 优化 by [@stormslowly](https://github.com/stormslowly) in [#1606](https://github.com/umijs/mako/pull/1606) + ## 0.8.12 `2024-09-13` -修复: 检测导出变量的副作用以进行 tree-shaking 优化 (by @stormslowly in #1579) -修复: 修复 chunk_loading_global 包含引号时的输出错误 (by @xusd320 in #1582) -其他: 添加用于调试模块/块图的 subdot cli 工具脚本 (by @stormslowly in #1585) -修复: 修复 Windows 下复制功能失效的问题 (by @sorrycc in #1587) -修复: 修复 Windows 下模块 ID 的路径问题 (by @sorrycc in #1588) -优化: 优化按需引入命名空间,减少冗余代码 (by @stormslowly in #1584) -修复 (已回滚): 修复 Mako 配置合并问题 (by @hualigushi in #1578) -修复: 修复清除依赖项时找不到模块导致程序崩溃的问题 (by @Jinbao1001 in #1581) -修复: 修复监视过多文件导致的错误 (by @Jinbao1001 in #1550) -新增: 支持数字模块 ID (by @Jinbao1001 in #1561) +* 修复: 检测导出变量的副作用以进行 tree-shaking 优化 (by [@stormslowly](https://github.com/stormslowly) in [#1579](https://github.com/umijs/mako/pull/1579)) +* 修复: 修复 chunk_loading_global 包含引号时的输出错误 (by [@xusd320](https://github.com/xusd320) in [#1582](https://github.com/umijs/mako/pull/1582)) +* 其他: 添加用于调试模块/块图的 subdot cli 工具脚本 (by [@stormslowly](https://github.com/stormslowly) in [#1585](https://github.com/umijs/mako/pull/1585)) +* 修复: 修复 Windows 下复制功能失效的问题 (by [@sorrycc](https://github.com/sorrycc) in [#1587](https://github.com/umijs/mako/pull/1587)) +* 修复: 修复 Windows 下模块 ID 的路径问题 (by [@sorrycc](https://github.com/sorrycc) in [#1588](https://github.com/umijs/mako/pull/1588)) +* 优化: 优化按需引入命名空间,减少冗余代码 (by [@stormslowly](https://github.com/stormslowly) in [#1584](https://github.com/umijs/mako/pull/1584)) +* 修复 (已回滚): 修复 Mako 配置合并问题 (by [@hualigushi](https://github.com/hualigushi) in [#1578](https://github.com/umijs/mako/pull/1578)) +* 修复: 修复清除依赖项时找不到模块导致程序崩溃的问题 (by [@Jinbao1001](https://github.com/Jinbao1001) in [#1581](https://github.com/umijs/mako/pull/1581)) +* 修复: 修复监视过多文件导致的错误 (by [@Jinbao1001](https://github.com/Jinbao1001) in [#1550](https://github.com/umijs/mako/pull/1550)) +* 新增: 支持数字模块 ID (by [@Jinbao1001](https://github.com/Jinbao1001) in [#1561](https://github.com/umijs/mako/pull/1561)) ## 0.8.11 @@ -79,12 +107,12 @@ `2024-08-22` -- 修复:stat.json 中 map 文件路径中的后缀名错误 by [@stormslowly](https://github.com/stormslowly) in https://github.com/umijs/mako/pull/1506 -- 修复:无法解析使用 `node` 导出字段的依赖包 by [@sorrycc](https://github.com/sorrycc) in https://github.com/umijs/mako/pull/1516 -- 性能:合并 source map,最高为 generation 阶段提速 800% by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1509 -- 性能:优化 chunk 分组逻辑,最高为 group_chunks 阶段提速 500% by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1475 -- 改进:调整 px2rem 配置中正则值的约定方式 by [@xiaohuoni](https://github.com/xiaohuoni) in https://github.com/umijs/mako/pull/1469 -- 改进:调整 define 配置的替换行为,与社区共识保持一致 by [@xusd320](https://github.com/xusd320) in https://github.com/umijs/mako/pull/1505 +- 修复:stat.json 中 map 文件路径中的后缀名错误 by [@stormslowly](https://github.com/stormslowly) in [#1506](https://github.com/umijs/mako/pull/1506) +- 修复:无法解析使用 `node` 导出字段的依赖包 by [@sorrycc](https://github.com/sorrycc) in [#1516](https://github.com/umijs/mako/pull/1516) +- 性能:合并 source map,最高为 generation 阶段提速 800% by [@xusd320](https://github.com/xusd320) in [#1509](https://github.com/umijs/mako/pull/1509) +- 性能:优化 chunk 分组逻辑,最高为 group_chunks 阶段提速 500% by [@xusd320](https://github.com/xusd320) in [#1475](https://github.com/umijs/mako/pull/1475) +- 改进:调整 px2rem 配置中正则值的约定方式 by [@xiaohuoni](https://github.com/xiaohuoni) in [#1469](https://github.com/umijs/mako/pull/1469) +- 改进:调整 define 配置的替换行为,与社区共识保持一致 by [@xusd320](https://github.com/xusd320) in [#1505](https://github.com/umijs/mako/pull/1505) ## 0.8.2 @@ -124,7 +152,7 @@ - 新增: saas 配置支持 function by [@xiaohuoni](https://github.com/xiaohuoni) in [#1461](https://github.com/umijs/mako/pull/1461) - 修复: px2rem 没有正确复制 raw_value by [@xiaohuoni](https://github.com/xiaohuoni) in [#1462](https://github.com/umijs/mako/pull/1462) - 优化: 使用 hashlink 让大型项目 codeSplitting 提速 300% by [@xusd320](https://github.com/xusd320) in [#1460](https://github.com/umijs/mako/pull/1460) -- 优化: 并行处理树摇逻辑 by [@stormslowly](https://github.com/stormslowly) in https://github.com/umijs/mako/pull/1452 +- 优化: 并行处理树摇逻辑 by [@stormslowly](https://github.com/stormslowly) in [#1452](https://github.com/umijs/mako/pull/1452) ## 0.7.8 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0193fd714..6e4b4be5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -166,21 +166,26 @@ $ XCODE_PROFILE=1 OKAM=/PATH/TO/umijs/marko/packages/bundler-mako/index.js bigfi ## Release -You can release mako with ci or locally. +Before release, please make sure everything is ok. -### Release with CI +```bash +$ just ready +``` -> NOTICE: _canary_ and _dev_ tags are now supported to be released with CI. +Open https://github.com/umijs/mako/actions?query=branch%3Amaster+event%3Apush to checkout the latest master push action with name "node-bind-build", and download the artifacts to packages/mako directory. If the artifacts has no commit hash in the name, you should add the commit hash manually. ```bash -# Make sure everything is ok -$ just ready -# Release with CI +$ git rev-parse HEAD +``` + +Then you can release the new version. + +``` +# Release @umijs/mako and @umijs/bundler-mako $ npm run release -# After released successful, you need to release bundler-mako manually. -$ npm run release:bundler-mako ``` -### Release Locally +After release, you must do 2 things: -Refer to https://yuque.antfin.com/mako/vz2gn4/vkp4qs8u4zcuxqoc for details. +- Release the new version on github +- Update the changelog in CHANGELOG.md and CHANGELOG_zh-CN.md diff --git a/Cargo.lock b/Cargo.lock index 6e34e9008..e8130886d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "ab_glyph" -version = "0.2.22" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1061f3ff92c2f65800df1f12fc7b4ff44ee14783104187dd04dfee6f11b0fd2" +checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -51,7 +51,7 @@ checksum = "134d0acf6acb667c89d3332999b1a5df4edbc8d6113910f392ebb73f2b03bb56" dependencies = [ "accesskit", "accesskit_consumer", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", ] @@ -63,9 +63,9 @@ checksum = "e084cb5168790c0c112626175412dc5ad127083441a8248ae49ddf6725519e83" dependencies = [ "accesskit", "accesskit_consumer", - "async-channel", + "async-channel 1.9.0", "atspi", - "futures-lite", + "futures-lite 1.13.0", "serde", "zbus", ] @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.19.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] @@ -112,11 +112,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -125,9 +131,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -139,18 +145,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-activity" @@ -202,99 +208,96 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" [[package]] name = "arboard" -version = "3.2.1" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac57f2b058a76363e357c056e4f74f1945bf734d37b8b3ef49066c4787dde0fc" +checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" dependencies = [ "clipboard-win", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation", "parking_lot", - "thiserror", - "winapi 0.3.9", "x11rb", ] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ast_node" -version = "0.9.5" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c09c69dffe06d222d072c878c3afe86eee2179806f20503faec97250268b4c24" +checksum = "f9184f2b369b3e8625712493c89b785881f27eedc6cde480a81883cef78868b2" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -303,7 +306,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" dependencies = [ - "event-listener", + "event-listener 2.5.3", "futures-core", ] @@ -314,21 +317,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", "futures-core", + "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.5.4" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1da3ae8dabd9c00f453a329dfe1fb28da3c0a72e2478cdcd93171740c20499" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ - "async-lock", "async-task", "concurrent-queue", - "fastrand 2.0.1", - "futures-lite", + "fastrand 2.1.1", + "futures-lite 2.3.0", "slab", ] @@ -338,10 +352,10 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "blocking", - "futures-lite", + "futures-lite 1.13.0", ] [[package]] @@ -350,73 +364,120 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", - "polling", - "rustix 0.37.19", + "polling 2.8.0", + "rustix 0.37.27", "slab", - "socket2", + "socket2 0.4.10", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock 3.4.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.3", + "rustix 0.38.37", + "slab", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "async-lock" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ - "async-io", - "async-lock", - "autocfg", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", "blocking", "cfg-if", - "event-listener", - "futures-lite", - "rustix 0.37.19", - "signal-hook", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.37", "windows-sys 0.48.0", ] [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io 2.3.4", + "async-lock 3.4.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.37", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", ] [[package]] name = "async-task" -version = "4.4.1" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -427,9 +488,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atomic_refcell" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f2bfe491d41d45507b8431da8274f7feeca64a49e86d980eed2937ec2ff020" +checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" [[package]] name = "atspi" @@ -441,7 +502,7 @@ dependencies = [ "async-trait", "atspi-macros", "enumflags2", - "futures-lite", + "futures-lite 1.13.0", "serde", "tracing", "zbus", @@ -458,60 +519,36 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "auto_impl" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", + "miniz_oxide 0.8.0", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -529,12 +566,27 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" +dependencies = [ + "simd-abstraction", +] + [[package]] name = "better_scoped_tls" version = "0.1.1" @@ -561,9 +613,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -601,7 +653,7 @@ version = "0.1.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", ] [[package]] @@ -611,105 +663,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" dependencies = [ "block-sys", - "objc2-encode", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", ] [[package]] name = "blocking" -version = "1.4.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.3.1", "async-task", - "fastrand 2.0.1", "futures-io", - "futures-lite", + "futures-lite 2.3.0", "piper", - "tracing", ] [[package]] name = "browserslist-rs" -version = "0.13.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33066f72a558361eeb1077b0aff0f1dce1ac75bdc20b38a642f155f767b2824" +checksum = "fdf0ca73de70c3da94e4194e4a01fe732378f55d47cf4c0588caab22a0dbfa14" dependencies = [ - "ahash 0.8.6", - "anyhow", + "ahash 0.8.11", "chrono", "either", + "indexmap 2.5.0", "itertools", "nom", "once_cell", - "quote", "serde", "serde_json", - "string_cache", - "string_cache_codegen", "thiserror", ] [[package]] name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "allocator-api2", ] [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "c_linked_list" @@ -723,10 +759,10 @@ version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c8c50262271cdf5abc979a5f76515c234e764fa025d1ba4862c0f0bcda0e95" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", "cached_proc_macro", "cached_proc_macro_types", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "instant", "once_cell", "thiserror", @@ -738,7 +774,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -746,9 +782,9 @@ dependencies = [ [[package]] name = "cached_proc_macro_types" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" [[package]] name = "calloop" @@ -766,27 +802,27 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", @@ -798,11 +834,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ "jobserver", + "libc", + "shlex", ] [[package]] @@ -848,44 +886,43 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.11" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.11" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clean-path" @@ -895,13 +932,11 @@ checksum = "aaa6b4b263a5d737e9bf6b7c09b72c41a5480aec4d7219af827f6564e950b6a5" [[package]] name = "clipboard-win" -version = "4.5.0" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" dependencies = [ "error-code", - "str-buf", - "winapi 0.3.9", ] [[package]] @@ -942,26 +977,25 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", "windows-sys 0.48.0", ] [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -969,18 +1003,18 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "config" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" +checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" dependencies = [ "async-trait", "json5", @@ -997,15 +1031,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -1019,9 +1053,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1029,9 +1063,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -1048,9 +1082,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -1059,9 +1093,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1083,55 +1117,46 @@ checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.8.0", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -1145,12 +1170,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.2" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1586fa608b1dab41f667475b4a41faec5ba680aee428bfa5de4ea520fdc6e901" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -1165,8 +1190,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -1179,21 +1214,46 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.77", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core 0.20.10", + "quote", + "syn 2.0.77", +] + [[package]] name = "dashmap" version = "4.0.2" @@ -1211,7 +1271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -1219,19 +1279,27 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] -name = "delegate" -version = "0.12.0" +name = "debugid" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", + "serde", + "uuid", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", ] [[package]] @@ -1245,6 +1313,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +dependencies = [ + "derive_builder_core", + "syn 2.0.77", +] + [[package]] name = "diff" version = "0.1.13" @@ -1279,7 +1378,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.1", + "libloading 0.8.5", ] [[package]] @@ -1290,15 +1389,15 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "ecolor" @@ -1344,7 +1443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3aef8ec3ae1b772f340170c65bf27d5b8c28f543a0116c844d2ac08d01123e7" dependencies = [ "accesskit", - "ahash 0.8.6", + "ahash 0.8.11", "epaint", "log", "nohash-hasher", @@ -1384,9 +1483,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "emath" @@ -1404,54 +1503,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] -name = "enum-iterator" -version = "1.4.1" +name = "enumflags2" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ - "enum-iterator-derive", + "enumflags2_derive", + "serde", ] [[package]] -name = "enum-iterator-derive" -version = "1.2.1" +name = "enumflags2_derive" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] -name = "enumflags2" -version = "0.7.8" +name = "epaint" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", -] - -[[package]] -name = "epaint" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09333964d4d57f40a85338ba3ca5ed4716070ab184dcfed966b35491c5c64f3b" +checksum = "09333964d4d57f40a85338ba3ca5ed4716070ab184dcfed966b35491c5c64f3b" dependencies = [ "ab_glyph", - "ahash 0.8.6", + "ahash 0.8.11", "atomic_refcell", "bytemuck", "ecolor", @@ -1463,46 +1542,63 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "error-code" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ - "cc", - "libc", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "error-code" -version = "2.3.1" +name = "event-listener" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ - "libc", - "str-buf", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] [[package]] name = "fastrand" @@ -1515,15 +1611,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -1539,14 +1635,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "libredox 0.1.3", + "windows-sys 0.59.0", ] [[package]] @@ -1557,12 +1653,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide 0.8.0", ] [[package]] @@ -1597,14 +1693,13 @@ dependencies = [ [[package]] name = "from_variant" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ec5dc38ee19078d84a692b1c41181ff9f94331c76cee66ff0208c770b5e54f" +checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "swc_macros_common", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -1630,9 +1725,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1645,9 +1740,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1655,15 +1750,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1672,9 +1767,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1691,34 +1786,47 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.1", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1781,19 +1889,19 @@ dependencies = [ [[package]] name = "gethostname" -version = "0.2.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" dependencies = [ "libc", - "winapi 0.3.9", + "windows-targets 0.48.5", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1802,21 +1910,21 @@ dependencies = [ [[package]] name = "getset" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" dependencies = [ - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "gimli" -version = "0.27.2" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "gl_generator" @@ -1868,7 +1976,7 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "libloading 0.7.4", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", "raw-window-handle", "wayland-sys 0.30.1", @@ -1919,9 +2027,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1929,7 +2037,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.5.0", "slab", "tokio", "tokio-util", @@ -1942,7 +2050,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.8", ] [[package]] @@ -1951,16 +2059,16 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", ] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", "allocator-api2", ] @@ -1970,7 +2078,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1980,28 +2088,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -2011,18 +2113,41 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "hstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412" +dependencies = [ + "hashbrown 0.14.5", + "new_debug_unreachable", + "once_cell", + "phf", + "rustc-hash", + "triomphe", +] + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", ] [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -2031,9 +2156,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -2048,21 +2173,21 @@ checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2075,7 +2200,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -2116,9 +2241,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2161,14 +2286,13 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "image" -version = "0.24.7" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", "color_quant", - "num-rational", "num-traits", "png", ] @@ -2181,18 +2305,18 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "rayon", "serde", ] [[package]] name = "indexmap" -version = "2.2.6" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", + "rayon", "serde", ] @@ -2231,23 +2355,22 @@ dependencies = [ [[package]] name = "insta" -version = "1.30.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28491f7753051e5704d4d0ae7860d45fae3238d7d235bc4289dcd45c48d3cec3" +checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" dependencies = [ "console", "lazy_static", "linked-hash-map", "serde", "similar", - "yaml-rust", ] [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", "js-sys", @@ -2261,7 +2384,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -2277,40 +2400,25 @@ dependencies = [ [[package]] name = "is-macro" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7d079e129b77477a49c5c4f1cfe9ce6c2c909ef52520693e8e811a714c7b20" -dependencies = [ - "Inflector", - "pmutil 0.5.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "is-macro" -version = "0.3.0" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4467ed1321b310c2625c5aa6c1b1ffc5de4d9e42668cf697a08fb033ee8265e" +checksum = "2069faacbe981460232f880d26bf3c7634e322d49053aa48c27e3ae642f728f1" dependencies = [ "Inflector", - "pmutil 0.6.1", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.3.2", - "io-lifetimes", - "rustix 0.37.19", - "windows-sys 0.48.0", + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -2325,24 +2433,30 @@ dependencies = [ [[package]] name = "is_ci" -version = "1.1.1" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "itoap" @@ -2374,27 +2488,30 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] [[package]] name = "json-strip-comments" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d129799327c8f80861e467c59b825ba24c277dba6ad0d71a141dc98f9e04ee" +checksum = "b271732a960335e715b6b2ae66a086f115c74eb97360e996d2bd809bfc063bba" +dependencies = [ + "memchr", +] [[package]] name = "json5" @@ -2424,9 +2541,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kqueue" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", @@ -2434,9 +2551,9 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ "bitflags 1.3.2", "libc", @@ -2444,9 +2561,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lexical" @@ -2523,9 +2640,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.146" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libloading" @@ -2539,12 +2656,34 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.4.1", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.4", ] [[package]] @@ -2567,21 +2706,21 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2589,9 +2728,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.18" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" @@ -2614,7 +2753,7 @@ version = "0.1.0" dependencies = [ "anyhow", "base64 0.22.1", - "bitflags 2.4.2", + "bitflags 2.6.0", "cached", "chrono", "clap", @@ -2622,7 +2761,6 @@ dependencies = [ "config", "convert_case", "dashmap 4.0.2", - "delegate", "eframe", "fixedbitset", "fs_extra", @@ -2631,11 +2769,11 @@ dependencies = [ "glob", "glob-match", "hashlink", - "heck", + "heck 0.4.1", "hyper", "hyper-staticfile", "hyper-tungstenite", - "indexmap 2.2.6", + "indexmap 2.5.0", "indicatif", "insta", "maplit", @@ -2665,15 +2803,15 @@ dependencies = [ "serde_json", "serde_yaml", "svgr-rs", - "swc_core 0.83.22", + "swc_core 0.101.7", "swc_emotion", - "swc_error_reporters", + "swc_error_reporters 0.21.0", "swc_node_comments", "thiserror", "tikv-jemallocator", "tokio", "tokio-tungstenite", - "toml 0.7.6", + "toml 0.7.8", "tracing", "tracing-subscriber", "tungstenite", @@ -2692,7 +2830,8 @@ dependencies = [ "napi", "napi-build", "napi-derive", - "rayon", + "oneshot", + "serde", "serde_json", "tikv-jemallocator", ] @@ -2714,9 +2853,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "markdown" -version = "1.0.0-alpha.11" +version = "1.0.0-alpha.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f557389e7cdb1e3574c43d82965f0d933fff789c6ea2779cb0e9e72ec4b1224e" +checksum = "911a8325e6fb87b89890cd4529a2ab34c2669c026279e61c26b7140a3d821ccb" dependencies = [ "unicode-id", ] @@ -2738,19 +2877,19 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "mdxjs" -version = "0.1.14" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334329b79f2a86b4e432a4f9911df72e4b7dff1164dfa3027bc7f91d60391d8f" +checksum = "ec5cf50756dfb3eaf8f72979c94a3c2e281f3ba6e35280fa4b73eaac2cd23b6f" dependencies = [ "markdown", - "swc_core 0.79.71", + "swc_core 0.103.2", ] [[package]] name = "memchr" -version = "2.6.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -2781,74 +2920,68 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] [[package]] name = "miette" -version = "4.7.1" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c90329e44f9208b55f45711f9558cec15d7ef8295cc65ecd6d4188ae8edc58c" +checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" dependencies = [ - "atty", "backtrace", - "miette-derive 4.7.1", + "backtrace-ext", + "is-terminal", + "miette-derive 5.10.0", "once_cell", - "owo-colors", - "supports-color 1.3.1", - "supports-hyperlinks 1.2.0", - "supports-unicode 1.0.2", + "owo-colors 3.5.0", + "supports-color", + "supports-hyperlinks", + "supports-unicode", "terminal_size", - "textwrap", + "textwrap 0.15.2", "thiserror", "unicode-width", ] [[package]] name = "miette" -version = "5.10.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" +checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" dependencies = [ - "backtrace", - "backtrace-ext", - "is-terminal", - "miette-derive 5.10.0", - "once_cell", - "owo-colors", - "supports-color 2.1.0", - "supports-hyperlinks 2.1.0", - "supports-unicode 2.0.0", - "terminal_size", - "textwrap", + "cfg-if", + "miette-derive 7.2.0", + "owo-colors 4.1.0", + "textwrap 0.16.1", "thiserror", "unicode-width", ] [[package]] name = "miette-derive" -version = "4.7.1" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b5bc45b761bcf1b5e6e6c4128cd93b84c218721a8d9b894aa0aff4ed180174c" +checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "miette-derive" -version = "5.10.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" +checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -2879,9 +3012,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -2895,28 +3028,28 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", + "simd-adler32", ] [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", - "simd-adler32", + "adler2", ] [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2924,6 +3057,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "nanoid" version = "0.4.0" @@ -2935,11 +3080,11 @@ dependencies = [ [[package]] name = "napi" -version = "2.14.0" +version = "2.16.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d90182620f32fe34b6ac9b52cba898af26e94c7f5abc01eb4094c417ae2e6c" +checksum = "53575dfa17f208dd1ce3a2da2da4659aae393b256a472f2738a8586a6c4107fd" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "ctor", "napi-derive", "napi-sys", @@ -2951,29 +3096,29 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.0.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" +checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a" [[package]] name = "napi-derive" -version = "2.14.1" +version = "2.16.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3619fa472d23cd5af94d63a2bae454a77a8863251f40230fbf59ce20eafa8a86" +checksum = "17435f7a00bfdab20b0c27d9c56f58f6499e418252253081bfff448099da31d1" dependencies = [ "cfg-if", "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "napi-derive-backend" -version = "1.0.54" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd3ea4b54020c73d591a49cd192f6334c5f37f71a63ead54dbc851fa991ef00" +checksum = "967c485e00f0bf3b1bdbe510a38a4606919cf1d34d9a37ad41f25a81aa077abe" dependencies = [ "convert_case", "once_cell", @@ -2981,16 +3126,16 @@ dependencies = [ "quote", "regex", "semver 1.0.23", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "napi-sys" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" +checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3" dependencies = [ - "libloading 0.8.1", + "libloading 0.8.5", ] [[package]] @@ -3030,9 +3175,9 @@ dependencies = [ [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" @@ -3102,7 +3247,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -3110,7 +3255,7 @@ dependencies = [ "kqueue", "libc", "log", - "mio", + "mio 0.8.11", "walkdir", "windows-sys 0.48.0", ] @@ -3140,53 +3285,46 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", "serde", ] [[package]] -name = "num-integer" -version = "0.1.45" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "num-rational" -version = "0.4.1" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.9", "libc", ] @@ -3229,7 +3367,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -3248,21 +3386,16 @@ dependencies = [ ] [[package]] -name = "objc-foundation" -version = "0.1.1" +name = "objc-sys" +version = "0.2.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] +checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" [[package]] name = "objc-sys" -version = "0.2.0-beta.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" @@ -3270,49 +3403,139 @@ version = "0.3.0-beta.3.patch-leaks.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" dependencies = [ - "block2", - "objc-sys", - "objc2-encode", + "block2 0.2.0-alpha.6", + "objc-sys 0.2.0-beta.2", + "objc2-encode 2.0.0-pre.2", ] [[package]] -name = "objc2-encode" -version = "2.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys 0.3.5", + "objc2-encode 4.0.3", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "2.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", ] [[package]] -name = "objc_id" -version = "0.1.1" +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "objc", + "bitflags 2.6.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", + "objc2-metal", ] [[package]] name = "object" -version = "0.30.4" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" + +[[package]] +name = "oneshot" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "e296cf87e61c9cfc1a61c3c63a0f7f286ed4554e0e22be84e8a38e1d264a2a29" [[package]] name = "open" -version = "5.1.4" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ca541f22b1c46d4bb9801014f234758ab4297e7870b904b6a8415b980a7388" +checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" dependencies = [ "is-wsl", "libc", @@ -3321,11 +3544,11 @@ dependencies = [ [[package]] name = "orbclient" -version = "0.3.46" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8378ac0dfbd4e7895f2d2c1f1345cab3836910baf3a300b000d04250f0c8428f" +checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "redox_syscall 0.3.5", + "libredox 0.0.2", ] [[package]] @@ -3348,6 +3571,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "outref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" + [[package]] name = "overload" version = "0.1.1" @@ -3356,9 +3585,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.19.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" +checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90" dependencies = [ "ttf-parser", ] @@ -3369,6 +3598,12 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "owo-colors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" + [[package]] name = "oxc_resolver" version = "1.7.0" @@ -3389,15 +3624,15 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.1" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -3405,22 +3640,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.4", "smallvec", - "windows-targets 0.48.0", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "path-clean" @@ -3448,9 +3683,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" dependencies = [ "memchr", "thiserror", @@ -3459,9 +3694,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" dependencies = [ "pest", "pest_generator", @@ -3469,22 +3704,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" dependencies = [ "once_cell", "pest", @@ -3493,30 +3728,29 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap 2.5.0", ] [[package]] name = "phf" -version = "0.10.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", "phf_shared", - "proc-macro-hack", ] [[package]] name = "phf_generator" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", "rand", @@ -3524,52 +3758,51 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ "phf_generator", "phf_shared", - "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "phf_shared" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", ] [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -3579,54 +3812,32 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand 2.1.1", "futures-io", ] [[package]] name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "pmutil" -version = "0.5.3" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "pmutil" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", -] +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.1", + "miniz_oxide 0.7.4", ] [[package]] @@ -3645,6 +3856,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix 0.38.37", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "portable-atomic" version = "1.7.0" @@ -3652,24 +3878,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] -name = "precomputed-hash" -version = "0.1.1" +name = "ppv-lite86" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "preset_env_base" -version = "0.4.8" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008ae5e91d877e168b73c17bed2e4dc7553cd7cc237a776d9479eab6642352c5" +checksum = "1b30eab18be480c194938e433e269d5298a279f6410f02fbc73f3576a325c110" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", "anyhow", "browserslist-rs", "dashmap 5.5.3", @@ -3698,53 +3927,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit 0.19.12", + "toml_edit 0.19.15", ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "proc-macro-error-attr2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ - "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.109", - "version_check", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ + "proc-macro-error-attr2", "proc-macro2", "quote", - "version_check", + "syn 2.0.77", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" dependencies = [ "cc", ] @@ -3804,9 +4025,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3861,9 +4082,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3871,14 +4092,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -3899,16 +4118,25 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "regex" -version = "1.9.3" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.6", - "regex-syntax 0.7.4", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -3922,13 +4150,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.4", ] [[package]] @@ -3939,52 +4167,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relative-path" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" - -[[package]] -name = "rend" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "rkyv" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" -dependencies = [ - "bitvec", - "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "ron" @@ -4009,9 +4200,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -4030,48 +4221,48 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.3.7", + "linux-raw-sys 0.3.8", "windows-sys 0.48.0", ] [[package]] name = "rustix" -version = "0.38.3" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.10", - "windows-sys 0.48.0", + "linux-raw-sys 0.4.14", + "windows-sys 0.52.0", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "ryu-js" -version = "0.2.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" +checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" [[package]] name = "sailfish" @@ -4097,8 +4288,8 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.50", - "toml 0.8.2", + "syn 2.0.77", + "toml 0.8.19", ] [[package]] @@ -4128,9 +4319,9 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" @@ -4145,12 +4336,6 @@ dependencies = [ "tiny-skia", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "semver" version = "0.9.0" @@ -4177,9 +4362,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4198,76 +4383,66 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.5.0", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] [[package]] name = "serde_yaml" -version = "0.9.22" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452e67b9c20c37fa79df53201dc03839651086ed9bbe92b3ca585ca9fdaa7d85" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.5.0", "itoa", "ryu", "serde", "unsafe-libyaml", ] -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -4287,30 +4462,35 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] -name = "signal-hook" -version = "0.3.17" +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", - "signal-hook-registry", ] [[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "simd-abstraction" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" dependencies = [ - "libc", + "outref", ] [[package]] @@ -4319,47 +4499,41 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - [[package]] name = "similar" -version = "2.2.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "slotmap" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" dependencies = [ "version_check", ] [[package]] name = "smallvec" -version = "1.11.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smartstring" @@ -4374,9 +4548,9 @@ dependencies = [ [[package]] name = "smawk" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "smithay-client-toolkit" @@ -4409,34 +4583,48 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi 0.3.9", ] +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "sourcemap" -version = "6.2.3" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed16231c92d0a6f0388f56e0ab2be24ecff1173f8e22f0ea5e074d0525631cb" +checksum = "dab08a862c70980b8e23698b507e272317ae52a608a164a844111f5372374f1f" dependencies = [ + "base64-simd", + "bitvec", "data-encoding", + "debugid", "if_chain", + "rustc-hash", "rustc_version", "serde", "serde_json", - "unicode-id", + "unicode-id-start", "url", ] [[package]] name = "st-map" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f352d5d14be5a1f956d76ae0c8060c3487aaa2a080f10a4b4ff023c7c05a9047" +checksum = "8257dd592de7614be71a2342d36ba2d527ddad3f9a0c8d09d6ceed4c371531e4" dependencies = [ "arrayvec", "static-map-macro", @@ -4450,27 +4638,26 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" dependencies = [ "cc", "cfg-if", "libc", "psm", - "winapi 0.3.9", + "windows-sys 0.59.0", ] [[package]] name = "static-map-macro" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7628ae0bd92555d3de4303da41a5c8b1c5363e892001325f34e4be9ed024d0d7" +checksum = "710e9696ef338691287aeb937ee6ffe60022f579d3c8d2fd9d58973a9a10a466" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -4479,12 +4666,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "str-buf" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" - [[package]] name = "strict-num" version = "0.1.1" @@ -4492,42 +4673,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] -name = "string_cache" -version = "0.8.7" +name = "string_enum" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "05e383308aebc257e7d7920224fa055c632478d92744eca77f99be8fa1545b90" dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", -] - -[[package]] -name = "string_enum" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fa4d4f81d7c05b9161f8de839975d3326328b8ba2831164b465524cc2f55252" -dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -4537,14 +4691,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "supports-color" -version = "1.3.1" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f" -dependencies = [ - "atty", - "is_ci", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "supports-color" @@ -4556,15 +4706,6 @@ dependencies = [ "is_ci", ] -[[package]] -name = "supports-hyperlinks" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406" -dependencies = [ - "atty", -] - [[package]] name = "supports-hyperlinks" version = "2.1.0" @@ -4576,18 +4717,9 @@ dependencies = [ [[package]] name = "supports-unicode" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2" -dependencies = [ - "atty", -] - -[[package]] -name = "supports-unicode" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" +checksum = "f850c19edd184a205e883199a261ed44471c81e39bd95b1357f5febbef00e77a" dependencies = [ "is-terminal", ] @@ -4595,29 +4727,32 @@ dependencies = [ [[package]] name = "svgr-rs" version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a959be330ea7bc8f5722868a53e625962ae70842ade80427bda9a0810ff50a80" dependencies = [ "clap", + "html-escape", "linked-hash-map", "linked_hash_set", + "napi", + "napi-derive", "regex", "serde", - "swc_core 0.74.6", + "swc_core 0.101.7", "swc_xml", + "testing", + "thiserror", ] [[package]] name = "swc" -version = "0.266.28" +version = "0.284.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49be68a31f62828304f0325a324bbf47cf128c954a49f4e3730eba29b01b6376" +checksum = "833bb7f4073f08aec7144619a2cf682413b7a0cc8f21b7e76abd2fd02373685d" dependencies = [ "anyhow", - "base64 0.13.1", + "base64 0.21.7", "dashmap 5.5.3", "either", - "indexmap 1.9.3", + "indexmap 2.5.0", "jsonc-parser", "lru", "once_cell", @@ -4628,100 +4763,97 @@ dependencies = [ "serde", "serde_json", "sourcemap", - "swc_atoms 0.5.9", + "swc_atoms", "swc_cached", - "swc_common 0.32.1", + "swc_common 0.37.5", + "swc_compiler_base", "swc_config", - "swc_ecma_ast 0.109.1", - "swc_ecma_codegen 0.145.5", + "swc_ecma_ast", + "swc_ecma_codegen", "swc_ecma_ext_transforms", "swc_ecma_lints", - "swc_ecma_loader 0.44.4", + "swc_ecma_loader", "swc_ecma_minifier", - "swc_ecma_parser 0.140.0", + "swc_ecma_parser", "swc_ecma_preset_env", "swc_ecma_transforms", - "swc_ecma_transforms_base 0.133.5", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_compat", - "swc_ecma_transforms_optimization 0.193.23", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", - "swc_error_reporters", + "swc_ecma_transforms_optimization", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_error_reporters 0.21.0", "swc_node_comments", "swc_timer", + "swc_transform_common", + "swc_typescript", "swc_visit", "tracing", "url", ] [[package]] -name = "swc_atoms" -version = "0.4.43" +name = "swc_allocator" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64593af3e0fbacd1b7147a0188f1fd77a2fc8ae3c2425bdb9528de255b9f452b" +checksum = "adc8bd3075d1c6964010333fae9ddcd91ad422a4f8eb8b3206a9b2b6afb4209e" dependencies = [ - "once_cell", + "bumpalo", + "hashbrown 0.14.5", + "ptr_meta", "rustc-hash", - "serde", - "string_cache", - "string_cache_codegen", "triomphe", ] [[package]] name = "swc_atoms" -version = "0.5.9" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f54563d7dcba626d4acfe14ed12def7ecc28e004debe3ecd2c3ee07cc47e449" +checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" dependencies = [ - "bytecheck", + "hstr", "once_cell", - "rkyv", "rustc-hash", "serde", - "string_cache", - "string_cache_codegen", - "triomphe", ] [[package]] name = "swc_bundler" -version = "0.212.5" +version = "0.236.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c39d6d7fef9ee2a951423593764bea1666a4be0cbc89030d0da8f985124870" +checksum = "bf56bdfc5af60d362bfe63c002af34b9ffba711dd1630fc9d58c3b0a2f5ce54b" dependencies = [ - "ahash 0.7.6", "anyhow", "crc", - "indexmap 1.9.3", - "is-macro 0.2.2", + "indexmap 2.5.0", + "is-macro", "once_cell", "parking_lot", "petgraph", "radix_fmt", "relative-path", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_ecma_codegen 0.137.6", - "swc_ecma_loader 0.42.5", - "swc_ecma_parser 0.132.6", - "swc_ecma_transforms_base 0.125.1", - "swc_ecma_transforms_optimization 0.185.4", - "swc_ecma_utils 0.115.8", - "swc_ecma_visit 0.88.5", - "swc_fast_graph 0.18.5", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_loader", + "swc_ecma_parser", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_optimization", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_fast_graph", "swc_graph_analyzer", "tracing", ] [[package]] name = "swc_cached" -version = "0.3.17" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b8051bbf1c23817f9f2912fce18d9a6efcaaf8f8e1a4c69dbaf72bcaf71136" +checksum = "83406221c501860fce9c27444f44125eafe9e598b8b81be7563d7036784cd05c" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", "anyhow", "dashmap 5.5.3", "once_cell", @@ -4731,11 +4863,10 @@ dependencies = [ [[package]] name = "swc_common" -version = "0.30.5" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e95bf36e3e217431c50eab784c5601bf5f0ed3657aac6bda57748fa4d6103b" +checksum = "457fb92efa9f0c849d6bc4e86561982d464176bc3df96bb22baed5e98309e090" dependencies = [ - "ahash 0.7.6", "ast_node", "better_scoped_tls", "cfg-if", @@ -4748,10 +4879,11 @@ dependencies = [ "rustc-hash", "serde", "siphasher", - "string_cache", - "swc_atoms 0.4.43", + "swc_allocator", + "swc_atoms", "swc_eq_ignore_macros", "swc_visit", + "termcolor", "tracing", "unicode-width", "url", @@ -4759,10 +4891,11 @@ dependencies = [ [[package]] name = "swc_common" -version = "0.31.22" +version = "0.37.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d00f960c667c59c133f30492f4d07f26242fcf988a066d3871e6d3d838d528" +checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" dependencies = [ + "ahash 0.8.11", "ast_node", "better_scoped_tls", "cfg-if", @@ -4771,121 +4904,85 @@ dependencies = [ "new_debug_unreachable", "num-bigint", "once_cell", + "parking_lot", "rustc-hash", "serde", "siphasher", - "string_cache", - "swc_atoms 0.5.9", + "sourcemap", + "swc_allocator", + "swc_atoms", "swc_eq_ignore_macros", "swc_visit", + "termcolor", "tracing", "unicode-width", "url", ] [[package]] -name = "swc_common" -version = "0.32.1" +name = "swc_compiler_base" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c84742fc22df1c293da5354c1cc8a5b45a045e9dc941005c1fd9cb4e9bdabc1" +checksum = "9859d605bfa3ba8323f37bc4f51839c0e21ea59b657f65865388b0adfeb0a413" dependencies = [ - "ahash 0.8.6", "anyhow", - "ast_node", - "atty", - "better_scoped_tls", - "bytecheck", - "cfg-if", - "either", - "from_variant", - "new_debug_unreachable", - "num-bigint", + "base64 0.21.7", "once_cell", - "parking_lot", - "rkyv", + "pathdiff", "rustc-hash", "serde", - "siphasher", + "serde_json", "sourcemap", - "string_cache", - "swc_atoms 0.5.9", - "swc_eq_ignore_macros", - "swc_visit", - "termcolor", - "tracing", - "unicode-width", - "url", + "swc_allocator", + "swc_atoms", + "swc_common 0.37.5", + "swc_config", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_minifier", + "swc_ecma_parser", + "swc_ecma_visit", + "swc_timer", ] [[package]] name = "swc_config" -version = "0.1.7" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba1c7a40d38f9dd4e9a046975d3faf95af42937b34b2b963be4d8f01239584b" +checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" dependencies = [ - "indexmap 1.9.3", + "anyhow", + "indexmap 2.5.0", "serde", "serde_json", + "sourcemap", + "swc_cached", "swc_config_macro", ] [[package]] name = "swc_config_macro" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b5aaca9a0082be4515f0fbbecc191bf5829cd25b5b9c0a2810f6a2bb0d6829" +checksum = "7c5f56139042c1a95b54f5ca48baa0e0172d369bcc9d3d473dad1de36bae8399" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "swc_core" -version = "0.74.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e18b78930ecae9f6415393c0c396af455e2a3cda540620f01b28a3e99ce4cc77" +checksum = "24fd64b47f1da39ff3c229b7a3f4fb4d9542e21b245ac77220a4b2ad1f455065" dependencies = [ - "swc_atoms 0.4.43", - "swc_bundler", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_ecma_codegen 0.137.6", - "swc_ecma_loader 0.42.5", - "swc_ecma_parser 0.132.6", - "swc_ecma_transforms_base 0.125.1", - "swc_ecma_visit 0.88.5", - "vergen", -] - -[[package]] -name = "swc_core" -version = "0.79.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83cc00b001e77b2c9019cbd5034fddbb627bb23010864a0e57d4943efa70644b" -dependencies = [ - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "swc_ecma_ast 0.107.8", - "swc_ecma_codegen 0.142.18", - "swc_ecma_parser 0.137.16", - "swc_ecma_transforms_base 0.130.25", - "swc_ecma_visit 0.93.8", - "vergen", -] - -[[package]] -name = "swc_core" -version = "0.83.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f42b020b98b1d844dd831c089581ca259b4fb8a0af60c7e6aae8aeadcce57e93" -dependencies = [ - "once_cell", "swc", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_allocator", + "swc_atoms", + "swc_bundler", + "swc_common 0.37.5", "swc_css_ast", "swc_css_codegen", "swc_css_compat", @@ -4895,52 +4992,66 @@ dependencies = [ "swc_css_prefixer", "swc_css_utils", "swc_css_visit", - "swc_ecma_ast 0.109.1", - "swc_ecma_codegen 0.145.5", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_loader", "swc_ecma_minifier", - "swc_ecma_parser 0.140.0", + "swc_ecma_parser", "swc_ecma_preset_env", "swc_ecma_quote_macros", - "swc_ecma_transforms_base 0.133.5", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_compat", "swc_ecma_transforms_module", - "swc_ecma_transforms_optimization 0.193.23", + "swc_ecma_transforms_optimization", "swc_ecma_transforms_proposal", "swc_ecma_transforms_react", - "swc_ecma_transforms_testing", "swc_ecma_transforms_typescript", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", - "swc_plugin", - "swc_plugin_macro", - "swc_plugin_proxy", - "vergen", + "swc_ecma_utils", + "swc_ecma_visit", + "vergen 8.3.2", +] + +[[package]] +name = "swc_core" +version = "0.103.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1297a233d0681b82e8706df416c697331c37e777d3c873d9554243525c3407f1" +dependencies = [ + "swc_allocator", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_transforms_base 0.146.0", + "swc_ecma_visit", + "vergen 9.0.0", ] [[package]] name = "swc_css_ast" -version = "0.139.1" +version = "0.144.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fab824eff88884673de1d6b84cdb5d3d71c0b903fcef62a3ec1f44f40477433f" +checksum = "931a3c25a6bae42537783eab131b34d8fd2913d14f975106ceb3287716072ee0" dependencies = [ - "is-macro 0.3.0", + "is-macro", "string_enum", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", ] [[package]] name = "swc_css_codegen" -version = "0.149.1" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef989abd4b9ccf3caf6a4ab0ceb9f9e7d6a27c08585a20a7fc7b9db6c73a341" +checksum = "09080a69fd9c07d76141f02c9d2826e46f08ffab5fdb8942cd8a95f38712f038" dependencies = [ - "auto_impl 1.1.0", - "bitflags 2.4.2", + "auto_impl", + "bitflags 2.6.0", "rustc-hash", "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_css_codegen_macros", "swc_css_utils", @@ -4948,29 +5059,28 @@ dependencies = [ [[package]] name = "swc_css_codegen_macros" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da287376d8e9ab2e2c5a17fffd0c4701140433a8640ea52fa0c368e69dec565" +checksum = "de2ece8c7dbdde85aa1bcc9764c5f41f7450d8bf1312eac2375b8dc0ecbc13d7" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "swc_css_compat" -version = "0.25.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ee1b2b77e7daaf389237ca2656df01cf8c1a6f2d9b158459921b202a661f8a" +checksum = "a46554269c0dcf34f3a414b3b43ed7dcd5e777e6cfa270a476101e522650ec58" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "once_cell", "serde", "serde_json", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_css_utils", "swc_css_visit", @@ -4978,13 +5088,13 @@ dependencies = [ [[package]] name = "swc_css_minifier" -version = "0.114.1" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21db6b6ef607d47d09a7e2fd0b8fd5ec29d05d1182f8d3d5eebef0f1b94c3f4d" +checksum = "3db2730dce248bf3ebab2d39885e7494b14a74279f93afcef4054c19aca61d17" dependencies = [ "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_css_utils", "swc_css_visit", @@ -4992,14 +5102,14 @@ dependencies = [ [[package]] name = "swc_css_modules" -version = "0.27.3" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac80e62e3221cb2abc0edd33886c74c7d2a64ca3756adce0047527026dff71ca" +checksum = "754fa55c23bcfaca640182d7812bc2104f8b20a488e7d29975e890618b6dc71c" dependencies = [ "rustc-hash", "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_css_codegen", "swc_css_parser", @@ -5008,29 +5118,29 @@ dependencies = [ [[package]] name = "swc_css_parser" -version = "0.148.1" +version = "0.154.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b02a3c11508487249aa571a908e673c540191de97d5139bb78ab03188dd57e26" +checksum = "02babeae8d3a1dad9858e6ade577b27cc463f8eb60139df0d05d58605e6c0554" dependencies = [ "lexical", "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", ] [[package]] name = "swc_css_prefixer" -version = "0.151.1" +version = "0.158.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "274da87a8f0117ef86382b132812aa6a1b700b31c37ef95ce3bbde7e05f8c098" +checksum = "b883a7be6ae276f2085b72585a790394939f89b65dbb562ed53df7e97af93884" dependencies = [ "once_cell", "preset_env_base", "serde", "serde_json", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_css_utils", "swc_css_visit", @@ -5038,207 +5148,314 @@ dependencies = [ [[package]] name = "swc_css_utils" -version = "0.136.1" +version = "0.141.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eead47672e3c832e2e3fc3e523490c4822d80a7fc8c50e87a66f9ab7003b517" +checksum = "28e930b27b85b95329f29b1fa36be032fb9bd04f20b0a7180c9c0fc19a368979" dependencies = [ "once_cell", "serde", "serde_json", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_css_visit", ] [[package]] name = "swc_css_visit" -version = "0.138.1" +version = "0.143.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83f01449a09b8a87ab4bd2ea6cbaaf74e39f9bfba3842a2918e998c5f9b428a4" +checksum = "c603fa9af0a4adc536a901ab728384c7da4fa0187b64d6aa25eb75ea61f1482b" dependencies = [ "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_css_ast", "swc_visit", ] [[package]] name = "swc_ecma_ast" -version = "0.102.5" +version = "0.118.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bc96ac4740ddd7e09baaa153b6cf74e62ed7436d674606c060ea01fd7c20cd0" +checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" dependencies = [ - "bitflags 1.3.2", - "is-macro 0.2.2", + "bitflags 2.6.0", + "is-macro", "num-bigint", + "phf", "scoped-tls", "serde", "string_enum", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "unicode-id", + "swc_atoms", + "swc_common 0.37.5", + "unicode-id-start", ] [[package]] -name = "swc_ecma_ast" -version = "0.107.8" +name = "swc_ecma_codegen" +version = "0.155.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6528f3dd33e11eae9d7fe9fee4a79d5bbd211c74426ab2eec64dc82bd2eb74d" +checksum = "cc7641608ef117cfbef9581a99d02059b522fcca75e5244fa0cbbd8606689c6f" dependencies = [ - "bitflags 2.4.2", - "is-macro 0.3.0", + "memchr", "num-bigint", - "scoped-tls", - "string_enum", - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "unicode-id", + "once_cell", + "serde", + "sourcemap", + "swc_allocator", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_codegen_macros", + "tracing", ] [[package]] -name = "swc_ecma_ast" -version = "0.109.1" +name = "swc_ecma_codegen_macros" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e063a1614daed3ea8be56e5dd8edb17003409088d2fc9ce4aca3378879812607" +checksum = "859fabde36db38634f3fad548dd5e3410c1aebba1b67a3c63e67018fa57a0bca" dependencies = [ - "bitflags 2.4.2", - "bytecheck", - "is-macro 0.3.0", - "num-bigint", - "rkyv", - "scoped-tls", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.77", +] + +[[package]] +name = "swc_ecma_compat_bugfixes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f9cac39f19d6509db921f4b75934aaa64fc84b599416e5c1fcaed1c313132f" +dependencies = [ + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_compat_es2015", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_ecma_compat_common" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9acdf402b36f8e83084b10e119d7ba9d07e5229ef39e1343f147db816c7b73e" +dependencies = [ + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", +] + +[[package]] +name = "swc_ecma_compat_es2015" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dade6e0c6e8ddb61281fee2331c3775a920c31535b91e8cace2e0c4eed6158d3" +dependencies = [ + "arrayvec", + "indexmap 2.5.0", + "is-macro", "serde", - "string_enum", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "unicode-id", + "serde_derive", + "smallvec", + "swc_atoms", + "swc_common 0.37.5", + "swc_config", + "swc_ecma_ast", + "swc_ecma_compat_common", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_classes", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", ] [[package]] -name = "swc_ecma_codegen" -version = "0.137.6" +name = "swc_ecma_compat_es2016" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b1fc2f9d9a83e15ea27df387279c9f79c12eedeb58af29da663fda952600b1" +checksum = "209e347cdc3fb56632a1d882f981f3448f5f529c16d8da9d770207fffda4a8f6" +dependencies = [ + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_ecma_compat_es2017" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa87a6861b2adc8b0178fb450165101c4396409481c8726ec90ad28398cae5d" dependencies = [ - "memchr", - "num-bigint", - "once_cell", - "rustc-hash", "serde", - "sourcemap", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_ecma_codegen_macros", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", "tracing", ] [[package]] -name = "swc_ecma_codegen" -version = "0.142.18" +name = "swc_ecma_compat_es2018" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933643517578f6c383fead24be0ba707c8548d43a9f80c46cc6972c5d7a0ab3a" +checksum = "f577f098e7c3738ade709caadb17c9f3bd911ea2ee6cfacca561d12addcc5761" dependencies = [ - "memchr", - "num-bigint", - "once_cell", - "rustc-hash", "serde", - "sourcemap", - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "swc_ecma_ast 0.107.8", - "swc_ecma_codegen_macros", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_compat_common", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", "tracing", ] [[package]] -name = "swc_ecma_codegen" -version = "0.145.5" +name = "swc_ecma_compat_es2019" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "547ed57b827ea4df3e2c27cea153482f8b2ce2d271ae30c456fbb2d5a5ecc19d" +checksum = "f9d52253dc2f83a3fca526c387c33e4ff9a8423b68c271414c9f870e1ced3231" +dependencies = [ + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_ecma_compat_es2020" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed343932876fad34b1d4a13e30c55b94531e89916f45e7c04203bc49a29565b9" dependencies = [ - "memchr", - "num-bigint", - "once_cell", - "rustc-hash", "serde", - "sourcemap", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_codegen_macros", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_compat_es2022", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", "tracing", ] [[package]] -name = "swc_ecma_codegen_macros" -version = "0.7.3" +name = "swc_ecma_compat_es2021" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcdff076dccca6cc6a0e0b2a2c8acfb066014382bc6df98ec99e755484814384" +checksum = "0b6b28a2c109466eaa809d9b9a5b81dcbb4e269ba293a9c5c34aabc67b6427bc" dependencies = [ - "pmutil 0.6.1", - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.50", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_ecma_compat_es2022" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3a644e271ea2a9df88e3e456c5c204c4916ef5136b7d946f9cd25607f47ec6" +dependencies = [ + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_compat_common", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_classes", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_ecma_compat_es3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e55ffadc12067b21524bf7b5d6938021ee918f65f18937ed27245c23544bc910" +dependencies = [ + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", ] [[package]] name = "swc_ecma_ext_transforms" -version = "0.109.0" +version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d995f94740b4cde4919e6e03d982230f755f49dac9dac52f0218254a1fd69f2b" +checksum = "ad03ee53c734eb74757d03c07ec71b1a982261830c9253ef3e2e4a089f9af25d" dependencies = [ "phf", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_lints" -version = "0.88.6" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300ae29c0fc98ed0364aa2fd4aa7702d6dc67d411dd4894e7e60d40e99c4ef19" +checksum = "20c11bcc9e3dc49929500c07c8b0c84a88064847d31e9ee16204b257e6bd315c" dependencies = [ - "auto_impl 1.1.0", + "auto_impl", "dashmap 5.5.3", "parking_lot", "rayon", "regex", "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_config", - "swc_ecma_ast 0.109.1", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_loader" -version = "0.42.5" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07db9ffa757d71893e265c716307c3c9568ab85645c126e80e0d0ba7528aef5" -dependencies = [ - "ahash 0.7.6", - "anyhow", - "pathdiff", - "serde", - "swc_common 0.30.5", - "tracing", -] - -[[package]] -name = "swc_ecma_loader" -version = "0.44.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2b3a3ec38fc9c691b787d32ac2aa5eb6871d1fe74ac4a10638fbd9b9bc407b" +checksum = "55fa3d55045b97894bfb04d38aff6d6302ac8a6a38e3bb3dfb0d20475c4974a9" dependencies = [ "anyhow", "dashmap 5.5.3", @@ -5250,23 +5467,25 @@ dependencies = [ "pathdiff", "serde", "serde_json", + "swc_atoms", "swc_cached", - "swc_common 0.32.1", + "swc_common 0.37.5", "tracing", ] [[package]] name = "swc_ecma_minifier" -version = "0.187.26" +version = "0.203.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80a2eb3007ceb2ff8096f56ee67fe1cff2f94e21ea015f0f9d99dfe53fc680a9" +checksum = "c9bc16bd0a3c295588939fe8d02f795d3463a2e1613600f9c860c7a9aadebe7c" dependencies = [ "arrayvec", - "indexmap 1.9.3", + "indexmap 2.5.0", "num-bigint", "num_cpus", "once_cell", "parking_lot", + "phf", "radix_fmt", "rayon", "regex", @@ -5274,91 +5493,53 @@ dependencies = [ "ryu-js", "serde", "serde_json", - "swc_atoms 0.5.9", - "swc_cached", - "swc_common 0.32.1", + "swc_allocator", + "swc_atoms", + "swc_common 0.37.5", "swc_config", - "swc_ecma_ast 0.109.1", - "swc_ecma_codegen 0.145.5", - "swc_ecma_parser 0.140.0", - "swc_ecma_transforms_base 0.133.5", - "swc_ecma_transforms_optimization 0.193.23", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_transforms_optimization", "swc_ecma_usage_analyzer", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_ecma_utils", + "swc_ecma_visit", "swc_timer", "tracing", ] [[package]] name = "swc_ecma_parser" -version = "0.132.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b8409efcb3c70fe31fb3203406ab73b3c3cd279aa2005887d1918049b2a38e" -dependencies = [ - "either", - "lexical", - "num-bigint", - "serde", - "smallvec", - "smartstring", - "stacker", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.137.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f95601ae9654b664a44154bd5186af106df8e7de2dfecad211b29dc90b84185" -dependencies = [ - "either", - "num-bigint", - "num-traits", - "serde", - "smallvec", - "smartstring", - "stacker", - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "swc_ecma_ast 0.107.8", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.140.0" +version = "0.149.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c968599841fcecfdc2e490188ad93251897a1bb912882547e6889e14a368399" +checksum = "683dada14722714588b56481399c699378b35b2ba4deb5c4db2fb627a97fb54b" dependencies = [ "either", + "new_debug_unreachable", "num-bigint", "num-traits", + "phf", "serde", "smallvec", "smartstring", "stacker", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", "tracing", "typed-arena", ] [[package]] name = "swc_ecma_preset_env" -version = "0.201.25" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "641be911f548518ab41f22dd377420a9b5d9de857a2f77ffdf51cf2aff0069bd" +checksum = "e5c01c4097d54b6992d926474546472f10f1f94799a6eb9b70176fc33e778573" dependencies = [ "anyhow", "dashmap 5.5.3", - "indexmap 1.9.3", + "indexmap 2.5.0", "once_cell", "preset_env_base", "rustc-hash", @@ -5367,472 +5548,334 @@ dependencies = [ "serde_json", "st-map", "string_enum", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", "swc_ecma_transforms", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_quote_macros" -version = "0.51.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b028b0675ad45b79b163c70e192f25b59d72366a2864c5d369dce707a38a1597" +checksum = "9781802c95d3bb1b248ae2641fab85012782bb5236e32600e6e4a00adf90a2dc" dependencies = [ "anyhow", - "pmutil 0.6.1", "proc-macro2", "quote", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_parser 0.140.0", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_parser", "swc_macros_common", - "syn 2.0.50", -] - -[[package]] -name = "swc_ecma_testing" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b776795afd44c8df3977391e239a8dedbe2139c5eeb1ea053c1e29314b6d8a7" -dependencies = [ - "anyhow", - "hex", - "sha-1", - "testing", - "tracing", + "syn 2.0.77", ] [[package]] name = "swc_ecma_transforms" -version = "0.224.23" +version = "0.238.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2dd0d135dbbadad6698bb42df89b90b03605f1625ae0906c39b3749b5afc40" +checksum = "d6a33679b1611630ee41f8ee8b41b9587de4171819698d313f7f8ae2c699f41a" dependencies = [ - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_transforms_base 0.133.5", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_compat", "swc_ecma_transforms_module", - "swc_ecma_transforms_optimization 0.193.23", + "swc_ecma_transforms_optimization", "swc_ecma_transforms_proposal", "swc_ecma_transforms_react", "swc_ecma_transforms_typescript", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "0.125.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b87668640fe6d63ecabaae1805534d1445ff63382ab8961cd623ccdeb1bfbc" -dependencies = [ - "better_scoped_tls", - "bitflags 1.3.2", - "indexmap 1.9.3", - "once_cell", - "phf", - "rustc-hash", - "serde", - "smallvec", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_ecma_parser 0.132.6", - "swc_ecma_utils 0.115.8", - "swc_ecma_visit 0.88.5", - "tracing", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_transforms_base" -version = "0.130.25" +version = "0.144.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42198e3909a6d852ebd88897267ee89323a8ebdbdb436ec60f48079f7c188018" +checksum = "7c0a71579d030e12fd3cfbfc8712c4ce21afc526f2a759903c77d8df61950f5e" dependencies = [ "better_scoped_tls", - "bitflags 2.4.2", - "indexmap 1.9.3", + "bitflags 2.6.0", + "indexmap 2.5.0", "once_cell", "phf", + "rayon", "rustc-hash", "serde", "smallvec", - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "swc_ecma_ast 0.107.8", - "swc_ecma_parser 0.137.16", - "swc_ecma_utils 0.120.20", - "swc_ecma_visit 0.93.8", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", "tracing", ] [[package]] name = "swc_ecma_transforms_base" -version = "0.133.5" +version = "0.146.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496e3957e19c22e61cd7ff020a87e1fe94c9334f4fa11267f08614fd5f85ba67" +checksum = "3b5a7c0a6c4cc7d0ba65549e7db52443bc0eb104563aeaae727ad87c176a1bbe" dependencies = [ "better_scoped_tls", - "bitflags 2.4.2", - "indexmap 1.9.3", + "bitflags 2.6.0", + "indexmap 2.5.0", "once_cell", "phf", - "rayon", "rustc-hash", "serde", "smallvec", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_parser 0.140.0", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", "tracing", ] [[package]] name = "swc_ecma_transforms_classes" -version = "0.122.5" +version = "0.133.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519ffccc874b8bb39db0fceec06c172b1d7a6e812ac6f4b0a000e5d3c295e495" +checksum = "0f37ec04525798a09ce02e52dc15433acee2d86664da0b8ede55bb5cefd95384" dependencies = [ - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_transforms_base 0.133.5", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_transforms_compat" -version = "0.159.12" +version = "0.170.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bfdc348f8e402b311cf25661086ea3bcdd8305688b582750d7934e2ba46f79e" +checksum = "4bb500b65423646da940e289ad37e7c88332d7194248c33fc63a9e768e104fe5" dependencies = [ "arrayvec", - "indexmap 1.9.3", - "is-macro 0.3.0", + "indexmap 2.5.0", + "is-macro", "num-bigint", "serde", "smallvec", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", "swc_config", - "swc_ecma_ast 0.109.1", - "swc_ecma_transforms_base 0.133.5", + "swc_ecma_ast", + "swc_ecma_compat_bugfixes", + "swc_ecma_compat_common", + "swc_ecma_compat_es2015", + "swc_ecma_compat_es2016", + "swc_ecma_compat_es2017", + "swc_ecma_compat_es2018", + "swc_ecma_compat_es2019", + "swc_ecma_compat_es2020", + "swc_ecma_compat_es2021", + "swc_ecma_compat_es2022", + "swc_ecma_compat_es3", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_classes", "swc_ecma_transforms_macros", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_ecma_utils", + "swc_ecma_visit", "swc_trace_macro", "tracing", ] [[package]] name = "swc_ecma_transforms_macros" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8188eab297da773836ef5cf2af03ee5cca7a563e1be4b146f8141452c28cc690" +checksum = "500a1dadad1e0e41e417d633b3d6d5de677c9e0d3159b94ba3348436cdb15aab" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "swc_ecma_transforms_module" -version = "0.176.16" +version = "0.189.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aee1c35e2dde705a7c899247302c306c4e1d4f6c2374f6c075ae6c4964aa1c8c" +checksum = "2b5bddea322502ce309f77b76dcd7994ff700fbba7caf9d12eb6fb7ef98ecd1b" dependencies = [ "Inflector", "anyhow", - "bitflags 2.4.2", - "indexmap 1.9.3", - "is-macro 0.3.0", - "path-clean 0.1.0", + "bitflags 2.6.0", + "indexmap 2.5.0", + "is-macro", + "path-clean 1.0.1", "pathdiff", "regex", "serde", - "swc_atoms 0.5.9", + "swc_atoms", "swc_cached", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_loader 0.44.4", - "swc_ecma_parser 0.140.0", - "swc_ecma_transforms_base 0.133.5", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_optimization" -version = "0.185.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "544681f98bd62c45e8fc091cfbf8425fb02fd458a4ad81b9557be8bb41e5db37" -dependencies = [ - "ahash 0.7.6", - "dashmap 5.5.3", - "indexmap 1.9.3", - "once_cell", - "petgraph", - "rustc-hash", - "serde_json", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_ecma_parser 0.132.6", - "swc_ecma_transforms_base 0.125.1", - "swc_ecma_transforms_macros", - "swc_ecma_utils 0.115.8", - "swc_ecma_visit 0.88.5", - "swc_fast_graph 0.18.5", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_loader", + "swc_ecma_parser", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", "tracing", ] [[package]] name = "swc_ecma_transforms_optimization" -version = "0.193.23" +version = "0.207.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321b41c92ea012e9514f694a6073ea7d5a5a081d4a78e381b0ee3c2a96a07b57" +checksum = "fc9b6dcb79ac6f396988c13ce2f782116aeb92e8ee77656072d1146697f66022" dependencies = [ "dashmap 5.5.3", - "indexmap 1.9.3", + "indexmap 2.5.0", "once_cell", "petgraph", "rayon", "rustc-hash", "serde_json", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_parser 0.140.0", - "swc_ecma_transforms_base 0.133.5", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_macros", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", - "swc_fast_graph 0.20.1", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_fast_graph", "tracing", ] [[package]] name = "swc_ecma_transforms_proposal" -version = "0.167.15" +version = "0.178.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9303611271cf1d8884920e6056acd3dbbd9f4dfda8ba7295dd6c76a02d20401" +checksum = "b252ea08cfd11e434f4c625ec95493e06c8b000b50eb8e908d76f3325dd5dfa8" dependencies = [ "either", "rustc-hash", "serde", "smallvec", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_transforms_base 0.133.5", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_classes", "swc_ecma_transforms_macros", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_transforms_react" -version = "0.179.16" +version = "0.190.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3066e5671862ec921d39a210bb94e2fd82c1d4a8b2ccf44feb9017ab8afadd61" +checksum = "c3e54a8c87d90812bf69b0f07931bb629111a3f24efe83b9190c3a40a5ebc25e" dependencies = [ - "base64 0.13.1", + "base64 0.21.7", "dashmap 5.5.3", - "indexmap 1.9.3", + "indexmap 2.5.0", "once_cell", "serde", - "sha-1", + "sha1", "string_enum", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_allocator", + "swc_atoms", + "swc_common 0.37.5", "swc_config", - "swc_ecma_ast 0.109.1", - "swc_ecma_parser 0.140.0", - "swc_ecma_transforms_base 0.133.5", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_macros", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", -] - -[[package]] -name = "swc_ecma_transforms_testing" -version = "0.136.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0636ec69f3de36ed0155a05e338b6ee294b115fafa15e13996f1ca7f2af6c3" -dependencies = [ - "ansi_term", - "anyhow", - "base64 0.13.1", - "hex", - "serde", - "serde_json", - "sha-1", - "sourcemap", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_codegen 0.145.5", - "swc_ecma_parser 0.140.0", - "swc_ecma_testing", - "swc_ecma_transforms_base 0.133.5", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", - "tempfile", - "testing", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_transforms_typescript" -version = "0.183.22" +version = "0.197.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a4ee5542e785db7c68a6b88de99916304fc47c47863f9c511db374c7e3835" +checksum = "0c7e8646e32ec76ed1bda9c111583f65ed8daa46586bbfd892788536c78a6d4c" dependencies = [ "ryu-js", "serde", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_transforms_base 0.133.5", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_transforms_base 0.144.0", "swc_ecma_transforms_react", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_ecma_utils", + "swc_ecma_visit", ] [[package]] name = "swc_ecma_usage_analyzer" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71dc9b35f1f137c72badbadb705a2325d161ff603224ab0e07e6834774ea281" -dependencies = [ - "indexmap 1.9.3", - "rustc-hash", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", - "swc_timer", - "tracing", -] - -[[package]] -name = "swc_ecma_utils" -version = "0.115.8" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077231ec8a3423b1b5dea4e6e220f7681315acca80494624b71717cf39d3ae64" -dependencies = [ - "indexmap 1.9.3", - "num_cpus", - "once_cell", - "rustc-hash", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_ecma_visit 0.88.5", - "tracing", - "unicode-id", -] - -[[package]] -name = "swc_ecma_utils" -version = "0.120.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058e23023eab86b548b0488b84a4d490f8d2f5e1de6483d82e352218fd59ae31" -dependencies = [ - "indexmap 1.9.3", - "num_cpus", - "once_cell", +checksum = "0c7689421c6a892642c5907fd608c56d982fdef0d6456f9dba3cc418c6ea7e07" +dependencies = [ + "indexmap 2.5.0", "rustc-hash", - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "swc_ecma_ast 0.107.8", - "swc_ecma_visit 0.93.8", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_timer", "tracing", - "unicode-id", ] [[package]] name = "swc_ecma_utils" -version = "0.123.0" +version = "0.134.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6d6b59ebd31b25fe2692ff705c806961e7856de8b7e91fd0942328886cd315" +checksum = "54f4e07d0d4987f8f27933549498acce5f89451ebe09b7d65f4d4ed4fc731200" dependencies = [ - "indexmap 1.9.3", + "indexmap 2.5.0", "num_cpus", "once_cell", "rayon", "rustc-hash", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_visit 0.95.1", + "ryu-js", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_visit", "tracing", "unicode-id", ] [[package]] name = "swc_ecma_visit" -version = "0.88.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67210c9d3bc4cdf6a1b2c69cb4ec77660a37e55e883c5ed9f8bc0e801758334b" -dependencies = [ - "num-bigint", - "swc_atoms 0.4.43", - "swc_common 0.30.5", - "swc_ecma_ast 0.102.5", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_visit" -version = "0.93.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9abcc6c3255eea772716872d9c958abfe97b1f4658c7a9d1d9dc55eb7e6da254" -dependencies = [ - "num-bigint", - "swc_atoms 0.5.9", - "swc_common 0.31.22", - "swc_ecma_ast 0.107.8", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_visit" -version = "0.95.1" +version = "0.104.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2774848b306e17fa280c598ecb192cc2c72a1163942b02d48606514336e9e7c5" +checksum = "5b1c6802e68e51f336e8bc9644e9ff9da75d7da9c1a6247d532f2e908aa33e81" dependencies = [ + "new_debug_unreachable", "num-bigint", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", + "serde", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", "swc_visit", "tracing", ] [[package]] name = "swc_emotion" -version = "0.51.0" +version = "0.72.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1a13c3241b2812f15e751687924b0458b55ca7c3576a752b939e954cb4b0ba" +checksum = "b4f4ea59296e236f2e66efb2a004fb2aecb1894dc7affd2747f83fe77939dadc" dependencies = [ - "base64 0.13.1", + "base64 0.22.1", "byteorder", "fxhash", "once_cell", @@ -5840,184 +5883,160 @@ dependencies = [ "regex", "serde", "sourcemap", - "swc_atoms 0.5.9", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_ecma_codegen 0.145.5", - "swc_ecma_utils 0.123.0", - "swc_ecma_visit 0.95.1", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_utils", + "swc_ecma_visit", "swc_trace_macro", "tracing", ] [[package]] name = "swc_eq_ignore_macros" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a95d367e228d52484c53336991fdcf47b6b553ef835d9159db4ba40efb0ee8" +checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "swc_error_reporters" -version = "0.16.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c76b479ad1a69bec65b261354b8e2dec8ed0f9ed43c7b54ab053dc4923e1c90e" +checksum = "e02c81943772dc4fb0a6228360552d353fedc1a368ee6d80a5172ecb376b1796" dependencies = [ "anyhow", - "miette 4.7.1", + "miette 7.2.0", "once_cell", "parking_lot", - "swc_common 0.32.1", + "swc_common 0.36.3", ] [[package]] -name = "swc_fast_graph" -version = "0.18.5" +name = "swc_error_reporters" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c9081b942cd9760525ef23f4c932cb2b314c5f06f3d8b25f7bb8a1449ff7ec" +checksum = "0d049e9256abf29d9fc66d3db3ea44b6815a64ad565ce31e117a74ee96478bb3" dependencies = [ - "indexmap 1.9.3", - "petgraph", - "rustc-hash", - "swc_common 0.30.5", + "anyhow", + "miette 7.2.0", + "once_cell", + "parking_lot", + "swc_common 0.37.5", ] [[package]] name = "swc_fast_graph" -version = "0.20.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f7297cdefdb54d8d09e0294c1aec3826825b1feefd0c25978365aa7f447a1c" +checksum = "357e2c97bb51431d65080f25b436bc4e2fc1a7f64a643bc21a8353e478dc799f" dependencies = [ - "indexmap 1.9.3", + "indexmap 2.5.0", "petgraph", "rustc-hash", - "swc_common 0.32.1", + "swc_common 0.37.5", ] [[package]] name = "swc_graph_analyzer" -version = "0.19.5" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23f7b0fd7b458e07d47e4a401a452cd60090e9eff93eadf06880e1787e19f293" +checksum = "f84e1d24a0d6e4066b42cfc00ab9b3109e314465aa199dd3e16849ed9566dce7" dependencies = [ - "ahash 0.7.6", - "auto_impl 0.5.0", + "auto_impl", "petgraph", - "swc_fast_graph 0.18.5", + "swc_common 0.37.5", + "swc_fast_graph", "tracing", ] [[package]] name = "swc_macros_common" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a273205ccb09b51fabe88c49f3b34c5a4631c4c00a16ae20e03111d6a42e832" +checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" dependencies = [ - "pmutil 0.6.1", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "swc_node_comments" -version = "0.19.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b9597573f1ab8bae72329eef550d214ced0955c7a4f1b6b4ae5e216219e710" +checksum = "d016ab18b432523b2a3c104ce3aaf7d869db46c0a41477dbfb6201ddc86c1eb0" dependencies = [ "dashmap 5.5.3", - "swc_atoms 0.5.9", - "swc_common 0.32.1", + "swc_atoms", + "swc_common 0.37.5", ] [[package]] -name = "swc_plugin" -version = "0.90.0" +name = "swc_timer" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5df720531bfbd7ceb1139319c39c20c446abfb8f7e0eb47b104205a71152b4" +checksum = "6b5fb6f8b8b85512aacbb3d7140a828666e0e0b1bcc69bf84000a0cd36306bab" dependencies = [ - "once_cell", + "tracing", ] [[package]] -name = "swc_plugin_macro" -version = "0.9.15" +name = "swc_trace_macro" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785309d342a69df4c929ee59e14e36889ca832f1d2a3c1d03c47c93126c72dbc" +checksum = "ff9719b6085dd2824fd61938a881937be14b08f95e2d27c64c825a9f65e052ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] -name = "swc_plugin_proxy" -version = "0.38.1" +name = "swc_transform_common" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76ccadcc63a459e096f332730b2d4e09548fc10e0be63df9f3bacecdf5332fe" +checksum = "eda3e80e1ad638d3575bc07745a914af13dcb02215098659f864731078271f2c" dependencies = [ "better_scoped_tls", - "rkyv", - "swc_common 0.32.1", - "swc_ecma_ast 0.109.1", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_timer" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1841a4bd92674f684a3e27b8e162d4eac912af87b34ecd4b6dc126fe4fd230fe" -dependencies = [ - "tracing", + "once_cell", + "rustc-hash", + "serde", + "serde_json", ] [[package]] -name = "swc_trace_macro" -version = "0.1.3" +name = "swc_typescript" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff9719b6085dd2824fd61938a881937be14b08f95e2d27c64c825a9f65e052ba" +checksum = "d5d043347b109a8aebfe01aaeada4af322304ea0f54ae8e5721df9afcb9305ca" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", + "swc_atoms", + "swc_common 0.37.5", + "swc_ecma_ast", + "thiserror", ] [[package]] name = "swc_visit" -version = "0.5.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c337fbb2d191bf371173dea6a957f01899adb8f189c6c31b122a6cfc98fc3" +checksum = "1ceb044142ba2719ef9eb3b6b454fce61ab849eb696c34d190f04651955c613d" dependencies = [ "either", - "swc_visit_macros", -] - -[[package]] -name = "swc_visit_macros" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f322730fb82f3930a450ac24de8c98523af7d34ab8cb2f46bcb405839891a99" -dependencies = [ - "Inflector", - "pmutil 0.6.1", - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.50", + "new_debug_unreachable", ] [[package]] name = "swc_xml" -version = "0.10.5" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1b517334dc2fa4fa724f165f6c718d3cff27b1b668bfb6664261d2af1f00f9" +checksum = "0a00df52c70e48a1a46289447e32b646a69b8f01c8ff37d72a38e071820a2734" dependencies = [ "swc_xml_ast", "swc_xml_codegen", @@ -6027,64 +6046,63 @@ dependencies = [ [[package]] name = "swc_xml_ast" -version = "0.9.5" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d95821a0f2962faf3ff0fea16cdcf401c7cd90d67a09effb6b638bfe82df38d" +checksum = "657b5392f0b28a096b80dd7e07338f1a6da2d9f1ec18d8b4b7041b7c12ab7a7b" dependencies = [ - "is-macro 0.2.2", + "is-macro", "string_enum", - "swc_atoms 0.4.43", - "swc_common 0.30.5", + "swc_atoms", + "swc_common 0.37.5", ] [[package]] name = "swc_xml_codegen" -version = "0.10.5" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48738c170db37b0c3dd762d0d0348875aa59c4835f2b16fd6ea5e5204b7acd27" +checksum = "6c408c3aa4c32e1f9c6f0df39fb852a24c48a1ace1c70e8b3f0e2155f83705f2" dependencies = [ - "auto_impl 0.5.0", - "bitflags 1.3.2", + "auto_impl", + "bitflags 2.6.0", "rustc-hash", - "swc_atoms 0.4.43", - "swc_common 0.30.5", + "swc_atoms", + "swc_common 0.37.5", "swc_xml_ast", "swc_xml_codegen_macros", ] [[package]] name = "swc_xml_codegen_macros" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5569cdfb93c97285c877c98eaa9c4897840666480fa2b8e35409c427d80086" +checksum = "aa129a0ce5386899ba969efe81b0e5e2f534c052d42682592f4beb95379ba977" dependencies = [ - "pmutil 0.5.3", "proc-macro2", "quote", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "swc_xml_parser" -version = "0.10.5" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d69b0d1c906a89e68e4d205aebd680492f2998be2dd53405051651e785b7e656" +checksum = "b8f79116b03882e60045e0b0f6ddeb68a832eb06876430230a8c891485385cbd" dependencies = [ - "swc_atoms 0.4.43", - "swc_common 0.30.5", + "swc_atoms", + "swc_common 0.37.5", "swc_xml_ast", ] [[package]] name = "swc_xml_visit" -version = "0.9.5" +version = "0.16.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68a07347d9446a2f9b9f57c5e3e5fbd8ee5471f811a3ed307209402c5ec7375" +checksum = "560b3e810d9b5bbdfc7fdb5bd6879c3ee1a980d352e42b5961512cb0a79c55b6" dependencies = [ "serde", - "swc_atoms 0.4.43", - "swc_common 0.30.5", + "swc_atoms", + "swc_common 0.37.5", "swc_visit", "swc_xml_ast", ] @@ -6102,9 +6120,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -6119,22 +6137,22 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.3", - "windows-sys 0.48.0", + "fastrand 2.1.1", + "once_cell", + "rustix 0.38.37", + "windows-sys 0.59.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -6151,9 +6169,9 @@ dependencies = [ [[package]] name = "testing" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31f7f4a7baef94495386462c2a55caa0f0885b61b28c120f783132d14938ed" +checksum = "9dda7450d6e429db582ca8a2cf698f3bc63bc04dae8d857936e810180e510c86" dependencies = [ "ansi_term", "cargo_metadata", @@ -6161,9 +6179,10 @@ dependencies = [ "once_cell", "pretty_assertions", "regex", + "serde", "serde_json", - "swc_common 0.32.1", - "swc_error_reporters", + "swc_common 0.36.3", + "swc_error_reporters 0.20.0", "testing_macros", "tracing", "tracing-subscriber", @@ -6171,19 +6190,18 @@ dependencies = [ [[package]] name = "testing_macros" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c15b796025051a07f1ac695ee0cac0883f05a0d510c9d171ef8d31a992e6a5" +checksum = "a39660370116afe46d5ff8bcb01b7afe2140dda3137ef5cb1914681e37a4ee06" dependencies = [ "anyhow", "glob", "once_cell", - "pmutil 0.6.1", "proc-macro2", "quote", "regex", "relative-path", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -6197,31 +6215,42 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -6249,11 +6278,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -6261,16 +6293,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -6301,9 +6334,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -6316,18 +6349,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "pin-project-lite", - "socket2", - "windows-sys 0.48.0", + "socket2 0.5.7", + "windows-sys 0.52.0", ] [[package]] @@ -6344,16 +6376,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -6367,76 +6398,75 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.19.12", + "toml_edit 0.19.15", ] [[package]] name = "toml" -version = "0.8.2" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.5.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.4.7", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.5.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.5.26", + "winnow 0.6.18", ] [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6444,20 +6474,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -6465,20 +6495,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -6494,9 +6524,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.8" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" dependencies = [ "serde", "stable_deref_trait", @@ -6504,15 +6534,15 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttf-parser" -version = "0.19.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" [[package]] name = "tungstenite" @@ -6552,9 +6582,9 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "typescript_tsconfig_json" @@ -6563,7 +6593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7cc416eaf05297012ead9d192226fe9a92e9a20f64f8780efb9085aaae9b590" dependencies = [ "clean-path", - "indexmap 2.2.6", + "indexmap 2.5.0", "rustc-hash", "serde", "serde_json", @@ -6577,83 +6607,86 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uds_windows" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ + "memoffset 0.9.1", "tempfile", "winapi 0.3.9", ] [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-id" -version = "0.3.3" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + +[[package]] +name = "unicode-id-start" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" +checksum = "bc3882f69607a2ac8cc4de3ee7993d8f68bb06f2974271195065b3bd07f2edea" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-linebreak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" -dependencies = [ - "hashbrown 0.12.3", - "regex", -] +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -6666,17 +6699,23 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] name = "valuable" @@ -6686,9 +6725,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vec1" -version = "1.10.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bda7c41ca331fe9a1c278a9e7ee055f4be7f5eb1c2b72f079b4ff8b5fce9d5c" +checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322" [[package]] name = "vec_map" @@ -6698,30 +6737,54 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "7.5.1" +version = "8.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" +checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" dependencies = [ "anyhow", - "cfg-if", - "enum-iterator", + "cargo_metadata", + "regex", + "rustversion", +] + +[[package]] +name = "vergen" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c32e7318e93a9ac53693b6caccfb05ff22e04a44c7cf8a279051f24c09da286f" +dependencies = [ + "anyhow", + "cargo_metadata", + "derive_builder", + "getset", + "regex", + "rustversion", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e06bee42361e43b60f363bad49d63798d0f42fb1768091812270eca00c784720" +dependencies = [ + "anyhow", + "derive_builder", "getset", "rustversion", - "thiserror", - "time", ] [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" @@ -6735,11 +6798,10 @@ dependencies = [ [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -6751,34 +6813,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -6788,9 +6851,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6798,22 +6861,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wayland-client" @@ -6902,9 +6965,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -6912,9 +6975,9 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.11" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2c79b77f525a2d670cb40619d7d9c673d09e0666f72c591ebd7861f84a87e57" +checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" dependencies = [ "core-foundation", "home", @@ -6951,20 +7014,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi 0.3.9", + "windows-sys 0.59.0", ] [[package]] @@ -6981,16 +7035,16 @@ checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ "windows-implement", "windows-interface", - "windows-targets 0.48.0", + "windows-targets 0.48.5", ] [[package]] name = "windows-core" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af6041b3f84485c21b57acdc0fee4f4f0c93f426053dc05fa5d6fc262537bbff" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.52.6", ] [[package]] @@ -7030,7 +7084,25 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -7050,17 +7122,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -7087,9 +7159,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" @@ -7105,9 +7177,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" @@ -7123,9 +7195,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" @@ -7147,9 +7219,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" @@ -7165,9 +7237,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" @@ -7183,9 +7255,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" @@ -7201,9 +7273,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" @@ -7226,9 +7298,9 @@ dependencies = [ "instant", "libc", "log", - "mio", + "mio 0.8.11", "ndk", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", "orbclient", "percent-encoding", @@ -7248,18 +7320,18 @@ dependencies = [ [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] [[package]] name = "winnow" -version = "0.5.26" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -7286,50 +7358,42 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.10.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "gethostname", - "nix 0.24.3", - "winapi 0.3.9", - "winapi-wsapoll", + "rustix 0.38.37", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.10.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" -dependencies = [ - "nix 0.24.3", -] +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" -dependencies = [ - "nom", -] +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xdg-home" -version = "1.0.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ - "nix 0.26.4", - "winapi 0.3.9", + "libc", + "windows-sys 0.59.0", ] [[package]] name = "xml-rs" -version = "0.8.14" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "yaml-rust" @@ -7348,15 +7412,15 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zbus" -version = "3.14.1" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" dependencies = [ "async-broadcast", "async-executor", "async-fs", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-process", "async-recursion", "async-task", @@ -7365,7 +7429,7 @@ dependencies = [ "byteorder", "derivative", "enumflags2", - "event-listener", + "event-listener 2.5.3", "futures-core", "futures-sink", "futures-util", @@ -7389,9 +7453,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "3.14.1" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -7403,9 +7467,9 @@ dependencies = [ [[package]] name = "zbus_names" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" dependencies = [ "serde", "static_assertions", @@ -7414,29 +7478,30 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.26" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.26" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "zvariant" -version = "3.15.0" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" dependencies = [ "byteorder", "enumflags2", @@ -7448,9 +7513,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "3.15.0" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index f5dbe9240..7f4044b07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,11 +3,15 @@ members = ["crates/*"] resolver = "2" [workspace.dependencies] +anyhow = "1.0.71" cached = "0.46.1" +clap = "4.3.11" mimalloc-rust = { version = "=0.2.1" } -serde = { version = "1.0.171", features = ["derive"] } +oneshot = "0.1.8" +regex = "1.9.3" +serde = "1.0.171" serde_json = "1.0.100" -swc_core = { version = "=0.83.22", default-features = false } +swc_core = { version = "0.101.4", default-features = false } tikv-jemallocator = { version = "=0.5.4", features = ["disable_initial_exec_tls"] } [profile.release] diff --git a/biome.json b/biome.json index 6763f765f..381930e4b 100644 --- a/biome.json +++ b/biome.json @@ -20,7 +20,8 @@ "./tmp/**", "./.pnpm-store/**", "./packages/*/dist/**", - "**/package.json" + "**/package.json", + "./crates/svgr-rs/__fixture__/**" ] }, "formatter": { diff --git a/crates/binding/Cargo.toml b/crates/binding/Cargo.toml index df9adf485..dfa62c088 100644 --- a/crates/binding/Cargo.toml +++ b/crates/binding/Cargo.toml @@ -7,12 +7,13 @@ version = "0.0.0" crate-type = ["cdylib"] [dependencies] -anyhow = "1.0.71" +anyhow = { workspace = true } cached = { workspace = true } mako = { path = '../mako' } -napi = { version = "2.14.0", default-features = false, features = ["napi4", "napi5", "serde-json", "tokio_rt"] } -napi-derive = "2.14.0" -rayon = "1.7.0" +napi = { version = "2.16.11", default-features = false, features = ["async", "napi4", "serde-json"] } +napi-derive = "2.16.12" +oneshot = { workspace = true } +serde = { workspace = true } serde_json = { workspace = true } [target.'cfg(not(target_os = "linux"))'.dependencies] diff --git a/crates/binding/src/js_hook.rs b/crates/binding/src/js_hook.rs new file mode 100644 index 000000000..fcf0615ea --- /dev/null +++ b/crates/binding/src/js_hook.rs @@ -0,0 +1,127 @@ +use napi::bindgen_prelude::*; +use napi::NapiRaw; +use napi_derive::napi; +use serde_json::Value; + +use crate::threadsafe_function::ThreadsafeFunction; + +#[napi(object)] +pub struct JsHooks { + pub name: Option, + #[napi( + ts_type = "(filePath: string) => Promise<{ content: string, type: 'css'|'js' } | void> | void;" + )] + pub load: Option, + #[napi(ts_type = "(filePath: string) => Promise | bool;")] + pub load_include: Option, + #[napi(ts_type = r#"(data: { + isFirstCompile: boolean; + time: number; + stats: { + hash: number; + builtAt: number; + rootPath: string; + outputPath: string; + assets: { type: string; name: string; path: string; size: number }[]; + chunkModules: { + type: string; + id: string; + chunks: string[]; + size: number; + }[]; + modules: Record< + string, + { id: string; dependents: string[]; dependencies: string[] } + >; + chunks: { + type: string; + id: string; + files: string[]; + entry: boolean; + modules: { type: string; id: string; size: number; chunks: string[] }[]; + siblings: string[]; + origin: { + module: string; + moduleIdentifier: string; + moduleName: string; + loc: string; + request: string; + }[]; + }[]; + entrypoints: Record; + rscClientComponents: { path; string; moduleId: string }[]; + rscCSSModules: { path; string; moduleId: string; modules: boolean }[]; + startTime: number; + endTime: number; + }; + }) => void"#)] + pub generate_end: Option, + #[napi(ts_type = "(path: string, content: Buffer) => Promise;")] + pub _on_generate_file: Option, + #[napi(ts_type = "() => Promise;")] + pub build_start: Option, + #[napi( + ts_type = "(source: string, importer: string, { isEntry: bool }) => Promise<{ id: string }>;" + )] + pub resolve_id: Option, +} + +pub struct TsFnHooks { + pub build_start: Option>, + pub generate_end: Option>, + pub load: Option>>, + pub load_include: Option>>, + pub resolve_id: + Option>>, + pub _on_generate_file: Option>, +} + +impl TsFnHooks { + pub fn new(env: Env, hooks: &JsHooks) -> Self { + Self { + build_start: hooks.build_start.as_ref().map(|hook| unsafe { + ThreadsafeFunction::from_napi_value(env.raw(), hook.raw()).unwrap() + }), + generate_end: hooks.generate_end.as_ref().map(|hook| unsafe { + ThreadsafeFunction::from_napi_value(env.raw(), hook.raw()).unwrap() + }), + load: hooks.load.as_ref().map(|hook| unsafe { + ThreadsafeFunction::from_napi_value(env.raw(), hook.raw()).unwrap() + }), + load_include: hooks.load_include.as_ref().map(|hook| unsafe { + ThreadsafeFunction::from_napi_value(env.raw(), hook.raw()).unwrap() + }), + resolve_id: hooks.resolve_id.as_ref().map(|hook| unsafe { + ThreadsafeFunction::from_napi_value(env.raw(), hook.raw()).unwrap() + }), + _on_generate_file: hooks._on_generate_file.as_ref().map(|hook| unsafe { + ThreadsafeFunction::from_napi_value(env.raw(), hook.raw()).unwrap() + }), + } + } +} + +#[napi(object)] +pub struct WriteFile { + pub path: String, + #[napi(ts_type = "Buffer")] + pub content: Vec, +} + +#[napi(object, use_nullable = true)] +pub struct LoadResult { + pub content: String, + #[napi(js_name = "type")] + pub content_type: String, +} + +#[napi(object, use_nullable = true)] +pub struct ResolveIdResult { + pub id: String, + pub external: Option, +} + +#[napi(object)] +pub struct ResolveIdParams { + pub is_entry: bool, +} diff --git a/crates/binding/src/js_plugin.rs b/crates/binding/src/js_plugin.rs index 345157c9b..e42b76762 100644 --- a/crates/binding/src/js_plugin.rs +++ b/crates/binding/src/js_plugin.rs @@ -1,7 +1,7 @@ -use std::sync::{mpsc, Arc}; +use std::path::PathBuf; +use std::sync::Arc; -use crate::threadsafe_function; -use crate::tsfn::{LoadResult, ReadMessage, TsFnHooks, WriteRequest}; +use crate::js_hook::{LoadResult, ResolveIdParams, ResolveIdResult, TsFnHooks, WriteFile}; pub struct JsPlugin { pub hooks: TsFnHooks, @@ -9,7 +9,8 @@ pub struct JsPlugin { use anyhow::{anyhow, Result}; use mako::ast::file::{Content, JsContent}; use mako::compiler::Context; -use mako::plugin::{Plugin, PluginGenerateEndParams, PluginLoadParam}; +use mako::plugin::{Plugin, PluginGenerateEndParams, PluginLoadParam, PluginResolveIdParams}; +use mako::resolve::{ExternalResource, Resolution, ResolvedResource, ResolverResource}; impl Plugin for JsPlugin { fn name(&self) -> &str { @@ -18,30 +19,25 @@ impl Plugin for JsPlugin { fn build_start(&self, _context: &Arc) -> Result<()> { if let Some(hook) = &self.hooks.build_start { - let (tx, rx) = mpsc::channel::>(); - hook.call( - ReadMessage { message: (), tx }, - threadsafe_function::ThreadsafeFunctionCallMode::Blocking, - ); - rx.recv() - .unwrap_or_else(|e| panic!("recv error: {:?}", e.to_string()))?; + hook.call(())? } Ok(()) } fn load(&self, param: &PluginLoadParam, _context: &Arc) -> Result> { if let Some(hook) = &self.hooks.load { - let (tx, rx) = mpsc::channel::>>(); - hook.call( - ReadMessage { - message: param.file.path.to_string_lossy().to_string(), - tx, - }, - threadsafe_function::ThreadsafeFunctionCallMode::Blocking, - ); - let x = rx - .recv() - .unwrap_or_else(|e| panic!("recv error: {:?}", e.to_string()))?; + if self.hooks.load_include.is_some() + && self + .hooks + .load_include + .as_ref() + .unwrap() + .call(param.file.path.to_string_lossy().to_string())? + == Some(false) + { + return Ok(None); + } + let x: Option = hook.call(param.file.path.to_string_lossy().to_string())?; if let Some(x) = x { match x.content_type.as_str() { "js" | "ts" => { @@ -64,35 +60,55 @@ impl Plugin for JsPlugin { Ok(None) } + fn resolve_id( + &self, + source: &str, + importer: &str, + params: &PluginResolveIdParams, + _context: &Arc, + ) -> Result> { + if let Some(hook) = &self.hooks.resolve_id { + let x: Option = hook.call(( + source.to_string(), + importer.to_string(), + ResolveIdParams { + is_entry: params.is_entry, + }, + ))?; + if let Some(x) = x { + if let Some(true) = x.external { + return Ok(Some(ResolverResource::External(ExternalResource { + source: source.to_string(), + external: source.to_string(), + script: None, + }))); + } + return Ok(Some(ResolverResource::Resolved(ResolvedResource( + Resolution { + path: PathBuf::from(x.id), + query: None, + fragment: None, + package_json: None, + }, + )))); + } + } + Ok(None) + } + fn generate_end(&self, param: &PluginGenerateEndParams, _context: &Arc) -> Result<()> { if let Some(hook) = &self.hooks.generate_end { - let (tx, rx) = mpsc::channel::>(); - hook.call( - ReadMessage { - message: param.clone(), - tx, - }, - threadsafe_function::ThreadsafeFunctionCallMode::Blocking, - ); - rx.recv() - .unwrap_or_else(|e| panic!("recv error: {:?}", e.to_string()))?; + hook.call(serde_json::to_value(param)?)? } Ok(()) } fn before_write_fs(&self, path: &std::path::Path, content: &[u8]) -> Result<()> { if let Some(hook) = &self.hooks._on_generate_file { - let (tx, rx) = mpsc::channel::>(); - hook.call( - WriteRequest { - path: path.to_path_buf(), - content: content.to_vec(), - tx, - }, - threadsafe_function::ThreadsafeFunctionCallMode::Blocking, - ); - rx.recv() - .unwrap_or_else(|e| panic!("recv error: {:?}", e.to_string()))?; + hook.call(WriteFile { + path: path.to_string_lossy().to_string(), + content: content.to_vec(), + })?; } Ok(()) } diff --git a/crates/binding/src/lib.rs b/crates/binding/src/lib.rs index 596183407..79cd93143 100644 --- a/crates/binding/src/lib.rs +++ b/crates/binding/src/lib.rs @@ -1,24 +1,22 @@ #![deny(clippy::all)] -#[macro_use] -extern crate napi_derive; - use std::sync::{Arc, Once}; +use js_hook::{JsHooks, TsFnHooks}; use js_plugin::JsPlugin; use mako::compiler::{Args, Compiler}; use mako::config::Config; use mako::dev::DevServer; use mako::plugin::Plugin; use mako::utils::logger::init_logger; +use mako::utils::thread_pool; use napi::bindgen_prelude::*; use napi::{JsObject, Status}; -use tsfn::{JsHooks, TsFnHooks}; +use napi_derive::napi; +mod js_hook; mod js_plugin; -mod tsfn; - -pub(crate) mod threadsafe_function; +mod threadsafe_function; #[cfg(not(target_os = "linux"))] #[global_allocator] @@ -226,7 +224,7 @@ pub fn build(env: Env, build_params: BuildParams) -> napi::Result { Ok(promise) } else { let (deferred, promise) = env.create_deferred()?; - rayon::spawn(move || { + thread_pool::spawn(move || { let compiler = Compiler::new(config, root.clone(), Args { watch: false }, Some(plugins)) .map_err(|e| napi::Error::new(Status::GenericFailure, format!("{}", e))); diff --git a/crates/binding/src/threadsafe_function.rs b/crates/binding/src/threadsafe_function.rs index 5d25a06d3..21011a81f 100644 --- a/crates/binding/src/threadsafe_function.rs +++ b/crates/binding/src/threadsafe_function.rs @@ -1,302 +1,73 @@ -// Fork of threadsafe_function from napi-rs that allows calling JS function manually rather than -// only returning args. This enables us to use the return value of the function. - -#![allow(clippy::single_component_path_imports)] - -use std::convert::Into; -use std::ffi::CString; use std::marker::PhantomData; -use std::os::raw::c_void; -use std::ptr; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use std::sync::Arc; - -use napi::{check_status, sys, Env, JsError, JsFunction, NapiValue, Result, Status}; - -/// ThreadSafeFunction Context object -/// the `value` is the value passed to `call` method -pub struct ThreadSafeCallContext { - pub env: Env, - pub value: T, - pub callback: Option, -} - -#[repr(u8)] -pub enum ThreadsafeFunctionCallMode { - NonBlocking, - Blocking, -} - -impl From for sys::napi_threadsafe_function_call_mode { - fn from(value: ThreadsafeFunctionCallMode) -> Self { - match value { - ThreadsafeFunctionCallMode::Blocking => sys::ThreadsafeFunctionCallMode::blocking, - ThreadsafeFunctionCallMode::NonBlocking => sys::ThreadsafeFunctionCallMode::nonblocking, - } - } -} -/// Communicate with the addon's main thread by invoking a JavaScript function from other threads. -/// -/// ## Example -/// An example of using `ThreadsafeFunction`: -/// -/// ```rust -/// #[macro_use] -/// extern crate napi_derive; -/// -/// use std::thread; -/// -/// use napi::{ -/// threadsafe_function::{ -/// ThreadSafeCallContext, ThreadsafeFunctionCallMode, ThreadsafeFunctionReleaseMode, -/// }, -/// CallContext, Error, JsFunction, JsNumber, JsUndefined, Result, Status, -/// }; -/// -/// #[js_function(1)] -/// pub fn test_threadsafe_function(ctx: CallContext) -> Result { -/// let func = ctx.get::(0)?; -/// -/// let tsfn = -/// ctx -/// .env -/// .create_threadsafe_function(&func, 0, |ctx: ThreadSafeCallContext>| { -/// ctx.value -/// .iter() -/// .map(|v| ctx.env.create_uint32(*v)) -/// .collect::>>() -/// })?; -/// -/// let tsfn_cloned = tsfn.clone(); -/// -/// thread::spawn(move || { -/// let output: Vec = vec![0, 1, 2, 3]; -/// // It's okay to call a threadsafe function multiple times. -/// tsfn.call(Ok(output.clone()), ThreadsafeFunctionCallMode::Blocking); -/// }); -/// -/// thread::spawn(move || { -/// let output: Vec = vec![3, 2, 1, 0]; -/// // It's okay to call a threadsafe function multiple times. -/// tsfn_cloned.call(Ok(output.clone()), ThreadsafeFunctionCallMode::NonBlocking); -/// }); -/// -/// ctx.env.get_undefined() -/// } -/// ``` -pub struct ThreadsafeFunction { - raw_tsfn: sys::napi_threadsafe_function, - aborted: Arc, - ref_count: Arc, - _phantom: PhantomData, +use anyhow::{anyhow, Result}; +use napi::bindgen_prelude::{spawn, FromNapiValue, JsValuesTupleIntoVec, Promise}; +use napi::sys::{napi_env, napi_value}; +use napi::threadsafe_function::{ + ErrorStrategy, ThreadsafeFunction as Tsfn, ThreadsafeFunctionCallMode, +}; +use napi::JsUnknown; +use oneshot::channel; + +pub struct ThreadsafeFunction { + tsfn: Tsfn, + env: napi_env, + _phantom: PhantomData, } -impl Clone for ThreadsafeFunction { +impl Clone for ThreadsafeFunction { fn clone(&self) -> Self { - if !self.aborted.load(Ordering::Acquire) { - let acquire_status = unsafe { sys::napi_acquire_threadsafe_function(self.raw_tsfn) }; - debug_assert!( - acquire_status == sys::Status::napi_ok, - "Acquire threadsafe function failed in clone" - ); - } - Self { - raw_tsfn: self.raw_tsfn, - aborted: Arc::clone(&self.aborted), - ref_count: Arc::clone(&self.ref_count), + tsfn: self.tsfn.clone(), + env: self.env, _phantom: PhantomData, } } } -unsafe impl Send for ThreadsafeFunction {} -unsafe impl Sync for ThreadsafeFunction {} - -impl ThreadsafeFunction { - /// See [napi_create_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_create_threadsafe_function) - /// for more information. - pub(crate) fn create) -> Result<()>>( - env: sys::napi_env, - func: sys::napi_value, - max_queue_size: usize, - callback: R, - ) -> Result { - let mut async_resource_name = ptr::null_mut(); - let s = "napi_rs_threadsafe_function"; - let len = s.len(); - let s = CString::new(s)?; - check_status!(unsafe { - sys::napi_create_string_utf8(env, s.as_ptr(), len, &mut async_resource_name) - })?; - - let initial_thread_count = 1usize; - let mut raw_tsfn = ptr::null_mut(); - let ptr = Box::into_raw(Box::new(callback)) as *mut c_void; - check_status!(unsafe { - sys::napi_create_threadsafe_function( - env, - func, - ptr::null_mut(), - async_resource_name, - max_queue_size, - initial_thread_count, - ptr, - Some(thread_finalize_cb::), - ptr, - Some(call_js_cb::), - &mut raw_tsfn, - ) - })?; - - let aborted = Arc::new(AtomicBool::new(false)); - let aborted_ptr = Arc::into_raw(aborted.clone()) as *mut c_void; - check_status!(unsafe { - sys::napi_add_env_cleanup_hook(env, Some(cleanup_cb), aborted_ptr) - })?; - - Ok(ThreadsafeFunction { - raw_tsfn, - aborted, - ref_count: Arc::new(AtomicUsize::new(initial_thread_count)), +impl FromNapiValue for ThreadsafeFunction { + unsafe fn from_napi_value(env: napi_env, napi_val: napi_value) -> napi::Result { + let tsfn = Tsfn::from_napi_value(env, napi_val)?; + Ok(Self { + tsfn, + env, _phantom: PhantomData, }) } } -impl ThreadsafeFunction { - /// See [napi_call_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_call_threadsafe_function) - /// for more information. - pub fn call(&self, value: T, mode: ThreadsafeFunctionCallMode) -> Status { - if self.aborted.load(Ordering::Acquire) { - return Status::Closing; - } - unsafe { - sys::napi_call_threadsafe_function( - self.raw_tsfn, - Box::into_raw(Box::new(value)) as *mut _, - mode.into(), - ) - } - .into() - } -} - -impl Drop for ThreadsafeFunction { - fn drop(&mut self) { - if !self.aborted.load(Ordering::Acquire) && self.ref_count.load(Ordering::Acquire) > 0usize - { - let release_status = unsafe { - sys::napi_release_threadsafe_function( - self.raw_tsfn, - sys::ThreadsafeFunctionReleaseMode::release, - ) - }; - assert!( - release_status == sys::Status::napi_ok, - "Threadsafe Function release failed" - ); - } - } -} - -unsafe extern "C" fn cleanup_cb(cleanup_data: *mut c_void) { - let aborted = Arc::::from_raw(cleanup_data.cast()); - aborted.store(true, Ordering::SeqCst); -} - -unsafe extern "C" fn thread_finalize_cb( - _raw_env: sys::napi_env, - finalize_data: *mut c_void, - _finalize_hint: *mut c_void, -) where - R: 'static + Send + FnMut(ThreadSafeCallContext) -> Result<()>, -{ - // cleanup - drop(Box::::from_raw(finalize_data.cast())); -} - -unsafe extern "C" fn call_js_cb( - raw_env: sys::napi_env, - js_callback: sys::napi_value, - context: *mut c_void, - data: *mut c_void, -) where - R: 'static + Send + FnMut(ThreadSafeCallContext) -> Result<()>, -{ - // env and/or callback can be null when shutting down - if raw_env.is_null() { - return; - } - - let ctx: &mut R = &mut *context.cast::(); - let val: Result = Ok(*Box::::from_raw(data.cast())); - - let mut recv = ptr::null_mut(); - sys::napi_get_undefined(raw_env, &mut recv); - - let ret = val.and_then(|v| { - (ctx)(ThreadSafeCallContext { - env: Env::from_raw(raw_env), - value: v, - callback: if js_callback.is_null() { - None - } else { - Some(JsFunction::from_raw(raw_env, js_callback).unwrap()) // TODO: unwrap +impl ThreadsafeFunction { + pub fn call(&self, value: P) -> Result { + let (sender, receiver) = channel(); + self.tsfn.call_with_return_value( + value, + ThreadsafeFunctionCallMode::NonBlocking, + move |r: JsUnknown| { + if r.is_promise().unwrap() { + let promise = Promise::::from_unknown(r).unwrap(); + spawn(async move { + let r = promise.await; + sender + .send( + r.map_err(|e| anyhow!("Tsfn promise rejected {}.", e.to_string())), + ) + .expect("Failed to send napi returned value."); + }); + } else { + let r = R::from_unknown(r).unwrap(); + sender + .send(Ok(r)) + .expect("Failed to send napi returned value."); + } + Ok(()) }, - }) - }); - - let status = match ret { - Ok(()) => sys::Status::napi_ok, - Err(e) => sys::napi_fatal_exception(raw_env, JsError::from(e).into_value(raw_env)), - }; - if status == sys::Status::napi_ok { - return; - } - if status == sys::Status::napi_pending_exception { - let mut error_result = ptr::null_mut(); - assert_eq!( - sys::napi_get_and_clear_last_exception(raw_env, &mut error_result), - sys::Status::napi_ok ); - // When shutting down, napi_fatal_exception sometimes returns another exception - let stat = sys::napi_fatal_exception(raw_env, error_result); - assert!(stat == sys::Status::napi_ok || stat == sys::Status::napi_pending_exception); - } else { - let error_code: Status = status.into(); - let error_code_string = format!("{:?}", error_code); - let mut error_code_value = ptr::null_mut(); - assert_eq!( - sys::napi_create_string_utf8( - raw_env, - error_code_string.as_ptr() as *const _, - error_code_string.len(), - &mut error_code_value, - ), - sys::Status::napi_ok, - ); - let error_msg = "Call JavaScript callback failed in thread safe function"; - let mut error_msg_value = ptr::null_mut(); - assert_eq!( - sys::napi_create_string_utf8( - raw_env, - error_msg.as_ptr() as *const _, - error_msg.len(), - &mut error_msg_value, - ), - sys::Status::napi_ok, - ); - let mut error_value = ptr::null_mut(); - assert_eq!( - sys::napi_create_error(raw_env, error_code_value, error_msg_value, &mut error_value), - sys::Status::napi_ok, - ); - assert_eq!( - sys::napi_fatal_exception(raw_env, error_value), - sys::Status::napi_ok - ); + receiver + .recv() + .expect("Failed to receive napi returned value.") } } + +unsafe impl Sync for ThreadsafeFunction {} +unsafe impl Send for ThreadsafeFunction {} diff --git a/crates/binding/src/tsfn.rs b/crates/binding/src/tsfn.rs deleted file mode 100644 index 4fd5754e2..000000000 --- a/crates/binding/src/tsfn.rs +++ /dev/null @@ -1,285 +0,0 @@ -use std::path::PathBuf; -use std::str::from_utf8_unchecked; -use std::sync::mpsc::Sender; - -use mako::plugin::PluginGenerateEndParams; -use napi::bindgen_prelude::*; -use napi::{JsObject, JsString, JsUnknown, NapiRaw}; - -use crate::threadsafe_function; - -#[napi(object)] -pub struct JsHooks { - pub name: Option, - #[napi( - ts_type = "(filePath: string) => Promise<{ content: string, type: 'css'|'js' } | void> | void;" - )] - pub load: Option, - #[napi(ts_type = r#"(data: { - isFirstCompile: boolean; - time: number; - stats: { - hash: number; - builtAt: number; - rootPath: string; - outputPath: string; - assets: { type: string; name: string; path: string; size: number }[]; - chunkModules: { - type: string; - id: string; - chunks: string[]; - size: number; - }[]; - modules: Record< - string, - { id: string; dependents: string[]; dependencies: string[] } - >; - chunks: { - type: string; - id: string; - files: string[]; - entry: boolean; - modules: { type: string; id: string; size: number; chunks: string[] }[]; - siblings: string[]; - origin: { - module: string; - moduleIdentifier: string; - moduleName: string; - loc: string; - request: string; - }[]; - }[]; - entrypoints: Record; - rscClientComponents: { path; string; moduleId: string }[]; - rscCSSModules: { path; string; moduleId: string; modules: boolean }[]; - startTime: number; - endTime: number; - }; - }) => void"#)] - pub generate_end: Option, - #[napi(ts_type = "(path: string, content: Buffer) => Promise;")] - pub _on_generate_file: Option, - #[napi(ts_type = "() => Promise;")] - pub build_start: Option, -} - -pub struct TsFnHooks { - pub name: String, - pub build_start: Option>>, - pub generate_end: - Option>>, - pub load: - Option>>>, - pub _on_generate_file: Option>, -} - -impl TsFnHooks { - pub fn new(env: Env, hooks: &JsHooks) -> Self { - let name = if let Some(name) = &hooks.name { - name.clone() - } else { - "unnamed_js_plugin".to_string() - }; - Self { - name, - build_start: hooks.build_start.as_ref().map(|hook| { - threadsafe_function::ThreadsafeFunction::create( - env.raw(), - unsafe { hook.raw() }, - 0, - |ctx: threadsafe_function::ThreadSafeCallContext>| { - let obj = ctx.env.create_object()?; - let result = ctx.callback.unwrap().call(None, &[obj])?; - await_promise_with_void(ctx.env, result, ctx.value.tx).unwrap(); - Ok(()) - }, - ) - .unwrap() - }), - generate_end: hooks.generate_end.as_ref().map(|hook| { - threadsafe_function::ThreadsafeFunction::create( - env.raw(), - unsafe { hook.raw() }, - 0, - |ctx: threadsafe_function::ThreadSafeCallContext< - ReadMessage, - >| { - let obj = ctx - .env - .to_js_value(&serde_json::to_value(ctx.value.message)?)?; - let result = ctx.callback.unwrap().call(None, &[obj])?; - await_promise_with_void(ctx.env, result, ctx.value.tx).unwrap(); - Ok(()) - }, - ) - .unwrap() - }), - load: hooks.load.as_ref().map(|hook| { - threadsafe_function::ThreadsafeFunction::create( - env.raw(), - unsafe { hook.raw() }, - 0, - |ctx: threadsafe_function::ThreadSafeCallContext< - ReadMessage>, - >| { - let str = ctx.env.create_string(&ctx.value.message)?; - let result = ctx.callback.unwrap().call(None, &[str])?; - await_promise_js_object(ctx.env, result, ctx.value.tx).unwrap(); - Ok(()) - }, - ) - .unwrap() - }), - _on_generate_file: hooks._on_generate_file.as_ref().map(|hook| { - threadsafe_function::ThreadsafeFunction::create( - env.raw(), - unsafe { hook.raw() }, - 0, - |ctx: threadsafe_function::ThreadSafeCallContext| unsafe { - let path_str = ctx.value.path.to_str().unwrap(); - let str = ctx.env.create_string(path_str)?; - let buffer = ctx - .env - .create_string(from_utf8_unchecked(&ctx.value.content))?; - let result = ctx.callback.unwrap().call(None, &[str, buffer])?; - await_promise_with_void(ctx.env, result, ctx.value.tx).unwrap(); - Ok(()) - }, - ) - .unwrap() - }), - } - } -} - -#[allow(dead_code)] -fn await_promise( - env: Env, - result: JsUnknown, - tx: Sender>, -) -> napi::Result<()> { - // If the result is a promise, wait for it to resolve, and send the result to the channel. - // Otherwise, send the result immediately. - if result.is_promise()? { - let result: JsObject = result.try_into()?; - let then: JsFunction = result.get_named_property("then")?; - let tx2 = tx.clone(); - let cb = env.create_function_from_closure("callback", move |ctx| { - let res = ctx.get::(0)?.into_utf8()?; - let s = res.into_owned()?; - tx.send(Ok(s)).unwrap(); - ctx.env.get_undefined() - })?; - let eb = env.create_function_from_closure("error_callback", move |ctx| { - let res = ctx.get::(0)?; - tx2.send(Err(napi::Error::from(res))).unwrap(); - ctx.env.get_undefined() - })?; - then.call(Some(&result), &[cb, eb])?; - } else { - let result: JsString = result.try_into()?; - let utf8 = result.into_utf8()?; - let s = utf8.into_owned()?; - tx.send(Ok(s)).unwrap(); - } - - Ok(()) -} - -fn await_promise_js_object( - env: Env, - result: JsUnknown, - tx: Sender>>, -) -> napi::Result<()> { - // If the result is a promise, wait for it to resolve, and send the result to the channel. - // Otherwise, send the result immediately. - if result.is_promise()? { - let result: JsObject = result.try_into()?; - let then: JsFunction = result.get_named_property("then")?; - let tx2 = tx.clone(); - let cb = env.create_function_from_closure("callback", move |ctx| { - let res = ctx.get::(0)?; - if matches!(res.get_type()?, ValueType::Undefined) { - tx.send(Ok(None)).unwrap(); - return ctx.env.get_undefined(); - } - let res: JsObject = res.try_into()?; - // let s = res.into_owned()?; - // get res.content as string - // println!("res: {:}", res.get_element(0)?.into_utf8()?.into_owned()?); - let content: JsString = res.get_named_property("content")?; - let content_type: JsString = res.get_named_property("type")?; - tx.send(Ok(Some(LoadResult { - content: content.into_utf8()?.into_owned()?, - content_type: content_type.into_utf8()?.into_owned()?, - }))) - .unwrap(); - ctx.env.get_undefined() - })?; - let eb = env.create_function_from_closure("error_callback", move |ctx| { - let res = ctx.get::(0)?; - tx2.send(Err(napi::Error::from(res))).unwrap(); - ctx.env.get_undefined() - })?; - then.call(Some(&result), &[cb, eb])?; - } else { - if matches!(result.get_type()?, ValueType::Undefined) { - tx.send(Ok(None)).unwrap(); - return Ok(()); - } - let res: JsObject = result.try_into()?; - let content: JsString = res.get_named_property("content")?; - let content_type: JsString = res.get_named_property("type")?; - tx.send(Ok(Some(LoadResult { - content: content.into_utf8()?.into_owned()?, - content_type: content_type.into_utf8()?.into_owned()?, - }))) - .unwrap(); - } - - Ok(()) -} - -fn await_promise_with_void( - env: Env, - result: JsUnknown, - tx: Sender>, -) -> napi::Result<()> { - // If the result is a promise, wait for it to resolve, and send the result to the channel. - // Otherwise, send the result immediately. - if result.is_promise()? { - let result: JsObject = result.try_into()?; - let then: JsFunction = result.get_named_property("then")?; - let tx2 = tx.clone(); - let cb = env.create_function_from_closure("callback", move |ctx| { - tx.send(Ok(())).unwrap(); - ctx.env.get_undefined() - })?; - let eb = env.create_function_from_closure("error_callback", move |ctx| { - let res = ctx.get::(0)?; - tx2.send(Err(napi::Error::from(res))).unwrap(); - ctx.env.get_undefined() - })?; - then.call(Some(&result), &[cb, eb])?; - } else { - tx.send(Ok(())).unwrap(); - } - - Ok(()) -} - -pub struct ReadMessage { - pub message: T, - pub tx: Sender>, -} - -pub struct WriteRequest { - pub path: PathBuf, - pub content: Vec, - pub tx: Sender>, -} - -pub struct LoadResult { - pub content: String, - pub content_type: String, -} diff --git a/crates/mako/Cargo.toml b/crates/mako/Cargo.toml index f1f2ded89..4c0cc4cc2 100644 --- a/crates/mako/Cargo.toml +++ b/crates/mako/Cargo.toml @@ -14,7 +14,6 @@ test = false bitflags = { version = "2.4.2", features = ["serde"] } cached = { workspace = true } dashmap = "4.0.1" -delegate = "0.12.0" fixedbitset = "0.4.2" get_if_addrs = "0.5.3" glob-match = "0.2.1" @@ -30,13 +29,6 @@ serde_json = { workspace = true } url = { version = "2.5.0" } swc_core = { workspace = true, features = [ - "__ecma", - "__ecma_plugin_transform", - "__ecma_transforms", - "__parser", - "__testing_transform", - "__utils", - "__visit", "base", "common_concurrent", "common_sourcemap", @@ -50,11 +42,11 @@ swc_core = { workspace = true, features = [ "css_prefixer", "css_utils", "css_visit", - "css_visit_path", "ecma_ast", "ecma_codegen", "ecma_minifier", "ecma_minifier_concurrent", + "ecma_parser", "ecma_preset_env", "ecma_quote", "ecma_transforms_compat", @@ -63,18 +55,19 @@ swc_core = { workspace = true, features = [ "ecma_transforms_proposal", "ecma_transforms_react", "ecma_transforms_typescript", + "ecma_utils", "ecma_visit_path", "swc_ecma_quote_macros", ] } -swc_emotion = "0.51.0" -swc_error_reporters = "0.16.1" -swc_node_comments = "0.19.1" +swc_emotion = "0.72.19" +swc_error_reporters = "0.21.0" +swc_node_comments = "0.24.0" -anyhow = "1.0.71" +anyhow = { workspace = true } base64 = "0.22.1" chrono = "0.4.38" -clap = { version = "4.3.11", features = ["derive"] } +clap = { workspace = true, features = ["derive"] } colored = "2" config = "0.13.3" convert_case = "0.6.0" @@ -89,7 +82,7 @@ hyper-tungstenite = "0.10.0" indexmap = "2.0.0" indicatif = "0.17.8" md5 = "0.7.0" -mdxjs = "0.1.14" +mdxjs = "0.2.6" mime_guess = "2.0.4" notify = { version = "6.1.1", default-features = false, features = ["macos_kqueue"] } notify-debouncer-full = { version = "0.3.1", default-features = false } @@ -100,12 +93,12 @@ petgraph = "0.6.3" puffin = { version = "0.16.0", optional = true } puffin_egui = { version = "0.22.0", optional = true } rayon = "1.7.0" -regex = "1.9.3" +regex = { workspace = true } sailfish = "0.8.3" semver = "1.0.23" serde-xml-rs = "0.6.0" serde_yaml = "0.9.22" -svgr-rs = "0.1.3" +svgr-rs = { path = "../svgr-rs" } thiserror = "1.0.43" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tokio-tungstenite = "0.19.0" diff --git a/crates/mako/src/ast.rs b/crates/mako/src/ast.rs index 6995a5303..e131721a9 100644 --- a/crates/mako/src/ast.rs +++ b/crates/mako/src/ast.rs @@ -1,3 +1,5 @@ +use swc_core::common::SyntaxContext; + pub(crate) mod comments; pub(crate) mod css_ast; pub(crate) mod error; @@ -7,3 +9,5 @@ pub(crate) mod sourcemap; #[cfg(test)] pub mod tests; pub(crate) mod utils; + +pub const DUMMY_CTXT: SyntaxContext = SyntaxContext::empty(); diff --git a/crates/mako/src/ast/comments.rs b/crates/mako/src/ast/comments.rs index afc76e75f..078a81fe2 100644 --- a/crates/mako/src/ast/comments.rs +++ b/crates/mako/src/ast/comments.rs @@ -1,14 +1,13 @@ -use delegate::delegate; use swc_core::common; use swc_core::common::comments::{Comment, Comments as CommentsTrait}; use swc_core::common::{BytePos, Span}; use swc_node_comments::SwcComments; #[derive(Default)] -pub struct Comments(MakoComments); +pub struct Comments(SwcComments); impl Comments { - pub fn get_swc_comments(&self) -> &MakoComments { + pub fn get_swc_comments(&self) -> &SwcComments { &self.0 } @@ -85,38 +84,3 @@ impl Comments { found } } - -#[derive(Clone, Default)] -pub struct MakoComments(SwcComments); - -impl CommentsTrait for MakoComments { - fn add_pure_comment(&self, pos: BytePos) { - //ref: https://github.com/swc-project/swc/pull/8172 - if pos.is_dummy() { - #[cfg(debug_assertions)] - { - use tracing::warn; - warn!("still got pure comments at dummy pos! UPGRADE SWC!!!"); - } - return; - } - self.0.add_pure_comment(pos); - } - - delegate! { - to self.0 { - fn add_leading(&self, pos: BytePos, cmt: Comment); - fn add_leading_comments(&self, pos: BytePos, comments: Vec); - fn has_leading(&self, pos: BytePos) -> bool; - fn move_leading(&self, from: BytePos, to: BytePos); - fn take_leading(&self, pos: BytePos) -> Option>; - fn get_leading(&self, pos: BytePos) -> Option>; - fn add_trailing(&self, pos: BytePos, cmt: Comment); - fn add_trailing_comments(&self, pos: BytePos, comments: Vec); - fn has_trailing(&self, pos: BytePos) -> bool; - fn move_trailing(&self, from: BytePos, to: BytePos); - fn take_trailing(&self, pos: BytePos) -> Option>; - fn get_trailing(&self, pos: BytePos) -> Option>; - } - } -} diff --git a/crates/mako/src/ast/css_ast.rs b/crates/mako/src/ast/css_ast.rs index 12d55e841..931ae6b99 100644 --- a/crates/mako/src/ast/css_ast.rs +++ b/crates/mako/src/ast/css_ast.rs @@ -37,7 +37,7 @@ impl fmt::Debug for CssAst { impl CssAst { pub fn new(file: &File, context: Arc, css_modules: bool) -> Result { let fm = context.meta.css.cm.new_source_file( - FileName::Real(file.relative_path.clone()), + FileName::Real(file.relative_path.clone()).into(), file.get_content_raw(), ); let config = parser::parser::ParserConfig { @@ -45,7 +45,10 @@ impl CssAst { legacy_ie: true, ..Default::default() }; - let lexer = parser::lexer::Lexer::new(StringInput::from(&*fm), config); + + let comments = context.meta.css.comments.clone(); + + let lexer = parser::lexer::Lexer::new(StringInput::from(&*fm), Some(&comments), config); let mut parser = parser::parser::Parser::new(lexer, config); let parse_result = parser.parse_all(); let mut ast_errors = parser.take_errors(); diff --git a/crates/mako/src/ast/js_ast.rs b/crates/mako/src/ast/js_ast.rs index 303fd78aa..b6a3c9edd 100644 --- a/crates/mako/src/ast/js_ast.rs +++ b/crates/mako/src/ast/js_ast.rs @@ -9,7 +9,7 @@ use swc_core::ecma::codegen::text_writer::JsWriter; use swc_core::ecma::codegen::{Config as JsCodegenConfig, Emitter}; use swc_core::ecma::parser::error::SyntaxError; use swc_core::ecma::parser::lexer::Lexer; -use swc_core::ecma::parser::{EsConfig, Parser, StringInput, Syntax, TsConfig}; +use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax, TsSyntax}; use swc_core::ecma::transforms::base::helpers::inject_helpers; use swc_core::ecma::utils::contains_top_level_await; use swc_core::ecma::visit; @@ -42,13 +42,13 @@ impl fmt::Debug for JsAst { impl JsAst { pub fn new(file: &File, context: Arc) -> Result { let fm = context.meta.script.cm.new_source_file( - FileName::Real(file.relative_path.to_path_buf()), + FileName::Real(file.relative_path.to_path_buf()).into(), file.get_content_raw(), ); let comments = context.meta.script.origin_comments.read().unwrap(); let extname = &file.extname; let syntax = if extname == "ts" || extname == "tsx" { - Syntax::Typescript(TsConfig { + Syntax::Typescript(TsSyntax { tsx: extname == "tsx", decorators: true, ..Default::default() @@ -57,7 +57,7 @@ impl JsAst { let jsx = file.is_content_jsx() || extname == "jsx" || (extname == "js" && !file.is_under_node_modules); - Syntax::Es(EsConfig { + Syntax::Es(EsSyntax { jsx, decorators: true, decorators_before_export: true, diff --git a/crates/mako/src/ast/sourcemap.rs b/crates/mako/src/ast/sourcemap.rs index 392729f8c..1caf96cc0 100644 --- a/crates/mako/src/ast/sourcemap.rs +++ b/crates/mako/src/ast/sourcemap.rs @@ -68,11 +68,22 @@ impl From for RawSourceMap { impl From for swc_sourcemap::SourceMap { fn from(rsm: RawSourceMap) -> Self { Self::new( - rsm.file, + rsm.file.map(|f| f.into_boxed_str().into()), rsm.tokens, - rsm.names, - rsm.sources, - Some(rsm.sources_content), + rsm.names + .into_iter() + .map(|n| n.into_boxed_str().into()) + .collect(), + rsm.sources + .into_iter() + .map(|n| n.into_boxed_str().into()) + .collect(), + Some( + rsm.sources_content + .into_iter() + .map(|op_string| op_string.map(|s| s.into_boxed_str().into())) + .collect(), + ), ) } } @@ -126,9 +137,10 @@ pub fn merge_source_map( final_token.get_src_col(), replaced_source.as_deref(), final_token.get_name(), + false, ); - // add source centent + // add source content if !builder.has_source_contents(added_token.src_id) { let source_content = final_token.get_source_view().map(|view| view.source()); diff --git a/crates/mako/src/ast/utils.rs b/crates/mako/src/ast/utils.rs index 7c0626001..2ef8ba3be 100644 --- a/crates/mako/src/ast/utils.rs +++ b/crates/mako/src/ast/utils.rs @@ -1,7 +1,7 @@ use swc_core::common::{Mark, DUMMY_SP}; use swc_core::ecma::ast::{ - CallExpr, Callee, Expr, ExprOrSpread, Ident, Import, Lit, MemberExpr, MemberProp, MetaPropExpr, - MetaPropKind, Module, ModuleItem, + CallExpr, Callee, Expr, ExprOrSpread, Ident, IdentName, Import, Lit, MemberExpr, MemberProp, + MetaPropExpr, MetaPropKind, Module, ModuleItem, }; pub fn is_remote_or_data(url: &str) -> bool { @@ -66,7 +66,7 @@ pub fn get_call_expr_ident(call_expr: &CallExpr) -> Option<&Ident> { } pub fn is_ident_undefined(ident: &Ident, sym: &str, unresolved_mark: &Mark) -> bool { - ident.sym == *sym && ident.span.ctxt.outer() == *unresolved_mark + ident.sym == *sym && ident.ctxt.outer() == *unresolved_mark } pub fn get_first_str_arg(call_expr: &CallExpr) -> Option { @@ -92,7 +92,7 @@ pub fn is_import_meta_url(expr: &Expr) -> bool { .. }), prop: - MemberProp::Ident(Ident { + MemberProp::Ident(IdentName { sym, .. }), @@ -103,16 +103,16 @@ pub fn is_import_meta_url(expr: &Expr) -> bool { pub fn id(s: &str) -> Ident { Ident { + ctxt: Default::default(), span: DUMMY_SP, sym: s.into(), optional: false, } } pub fn member_prop(s: &str) -> MemberProp { - MemberProp::Ident(Ident { + MemberProp::Ident(IdentName { span: DUMMY_SP, sym: s.into(), - optional: false, }) } @@ -127,6 +127,7 @@ pub fn promise_all(promises: ExprOrSpread) -> Expr { pub fn member_call(obj: Expr, member_prop: MemberProp, args: Vec) -> Expr { Expr::Call(CallExpr { span: DUMMY_SP, + ctxt: Default::default(), callee: Callee::Expr(Box::new(Expr::Member(MemberExpr { span: DUMMY_SP, obj: Box::new(obj), @@ -140,7 +141,7 @@ pub fn member_call(obj: Expr, member_prop: MemberProp, args: Vec) pub fn require_ensure(source: String) -> Expr { member_call( Expr::Ident(id("__mako_require__")), - MemberProp::Ident(id("ensure")), + MemberProp::Ident(id("ensure").into()), vec![ExprOrSpread { spread: None, expr: Box::new(Expr::Lit(Lit::Str(source.into()))), diff --git a/crates/mako/src/build/analyze_deps.rs b/crates/mako/src/build/analyze_deps.rs index 5286717e0..1bb374aa5 100644 --- a/crates/mako/src/build/analyze_deps.rs +++ b/crates/mako/src/build/analyze_deps.rs @@ -52,7 +52,6 @@ impl AnalyzeDeps { for dep in deps { let result = resolve( - // . &file.resolve_from(&context), &dep, &context.resolvers, diff --git a/crates/mako/src/build/load.rs b/crates/mako/src/build/load.rs index 2ee205e1c..401fd9e52 100644 --- a/crates/mako/src/build/load.rs +++ b/crates/mako/src/build/load.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use mdxjs::{compile, Options as MdxOptions}; +use regex::Regex; use serde_xml_rs::from_str as from_xml_str; use serde_yaml::{from_str as from_yaml_str, Value as YamlValue}; use thiserror::Error; @@ -14,6 +15,7 @@ use crate::ast::file::{Content, File, JsContent}; use crate::compiler::Context; use crate::config::Mode; use crate::plugin::PluginLoadParam; +use crate::utils::create_cached_regex; #[derive(Debug, Error)] enum LoadError { @@ -133,7 +135,7 @@ export function moduleToDom(css) { Err(reason) => { return Err(anyhow!(LoadError::CompileMdError { path: file.path.to_string_lossy().to_string(), - reason, + reason: reason.to_string(), })); } }; @@ -257,7 +259,20 @@ export function moduleToDom(css) { Ok(final_file_name) } }; - if !limit || file_size > context.config.inline_limit.try_into().unwrap() { + let inline_excludes_extensions = context + .config + .inline_excludes_extensions + .clone() + .iter() + .map(|s| create_cached_regex(s)) + .collect::>(); + let should_not_transform_base64 = inline_excludes_extensions + .iter() + .any(|regex| regex.is_match(&file.extname)); + if !limit + || file_size > context.config.inline_limit.try_into().unwrap() + || should_not_transform_base64 + { emit_assets() } else { let base64_result = file.get_base64(); diff --git a/crates/mako/src/build/transform.rs b/crates/mako/src/build/transform.rs index b76481998..b02ce7469 100644 --- a/crates/mako/src/build/transform.rs +++ b/crates/mako/src/build/transform.rs @@ -14,7 +14,7 @@ use swc_core::ecma::transforms::base::helpers::{Helpers, HELPERS}; use swc_core::ecma::transforms::base::{resolver, Assumptions}; use swc_core::ecma::transforms::compat::reserved_words; use swc_core::ecma::transforms::optimization::simplifier; -use swc_core::ecma::transforms::optimization::simplify::{dce, Config as SimpilifyConfig}; +use swc_core::ecma::transforms::optimization::simplify::{dce, Config as SimplifyConfig}; use swc_core::ecma::transforms::proposal::decorators; use swc_core::ecma::visit::{Fold, VisitMut}; @@ -98,13 +98,15 @@ impl Transform { cm.clone(), context.clone(), top_level_mark, + unresolved_mark, ))) } // strip should be ts only // since when use this in js, it will remove all unused imports // which is not expected as what webpack does if is_ts { - visitors.push(Box::new(ts_strip(top_level_mark))) + visitors + .push(Box::new(ts_strip(unresolved_mark, top_level_mark))); } // named default export if context.args.watch && !file.is_under_node_modules && is_jsx { @@ -236,7 +238,7 @@ impl Transform { // this must be kept for tree shaking to work Box::new(simplifier( unresolved_mark, - SimpilifyConfig { + SimplifyConfig { dce: dce::Config { top_level: false, ..Default::default() diff --git a/crates/mako/src/compiler.rs b/crates/mako/src/compiler.rs index 0418a1f89..2f2a5703c 100644 --- a/crates/mako/src/compiler.rs +++ b/crates/mako/src/compiler.rs @@ -10,6 +10,7 @@ use regex::Regex; use swc_core::common::sync::Lrc; use swc_core::common::{Globals, SourceMap, DUMMY_SP}; use swc_core::ecma::ast::Ident; +use swc_node_comments::SwcComments; use tracing::debug; use crate::ast::comments::Comments; @@ -182,6 +183,7 @@ impl ScriptMeta { fn build_ident(ident: &str) -> Ident { Ident { + ctxt: Default::default(), span: DUMMY_SP, sym: ident.into(), optional: false, @@ -191,6 +193,7 @@ fn build_ident(ident: &str) -> Ident { pub struct CssMeta { pub cm: Lrc, pub globals: Globals, + pub comments: SwcComments, } impl CssMeta { @@ -198,6 +201,7 @@ impl CssMeta { Self { cm: Default::default(), globals: Globals::default(), + comments: Default::default(), } } } diff --git a/crates/mako/src/config.rs b/crates/mako/src/config.rs index 51be8ae37..1dbc8c3ef 100644 --- a/crates/mako/src/config.rs +++ b/crates/mako/src/config.rs @@ -1,3 +1,488 @@ -#[allow(clippy::module_inception)] -mod config; -pub use config::*; +mod analyze; +mod code_splitting; +mod dev_server; +mod devtool; +mod duplicate_package_checker; +mod experimental; +mod external; +mod generic_usize; +mod hmr; +mod inline_css; +mod macros; +mod manifest; +mod minifish; +mod mode; +mod module_id_strategy; +mod optimization; +mod output; +mod progress; +mod provider; +mod px2rem; +mod react; +mod resolve; +mod rsc_client; +mod rsc_server; +mod stats; +mod transform_import; +mod tree_shaking; +mod umd; +mod watch; + +use std::collections::HashMap; +use std::fmt; +use std::path::{Path, PathBuf}; + +pub use analyze::AnalyzeConfig; +use anyhow::{anyhow, Result}; +pub use code_splitting::*; +use colored::Colorize; +use config; +pub use dev_server::{deserialize_dev_server, DevServerConfig}; +pub use devtool::{deserialize_devtool, DevtoolConfig}; +pub use duplicate_package_checker::{ + deserialize_check_duplicate_package, DuplicatePackageCheckerConfig, +}; +use experimental::ExperimentalConfig; +pub use external::{ + ExternalAdvanced, ExternalAdvancedSubpath, ExternalAdvancedSubpathConverter, + ExternalAdvancedSubpathRule, ExternalAdvancedSubpathTarget, ExternalConfig, +}; +pub use generic_usize::GenericUsizeDefault; +pub use hmr::{deserialize_hmr, HmrConfig}; +pub use inline_css::{deserialize_inline_css, InlineCssConfig}; +pub use manifest::{deserialize_manifest, ManifestConfig}; +use miette::{miette, ByteOffset, Diagnostic, NamedSource, SourceOffset, SourceSpan}; +pub use minifish::{deserialize_minifish, MinifishConfig}; +pub use mode::Mode; +pub use module_id_strategy::ModuleIdStrategy; +pub use optimization::{deserialize_optimization, OptimizationConfig}; +use output::get_default_chunk_loading_global; +pub use output::{CrossOriginLoading, OutputConfig, OutputMode}; +pub use progress::{deserialize_progress, ProgressConfig}; +pub use provider::Providers; +pub use px2rem::{deserialize_px2rem, Px2RemConfig}; +pub use react::{ReactConfig, ReactRuntimeConfig}; +pub use resolve::ResolveConfig; +pub use rsc_client::{deserialize_rsc_client, LogServerComponent, RscClientConfig}; +pub use rsc_server::{deserialize_rsc_server, RscServerConfig}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +pub use stats::{deserialize_stats, StatsConfig}; +use thiserror::Error; +pub use transform_import::{TransformImportConfig, TransformImportStyle}; +pub use tree_shaking::{deserialize_tree_shaking, TreeShakingStrategy}; +pub use umd::{deserialize_umd, Umd}; +pub use watch::WatchConfig; + +use crate::features::node::Node; + +#[derive(Debug, Diagnostic)] +#[diagnostic(code("mako.config.json parsed failed"))] +struct ConfigParseError { + #[source_code] + src: NamedSource, + #[label("Error here.")] + span: SourceSpan, + message: String, +} + +impl std::error::Error for ConfigParseError {} + +impl fmt::Display for ConfigParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.message) + } +} + +fn validate_mako_config(abs_config_file: String) -> miette::Result<()> { + if Path::new(&abs_config_file).exists() { + let content = std::fs::read_to_string(abs_config_file.clone()) + .map_err(|e| miette!("Failed to read file '{}': {}", &abs_config_file, e))?; + let result: Result = serde_json::from_str(&content); + if let Err(e) = result { + let line = e.line(); + let column = e.column(); + let start = SourceOffset::from_location(&content, line, column); + let span = SourceSpan::new(start, (1 as ByteOffset).into()); + return Err(ConfigParseError { + src: NamedSource::new("mako.config.json", content), + span, + message: e.to_string(), + } + .into()); + } + } + Ok(()) +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +pub enum Platform { + #[serde(rename = "browser")] + Browser, + #[serde(rename = "node")] + Node, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Config { + pub entry: HashMap, + pub output: OutputConfig, + pub resolve: ResolveConfig, + #[serde(deserialize_with = "deserialize_manifest", default)] + pub manifest: Option, + pub mode: Mode, + pub minify: bool, + #[serde(deserialize_with = "deserialize_devtool")] + pub devtool: Option, + pub externals: HashMap, + pub providers: Providers, + pub copy: Vec, + pub public_path: String, + pub inline_limit: usize, + pub inline_excludes_extensions: Vec, + pub targets: HashMap, + pub platform: Platform, + pub module_id_strategy: ModuleIdStrategy, + pub define: HashMap, + pub analyze: Option, + pub stats: Option, + pub mdx: bool, + #[serde(deserialize_with = "deserialize_hmr")] + pub hmr: Option, + #[serde(deserialize_with = "deserialize_dev_server")] + pub dev_server: Option, + #[serde(deserialize_with = "deserialize_code_splitting", default)] + pub code_splitting: Option, + #[serde(deserialize_with = "deserialize_px2rem", default)] + pub px2rem: Option, + #[serde(deserialize_with = "deserialize_progress", default)] + pub progress: Option, + pub hash: bool, + #[serde(rename = "_treeShaking", deserialize_with = "deserialize_tree_shaking")] + pub _tree_shaking: Option, + #[serde(rename = "autoCSSModules")] + pub auto_css_modules: bool, + #[serde(rename = "ignoreCSSParserErrors")] + pub ignore_css_parser_errors: bool, + pub dynamic_import_to_require: bool, + #[serde(deserialize_with = "deserialize_umd", default)] + pub umd: Option, + pub cjs: bool, + pub write_to_disk: bool, + pub transform_import: Vec, + pub chunk_parallel: bool, + pub clean: bool, + pub node_polyfill: bool, + pub ignores: Vec, + #[serde( + rename = "_minifish", + deserialize_with = "deserialize_minifish", + default + )] + pub _minifish: Option, + #[serde(rename = "optimizePackageImports")] + pub optimize_package_imports: bool, + pub emotion: bool, + pub flex_bugs: bool, + #[serde(deserialize_with = "deserialize_optimization")] + pub optimization: Option, + pub react: ReactConfig, + pub emit_assets: bool, + #[serde(rename = "cssModulesExportOnlyLocales")] + pub css_modules_export_only_locales: bool, + #[serde( + rename = "inlineCSS", + deserialize_with = "deserialize_inline_css", + default + )] + pub inline_css: Option, + #[serde( + rename = "rscServer", + deserialize_with = "deserialize_rsc_server", + default + )] + pub rsc_server: Option, + #[serde( + rename = "rscClient", + deserialize_with = "deserialize_rsc_client", + default + )] + pub rsc_client: Option, + pub experimental: ExperimentalConfig, + pub watch: WatchConfig, + pub use_define_for_class_fields: bool, + pub emit_decorator_metadata: bool, + #[serde( + rename = "duplicatePackageChecker", + deserialize_with = "deserialize_check_duplicate_package", + default + )] + pub check_duplicate_package: Option, +} + +const CONFIG_FILE: &str = "mako.config.json"; +const DEFAULT_CONFIG: &str = include_str!("./config/mako.config.default.json"); + +impl Config { + pub fn new( + root: &Path, + default_config: Option<&str>, + cli_config: Option<&str>, + ) -> Result { + let abs_config_file = root.join(CONFIG_FILE); + let abs_config_file = abs_config_file.to_str().unwrap(); + let c = config::Config::builder(); + // default config + let c = c.add_source(config::File::from_str( + DEFAULT_CONFIG, + config::FileFormat::Json5, + )); + // default config from args + let c = if let Some(default_config) = default_config { + c.add_source(config::File::from_str( + default_config, + config::FileFormat::Json5, + )) + } else { + c + }; + // validate user config + validate_mako_config(abs_config_file.to_string()).map_err(|e| anyhow!("{}", e))?; + // user config + let c = c.add_source(config::File::with_name(abs_config_file).required(false)); + // cli config + let c = if let Some(cli_config) = cli_config { + c.add_source(config::File::from_str( + cli_config, + config::FileFormat::Json5, + )) + } else { + c + }; + + let c = c.build()?; + let mut ret = c.try_deserialize::(); + // normalize & check + if let Ok(config) = &mut ret { + // normalize output + if config.output.path.is_relative() { + config.output.path = root.join(config.output.path.to_string_lossy().to_string()); + } + + if config.output.chunk_loading_global.is_empty() { + config.output.chunk_loading_global = + get_default_chunk_loading_global(config.umd.clone(), root); + } + + let node_env_config_opt = config.define.get("NODE_ENV"); + if let Some(node_env_config) = node_env_config_opt { + if node_env_config.as_str() != Some(config.mode.to_string().as_str()) { + let warn_message = format!( + "{}: The configuration of {} conflicts with current {} and will be overwritten as {} ", + "warning".to_string().yellow(), + "NODE_ENV".to_string().yellow(), + "mode".to_string().yellow(), + config.mode.to_string().red() + ); + println!("{}", warn_message); + } + } + + if config.cjs && config.umd.is_some() { + return Err(anyhow!("cjs and umd cannot be used at the same time",)); + } + + if config.hmr.is_some() && config.dev_server.is_none() { + return Err(anyhow!("hmr can only be used with devServer",)); + } + + if config.inline_css.is_some() && config.umd.is_none() { + return Err(anyhow!("inlineCSS can only be used with umd",)); + } + + let mode = format!("\"{}\"", config.mode); + config + .define + .insert("NODE_ENV".to_string(), serde_json::Value::String(mode)); + + if config.public_path != "runtime" && !config.public_path.ends_with('/') { + return Err(anyhow!("public_path must end with '/' or be 'runtime'")); + } + + // 暂不支持 remote external + // 如果 config.externals 中有值是以「script 」开头,则 panic 报错 + let basic_external_values = config + .externals + .values() + .filter_map(|v| match v { + ExternalConfig::Basic(b) => Some(b), + _ => None, + }) + .collect::>(); + for v in basic_external_values { + if v.starts_with("script ") { + return Err(anyhow!( + "remote external is not supported yet, but we found {}", + v.to_string().red() + )); + } + } + + // support default entries + if config.entry.is_empty() { + let file_paths = vec!["src/index.tsx", "src/index.ts", "index.tsx", "index.ts"]; + for file_path in file_paths { + let file_path = root.join(file_path); + if file_path.exists() { + config.entry.insert("index".to_string(), file_path); + break; + } + } + if config.entry.is_empty() { + return Err(anyhow!("Entry is empty")); + } + } + + // normalize entry + let entry_tuples = config + .entry + .clone() + .into_iter() + .map(|(k, v)| { + if let Ok(entry_path) = root.join(v).canonicalize() { + Ok((k, entry_path)) + } else { + Err(anyhow!("entry:{} not found", k,)) + } + }) + .collect::>>()?; + config.entry = entry_tuples.into_iter().collect(); + + // support relative alias + config.resolve.alias = config + .resolve + .alias + .clone() + .into_iter() + .map(|(k, v)| { + let v = if v.starts_with('.') { + root.join(v).to_string_lossy().to_string() + } else { + v + }; + (k, v) + }) + .collect(); + + // dev 环境下不产生 hash, prod 环境下根据用户配置 + if config.mode == Mode::Development { + config.hash = false; + } + + // configure node platform + Node::modify_config(config); + } + ret.map_err(|e| anyhow!("{}: {}", "config error".red(), e.to_string().red())) + } +} + +impl Default for Config { + fn default() -> Self { + let c = config::Config::builder(); + let c = c.add_source(config::File::from_str( + DEFAULT_CONFIG, + config::FileFormat::Json5, + )); + let c = c.build().unwrap(); + c.try_deserialize::().unwrap() + } +} + +#[derive(Error, Debug)] +pub enum ConfigError { + #[error("define value '{0}' is not an Expression")] + InvalidateDefineConfig(String), +} + +#[cfg(test)] +mod tests { + use crate::config::{Config, Mode, Platform}; + + #[test] + fn test_config() { + let current_dir = std::env::current_dir().unwrap(); + let config = Config::new(¤t_dir.join("test/config/normal"), None, None).unwrap(); + println!("{:?}", config); + assert_eq!(config.platform, Platform::Node); + } + + #[test] + fn test_config_args_default() { + let current_dir = std::env::current_dir().unwrap(); + let config = Config::new( + ¤t_dir.join("test/config/normal"), + Some(r#"{"mode":"production"}"#), + None, + ) + .unwrap(); + println!("{:?}", config); + assert_eq!(config.mode, Mode::Production); + } + + #[test] + fn test_config_cli_args() { + let current_dir = std::env::current_dir().unwrap(); + let config = Config::new( + ¤t_dir.join("test/config/normal"), + None, + Some(r#"{"platform":"browser"}"#), + ) + .unwrap(); + println!("{:?}", config); + assert_eq!(config.platform, Platform::Browser); + } + + #[test] + fn test_node_env_conflicts_with_mode() { + let current_dir = std::env::current_dir().unwrap(); + let config = Config::new( + ¤t_dir.join("test/config/node-env"), + None, + Some(r#"{"mode":"development"}"#), + ) + .unwrap(); + assert_eq!( + config.define.get("NODE_ENV"), + Some(&serde_json::Value::String("\"development\"".to_string())) + ); + } + + #[test] + #[should_panic(expected = "public_path must end with '/' or be 'runtime'")] + fn test_config_invalid_public_path() { + let current_dir = std::env::current_dir().unwrap(); + Config::new( + ¤t_dir.join("test/config/normal"), + None, + Some(r#"{"publicPath":"abc"}"#), + ) + .unwrap(); + } + + #[test] + fn test_node_platform() { + let current_dir = std::env::current_dir().unwrap(); + let config = + Config::new(¤t_dir.join("test/config/node-platform"), None, None).unwrap(); + assert_eq!( + config.targets.get("node"), + Some(&14.0), + "use node targets by default if platform is node", + ); + assert!( + config.ignores.iter().any(|i| i.contains("|fs|")), + "ignore Node.js standard library by default if platform is node", + ); + } +} diff --git a/crates/mako/src/config/analyze.rs b/crates/mako/src/config/analyze.rs new file mode 100644 index 000000000..1a4655123 --- /dev/null +++ b/crates/mako/src/config/analyze.rs @@ -0,0 +1,4 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct AnalyzeConfig {} diff --git a/crates/mako/src/config/code_splitting.rs b/crates/mako/src/config/code_splitting.rs new file mode 100644 index 000000000..e517ce539 --- /dev/null +++ b/crates/mako/src/config/code_splitting.rs @@ -0,0 +1,112 @@ +use serde::{Deserialize, Serialize}; + +use super::generic_usize::GenericUsizeDefault; +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Clone, Debug, Default, Eq, PartialEq)] +pub enum AllowChunks { + #[serde(rename = "all")] + All, + #[serde(rename = "entry")] + Entry, + #[serde(rename = "async")] + #[default] + Async, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct CodeSplitting { + pub strategy: CodeSplittingStrategy, + pub options: Option, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub enum CodeSplittingStrategy { + #[serde(rename = "auto")] + Auto, + #[serde(rename = "granular")] + Granular, + #[serde(rename = "advanced")] + Advanced, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(untagged)] +pub enum CodeSplittingStrategyOptions { + Granular(CodeSplittingGranularOptions), + Advanced(CodeSplittingAdvancedOptions), +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct CodeSplittingGranularOptions { + pub framework_packages: Vec, + #[serde(default = "GenericUsizeDefault::<160000>::value")] + pub lib_min_size: usize, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct CodeSplittingAdvancedOptions { + #[serde(default = "GenericUsizeDefault::<20000>::value")] + pub min_size: usize, + pub groups: Vec, +} + +impl Default for CodeSplittingAdvancedOptions { + fn default() -> Self { + CodeSplittingAdvancedOptions { + min_size: GenericUsizeDefault::<20000>::value(), + groups: vec![], + } + } +} + +#[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)] +pub enum ChunkNameSuffixStrategy { + #[serde(rename = "packageName")] + PackageName, + #[serde(rename = "dependentsHash")] + DependentsHash, +} + +#[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct ChunkGroup { + pub name: String, + #[serde(default)] + pub name_suffix: Option, + #[serde(default)] + pub allow_chunks: AllowChunks, + #[serde(default = "GenericUsizeDefault::<1>::value")] + pub min_chunks: usize, + #[serde(default = "GenericUsizeDefault::<20000>::value")] + pub min_size: usize, + #[serde(default = "GenericUsizeDefault::<5000000>::value")] + pub max_size: usize, + #[serde(default)] + pub min_module_size: Option, + #[serde(default)] + pub priority: i8, + #[serde(default)] + // A string raw of regex + pub test: Option, +} + +impl Default for ChunkGroup { + fn default() -> Self { + Self { + allow_chunks: AllowChunks::default(), + min_chunks: GenericUsizeDefault::<1>::value(), + min_size: GenericUsizeDefault::<20000>::value(), + max_size: GenericUsizeDefault::<5000000>::value(), + name: String::default(), + name_suffix: None, + min_module_size: None, + test: None, + priority: i8::default(), + } + } +} + +create_deserialize_fn!(deserialize_code_splitting, CodeSplitting); diff --git a/crates/mako/src/config/config.rs b/crates/mako/src/config/config.rs deleted file mode 100644 index 80c56655a..000000000 --- a/crates/mako/src/config/config.rs +++ /dev/null @@ -1,1091 +0,0 @@ -use std::collections::HashMap; -use std::fmt; -use std::path::{Path, PathBuf}; - -use anyhow::{anyhow, Result}; -use clap::ValueEnum; -use colored::Colorize; -use miette::{miette, ByteOffset, Diagnostic, NamedSource, SourceOffset, SourceSpan}; -use regex::Regex; -use serde::{Deserialize, Deserializer, Serialize}; -use serde_json::Value; -use swc_core::ecma::ast::EsVersion; -use thiserror::Error; -use {clap, config, thiserror}; - -use crate::features::node::Node; -use crate::{plugins, visitors}; - -#[derive(Debug, Diagnostic)] -#[diagnostic(code("mako.config.json parsed failed"))] -struct ConfigParseError { - #[source_code] - src: NamedSource, - #[label("Error here.")] - span: SourceSpan, - message: String, -} - -impl std::error::Error for ConfigParseError {} - -impl fmt::Display for ConfigParseError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.message) - } -} - -fn validate_mako_config(abs_config_file: String) -> miette::Result<()> { - if Path::new(&abs_config_file).exists() { - let content = std::fs::read_to_string(abs_config_file.clone()) - .map_err(|e| miette!("Failed to read file '{}': {}", &abs_config_file, e))?; - let result: Result = serde_json::from_str(&content); - if let Err(e) = result { - let line = e.line(); - let column = e.column(); - let start = SourceOffset::from_location(&content, line, column); - let span = SourceSpan::new(start, (1 as ByteOffset).into()); - return Err(ConfigParseError { - src: NamedSource::new("mako.config.json", content), - span, - message: e.to_string(), - } - .into()); - } - } - Ok(()) -} - -/** - * a macro to create deserialize function that allow false value for optional struct - */ -macro_rules! create_deserialize_fn { - ($fn_name:ident, $struct_type:ty) => { - pub fn $fn_name<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?; - - match value { - // allow false value for optional struct - serde_json::Value::Bool(false) => Ok(None), - // try deserialize - serde_json::Value::Object(obj) => Ok(Some( - serde_json::from_value::<$struct_type>(serde_json::Value::Object(obj)) - .map_err(serde::de::Error::custom)?, - )), - serde_json::Value::String(s) => Ok(Some( - serde_json::from_value::<$struct_type>(serde_json::Value::String(s.clone())) - .map_err(serde::de::Error::custom)?, - )), - _ => Err(serde::de::Error::custom(format!( - "invalid `{}` value: {}", - stringify!($fn_name).replace("deserialize_", ""), - value - ))), - } - } - }; -} -create_deserialize_fn!(deserialize_hmr, HmrConfig); -create_deserialize_fn!(deserialize_dev_server, DevServerConfig); -create_deserialize_fn!(deserialize_manifest, ManifestConfig); -create_deserialize_fn!(deserialize_code_splitting, CodeSplitting); -create_deserialize_fn!(deserialize_px2rem, Px2RemConfig); -create_deserialize_fn!(deserialize_progress, ProgressConfig); -create_deserialize_fn!( - deserialize_check_duplicate_package, - DuplicatePackageCheckerConfig -); -create_deserialize_fn!(deserialize_umd, String); -create_deserialize_fn!(deserialize_devtool, DevtoolConfig); -create_deserialize_fn!(deserialize_tree_shaking, TreeShakingStrategy); -create_deserialize_fn!(deserialize_optimization, OptimizationConfig); -create_deserialize_fn!(deserialize_minifish, MinifishConfig); -create_deserialize_fn!(deserialize_inline_css, InlineCssConfig); -create_deserialize_fn!(deserialize_rsc_client, RscClientConfig); -create_deserialize_fn!(deserialize_rsc_server, RscServerConfig); -create_deserialize_fn!(deserialize_stats, StatsConfig); -create_deserialize_fn!(deserialize_detect_loop, DetectCircularDependence); -create_deserialize_fn!(deserialize_cross_origin_loading, CrossOriginLoading); - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct OutputConfig { - pub path: PathBuf, - pub mode: OutputMode, - pub es_version: EsVersion, - pub meta: bool, - pub chunk_loading_global: String, - pub preserve_modules: bool, - pub preserve_modules_root: PathBuf, - pub skip_write: bool, - #[serde(deserialize_with = "deserialize_cross_origin_loading")] - pub cross_origin_loading: Option, - pub global_module_registry: bool, -} - -#[derive(Deserialize, Serialize, Debug, Clone)] -pub enum CrossOriginLoading { - #[serde(rename = "anonymous")] - Anonymous, - #[serde(rename = "use-credentials")] - UseCredentials, -} - -impl fmt::Display for CrossOriginLoading { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - CrossOriginLoading::Anonymous => write!(f, "anonymous"), - CrossOriginLoading::UseCredentials => write!(f, "use-credentials"), - } - } -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct ManifestConfig { - #[serde( - rename(deserialize = "fileName"), - default = "plugins::manifest::default_manifest_file_name" - )] - pub file_name: String, - #[serde(rename(deserialize = "basePath"), default)] - pub base_path: String, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct ResolveConfig { - pub alias: Vec<(String, String)>, - pub extensions: Vec, -} - -// format: HashMap -// e.g. -// { "process": ("process", "") } -// { "Buffer": ("buffer", "Buffer") } -pub type Providers = HashMap; - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ValueEnum, Clone)] -pub enum Mode { - #[serde(rename = "development")] - Development, - #[serde(rename = "production")] - Production, -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ValueEnum, Clone)] -pub enum OutputMode { - #[serde(rename = "bundle")] - Bundle, - #[serde(rename = "bundless")] - Bundless, -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] -pub enum Platform { - #[serde(rename = "browser")] - Browser, - #[serde(rename = "node")] - Node, -} - -impl std::fmt::Display for Mode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.to_possible_value().unwrap().get_name().fmt(f) - } -} - -#[derive(Deserialize, Serialize, Debug)] -pub enum DevtoolConfig { - /// Generate separate sourcemap file - #[serde(rename = "source-map")] - SourceMap, - /// Generate inline sourcemap - #[serde(rename = "inline-source-map")] - InlineSourceMap, -} - -#[derive(Deserialize, Serialize, Clone, Copy, Debug)] -pub enum ModuleIdStrategy { - #[serde(rename = "hashed")] - Hashed, - #[serde(rename = "named")] - Named, - #[serde(rename = "numeric")] - Numeric, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(rename_all = "camelCase")] -pub struct CodeSplittingGranularOptions { - pub framework_packages: Vec, - #[serde(default = "GenericUsizeDefault::<160000>::value")] - pub lib_min_size: usize, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct StatsConfig { - pub modules: bool, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct AnalyzeConfig {} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub enum CodeSplittingStrategy { - #[serde(rename = "auto")] - Auto, - #[serde(rename = "granular")] - Granular, - #[serde(rename = "advanced")] - Advanced, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(untagged)] -pub enum CodeSplittingStrategyOptions { - Granular(CodeSplittingGranularOptions), - Advanced(CodeSplittingAdvancedOptions), -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct CodeSplitting { - pub strategy: CodeSplittingStrategy, - pub options: Option, -} - -#[derive(Deserialize, Serialize, Clone, Copy, Debug)] -pub enum TreeShakingStrategy { - #[serde(rename = "basic")] - Basic, - #[serde(rename = "advanced")] - Advanced, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct Px2RemConfig { - #[serde(default = "visitors::css_px2rem::default_root")] - pub root: f64, - #[serde(rename = "propBlackList", default)] - pub prop_blacklist: Vec, - #[serde(rename = "propWhiteList", default)] - pub prop_whitelist: Vec, - #[serde(rename = "selectorBlackList", default)] - pub selector_blacklist: Vec, - #[serde(rename = "selectorWhiteList", default)] - pub selector_whitelist: Vec, - #[serde(rename = "selectorDoubleList", default)] - pub selector_doublelist: Vec, - #[serde(rename = "minPixelValue", default)] - pub min_pixel_value: f64, - #[serde(rename = "mediaQuery", default)] - pub media_query: bool, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct ProgressConfig { - #[serde(rename = "progressChars", default)] - pub progress_chars: String, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct DuplicatePackageCheckerConfig { - #[serde(rename = "verbose", default)] - pub verbose: bool, - #[serde(rename = "emitError", default)] - pub emit_error: bool, - #[serde(rename = "showHelp", default)] - pub show_help: bool, -} - -impl Default for Px2RemConfig { - fn default() -> Self { - Px2RemConfig { - root: visitors::css_px2rem::default_root(), - prop_blacklist: vec![], - prop_whitelist: vec![], - selector_blacklist: vec![], - selector_whitelist: vec![], - selector_doublelist: vec![], - min_pixel_value: 0.0, - media_query: false, - } - } -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(untagged)] -pub enum TransformImportStyle { - Built(String), - Source(bool), -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(rename_all = "camelCase")] -pub struct TransformImportConfig { - pub library_name: String, - pub library_directory: Option, - pub style: Option, -} - -#[derive(Deserialize, Serialize, Debug, Hash)] -pub enum ExternalAdvancedSubpathConverter { - PascalCase, -} - -#[derive(Deserialize, Serialize, Debug, Hash)] -#[serde(untagged)] -pub enum ExternalAdvancedSubpathTarget { - Empty, - Tpl(String), -} - -#[derive(Deserialize, Serialize, Debug, Hash)] -pub struct ExternalAdvancedSubpathRule { - pub regex: String, - #[serde(with = "external_target_format")] - pub target: ExternalAdvancedSubpathTarget, - #[serde(rename = "targetConverter")] - pub target_converter: Option, -} - -/** - * custom formatter for convert $EMPTY to enum, because rename is not supported for $ symbol - * @see https://serde.rs/custom-date-format.html - */ -mod external_target_format { - use serde::{self, Deserialize, Deserializer, Serializer}; - - use super::ExternalAdvancedSubpathTarget; - - pub fn serialize(v: &ExternalAdvancedSubpathTarget, serializer: S) -> Result - where - S: Serializer, - { - match v { - ExternalAdvancedSubpathTarget::Empty => serializer.serialize_str("$EMPTY"), - ExternalAdvancedSubpathTarget::Tpl(s) => serializer.serialize_str(s), - } - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let v = String::deserialize(deserializer)?; - - if v == "$EMPTY" { - Ok(ExternalAdvancedSubpathTarget::Empty) - } else { - Ok(ExternalAdvancedSubpathTarget::Tpl(v)) - } - } -} - -#[derive(Deserialize, Serialize, Debug, Hash)] -pub struct ExternalAdvancedSubpath { - pub exclude: Option>, - pub rules: Vec, -} - -#[derive(Deserialize, Serialize, Debug, Hash)] -pub struct ExternalAdvanced { - pub root: String, - #[serde(rename = "type")] - pub module_type: Option, - pub script: Option, - pub subpath: Option, -} - -#[derive(Deserialize, Serialize, Debug, Hash)] -#[serde(untagged)] -pub enum ExternalConfig { - Basic(String), - Advanced(ExternalAdvanced), -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct InjectItem { - pub from: String, - pub named: Option, - pub namespace: Option, - pub exclude: Option, - pub include: Option, - pub prefer_require: Option, -} - -#[derive(Deserialize, Serialize, Debug, Clone)] -pub enum ReactRuntimeConfig { - #[serde(rename = "automatic")] - Automatic, - #[serde(rename = "classic")] - Classic, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct ReactConfig { - pub pragma: String, - #[serde(rename = "importSource")] - pub import_source: String, - pub runtime: ReactRuntimeConfig, - #[serde(rename = "pragmaFrag")] - pub pragma_frag: String, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct MinifishConfig { - pub mapping: HashMap, - pub meta_path: Option, - pub inject: Option>, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct OptimizationConfig { - pub skip_modules: Option, - pub concatenate_modules: Option, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct InlineCssConfig {} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct RscServerConfig { - pub client_component_tpl: String, - #[serde(rename = "emitCSS")] - pub emit_css: bool, -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ValueEnum, Clone)] -pub enum LogServerComponent { - #[serde(rename = "error")] - Error, - #[serde(rename = "ignore")] - Ignore, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct RscClientConfig { - pub log_server_component: LogServerComponent, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DetectCircularDependence { - pub ignores: Vec, - pub graphviz: bool, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct ExperimentalConfig { - pub webpack_syntax_validate: Vec, - pub require_context: bool, - #[serde(deserialize_with = "deserialize_detect_loop")] - pub detect_circular_dependence: Option, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct WatchConfig { - pub ignore_paths: Option>, - #[serde(rename = "_nodeModulesRegexes")] - pub node_modules_regexes: Option>, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct HmrConfig {} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct DevServerConfig { - pub host: String, - pub port: u16, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct Config { - pub entry: HashMap, - pub output: OutputConfig, - pub resolve: ResolveConfig, - #[serde(deserialize_with = "deserialize_manifest", default)] - pub manifest: Option, - pub mode: Mode, - pub minify: bool, - #[serde(deserialize_with = "deserialize_devtool")] - pub devtool: Option, - pub externals: HashMap, - pub providers: Providers, - pub copy: Vec, - pub public_path: String, - pub inline_limit: usize, - pub targets: HashMap, - pub platform: Platform, - pub module_id_strategy: ModuleIdStrategy, - pub define: HashMap, - pub analyze: Option, - pub stats: Option, - pub mdx: bool, - #[serde(deserialize_with = "deserialize_hmr")] - pub hmr: Option, - #[serde(deserialize_with = "deserialize_dev_server")] - pub dev_server: Option, - #[serde(deserialize_with = "deserialize_code_splitting", default)] - pub code_splitting: Option, - #[serde(deserialize_with = "deserialize_px2rem", default)] - pub px2rem: Option, - #[serde(deserialize_with = "deserialize_progress", default)] - pub progress: Option, - pub hash: bool, - #[serde(rename = "_treeShaking", deserialize_with = "deserialize_tree_shaking")] - pub _tree_shaking: Option, - #[serde(rename = "autoCSSModules")] - pub auto_css_modules: bool, - #[serde(rename = "ignoreCSSParserErrors")] - pub ignore_css_parser_errors: bool, - pub dynamic_import_to_require: bool, - #[serde(deserialize_with = "deserialize_umd", default)] - pub umd: Option, - pub cjs: bool, - pub write_to_disk: bool, - pub transform_import: Vec, - pub chunk_parallel: bool, - pub clean: bool, - pub node_polyfill: bool, - pub ignores: Vec, - #[serde( - rename = "_minifish", - deserialize_with = "deserialize_minifish", - default - )] - pub _minifish: Option, - #[serde(rename = "optimizePackageImports")] - pub optimize_package_imports: bool, - pub emotion: bool, - pub flex_bugs: bool, - #[serde(deserialize_with = "deserialize_optimization")] - pub optimization: Option, - pub react: ReactConfig, - pub emit_assets: bool, - #[serde(rename = "cssModulesExportOnlyLocales")] - pub css_modules_export_only_locales: bool, - #[serde( - rename = "inlineCSS", - deserialize_with = "deserialize_inline_css", - default - )] - pub inline_css: Option, - #[serde( - rename = "rscServer", - deserialize_with = "deserialize_rsc_server", - default - )] - pub rsc_server: Option, - #[serde( - rename = "rscClient", - deserialize_with = "deserialize_rsc_client", - default - )] - pub rsc_client: Option, - pub experimental: ExperimentalConfig, - pub watch: WatchConfig, - pub use_define_for_class_fields: bool, - pub emit_decorator_metadata: bool, - #[serde( - rename = "duplicatePackageChecker", - deserialize_with = "deserialize_check_duplicate_package", - default - )] - pub check_duplicate_package: Option, -} - -#[derive(Deserialize, Serialize, Clone, Debug, Default)] -pub enum OptimizeAllowChunks { - #[serde(rename = "all")] - All, - #[serde(rename = "entry")] - Entry, - #[serde(rename = "async")] - #[default] - Async, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(rename_all = "camelCase")] -pub struct CodeSplittingAdvancedOptions { - #[serde(default = "GenericUsizeDefault::<20000>::value")] - pub min_size: usize, - pub groups: Vec, -} - -impl Default for CodeSplittingAdvancedOptions { - fn default() -> Self { - CodeSplittingAdvancedOptions { - min_size: GenericUsizeDefault::<20000>::value(), - groups: vec![], - } - } -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub enum OptimizeChunkNameSuffixStrategy { - #[serde(rename = "packageName")] - PackageName, - #[serde(rename = "dependentsHash")] - DependentsHash, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(rename_all = "camelCase")] -pub struct OptimizeChunkGroup { - pub name: String, - #[serde(default)] - pub name_suffix: Option, - #[serde(default)] - pub allow_chunks: OptimizeAllowChunks, - #[serde(default = "GenericUsizeDefault::<1>::value")] - pub min_chunks: usize, - #[serde(default = "GenericUsizeDefault::<20000>::value")] - pub min_size: usize, - #[serde(default = "GenericUsizeDefault::<5000000>::value")] - pub max_size: usize, - #[serde(default)] - pub min_module_size: Option, - #[serde(default)] - pub priority: i8, - #[serde(default, with = "optimize_test_format")] - pub test: Option, -} - -impl Default for OptimizeChunkGroup { - fn default() -> Self { - Self { - allow_chunks: OptimizeAllowChunks::default(), - min_chunks: GenericUsizeDefault::<1>::value(), - min_size: GenericUsizeDefault::<20000>::value(), - max_size: GenericUsizeDefault::<5000000>::value(), - name: String::default(), - name_suffix: None, - min_module_size: None, - test: None, - priority: i8::default(), - } - } -} - -/** - * custom formatter for convert string to regex - * @see https://serde.rs/custom-date-format.html - */ -mod optimize_test_format { - use regex::Regex; - use serde::{self, Deserialize, Deserializer, Serializer}; - - pub fn serialize(v: &Option, serializer: S) -> Result - where - S: Serializer, - { - if let Some(v) = v { - serializer.serialize_str(&v.to_string()) - } else { - serializer.serialize_none() - } - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - let v = String::deserialize(deserializer)?; - - if v.is_empty() { - Ok(None) - } else { - Ok(Regex::new(v.as_str()).ok()) - } - } -} - -const CONFIG_FILE: &str = "mako.config.json"; -const DEFAULT_CONFIG: &str = r#" -{ - "entry": {}, - "output": { - "path": "dist", - "mode": "bundle", - "esVersion": "es2022", - "meta": false, - "chunkLoadingGlobal": "", - "preserveModules": false, - "preserveModulesRoot": "", - "skipWrite": false, - "crossOriginLoading": false, - "globalModuleRegistry": false, - }, - "resolve": { "alias": [], "extensions": ["js", "jsx", "ts", "tsx"] }, - "mode": "development", - "minify": true, - "devtool": "source-map", - "externals": {}, - "copy": ["public"], - "providers": {}, - "publicPath": "/", - "inlineLimit": 10000, - "targets": { "chrome": 80 }, - "less": { "theme": {}, "lesscPath": "", javascriptEnabled: true }, - "define": {}, - "mdx": false, - "platform": "browser", - "hmr": {}, - "moduleIdStrategy": "named", - "hash": false, - "_treeShaking": "basic", - "autoCSSModules": false, - "ignoreCSSParserErrors": false, - "dynamicImportToRequire": false, - "writeToDisk": true, - "transformImport": [], - "chunkParallel": true, - "clean": true, - "nodePolyfill": true, - "ignores": [], - "optimizePackageImports": false, - "emotion": false, - "flexBugs": false, - "cjs": false, - "optimization": { "skipModules": true, "concatenateModules": true }, - "react": { - "pragma": "React.createElement", - "importSource": "react", - "runtime": "automatic", - "pragmaFrag": "React.Fragment" - }, - "progress": { - "progressChars": "▨▨" - }, - "duplicatePackageChecker": { - "verbose": false, - "showHelp": false, - "emitError": false, - }, - "emitAssets": true, - "cssModulesExportOnlyLocales": false, - "inlineCSS": false, - "rscServer": false, - "rscClient": false, - "experimental": { - "webpackSyntaxValidate": [], - "requireContext": true, - "detectCircularDependence": { "ignores": ["node_modules"], "graphviz": false } - }, - "useDefineForClassFields": true, - "emitDecoratorMetadata": false, - "watch": { "ignorePaths": [], "_nodeModulesRegexes": [] }, - "devServer": { "host": "127.0.0.1", "port": 3000 } -} -"#; - -impl Config { - pub fn new( - root: &Path, - default_config: Option<&str>, - cli_config: Option<&str>, - ) -> Result { - let abs_config_file = root.join(CONFIG_FILE); - let abs_config_file = abs_config_file.to_str().unwrap(); - let c = config::Config::builder(); - // default config - let c = c.add_source(config::File::from_str( - DEFAULT_CONFIG, - config::FileFormat::Json5, - )); - // default config from args - let c = if let Some(default_config) = default_config { - c.add_source(config::File::from_str( - default_config, - config::FileFormat::Json5, - )) - } else { - c - }; - // validate user config - validate_mako_config(abs_config_file.to_string()) - .map_err(|e| anyhow!("{}", format!("{:?}", e)))?; - // user config - let c = c.add_source(config::File::with_name(abs_config_file).required(false)); - // cli config - let c = if let Some(cli_config) = cli_config { - c.add_source(config::File::from_str( - cli_config, - config::FileFormat::Json5, - )) - } else { - c - }; - - let c = c.build()?; - let mut ret = c.try_deserialize::(); - // normalize & check - if let Ok(config) = &mut ret { - // normalize output - if config.output.path.is_relative() { - config.output.path = root.join(config.output.path.to_string_lossy().to_string()); - } - - if config.output.chunk_loading_global.is_empty() { - config.output.chunk_loading_global = - get_default_chunk_loading_global(config.umd.clone(), root); - } - - let node_env_config_opt = config.define.get("NODE_ENV"); - if let Some(node_env_config) = node_env_config_opt { - if node_env_config.as_str() != Some(config.mode.to_string().as_str()) { - let warn_message = format!( - "{}: The configuration of {} conflicts with current {} and will be overwritten as {} ", - "warning".to_string().yellow(), - "NODE_ENV".to_string().yellow(), - "mode".to_string().yellow(), - config.mode.to_string().red() - ); - println!("{}", warn_message); - } - } - - if config.cjs && config.umd.is_some() { - return Err(anyhow!("cjs and umd cannot be used at the same time",)); - } - - if config.hmr.is_some() && config.dev_server.is_none() { - return Err(anyhow!("hmr can only be used with devServer",)); - } - - if config.inline_css.is_some() && config.umd.is_none() { - return Err(anyhow!("inlineCSS can only be used with umd",)); - } - - let mode = format!("\"{}\"", config.mode); - config - .define - .insert("NODE_ENV".to_string(), serde_json::Value::String(mode)); - - if config.public_path != "runtime" && !config.public_path.ends_with('/') { - return Err(anyhow!("public_path must end with '/' or be 'runtime'")); - } - - // 暂不支持 remote external - // 如果 config.externals 中有值是以「script 」开头,则 panic 报错 - let basic_external_values = config - .externals - .values() - .filter_map(|v| match v { - ExternalConfig::Basic(b) => Some(b), - _ => None, - }) - .collect::>(); - for v in basic_external_values { - if v.starts_with("script ") { - return Err(anyhow!( - "remote external is not supported yet, but we found {}", - v.to_string().red() - )); - } - } - - // support default entries - if config.entry.is_empty() { - let file_paths = vec!["src/index.tsx", "src/index.ts", "index.tsx", "index.ts"]; - for file_path in file_paths { - let file_path = root.join(file_path); - if file_path.exists() { - config.entry.insert("index".to_string(), file_path); - break; - } - } - if config.entry.is_empty() { - return Err(anyhow!("Entry is empty")); - } - } - - // normalize entry - let entry_tuples = config - .entry - .clone() - .into_iter() - .map(|(k, v)| { - if let Ok(entry_path) = root.join(v).canonicalize() { - Ok((k, entry_path)) - } else { - Err(anyhow!("entry:{} not found", k,)) - } - }) - .collect::>>()?; - config.entry = entry_tuples.into_iter().collect(); - - // support relative alias - config.resolve.alias = config - .resolve - .alias - .clone() - .into_iter() - .map(|(k, v)| { - let v = if v.starts_with('.') { - root.join(v).to_string_lossy().to_string() - } else { - v - }; - (k, v) - }) - .collect(); - - // dev 环境下不产生 hash, prod 环境下根据用户配置 - if config.mode == Mode::Development { - config.hash = false; - } - - // configure node platform - Node::modify_config(config); - } - ret.map_err(|e| anyhow!("{}: {}", "config error".red(), e.to_string().red())) - } -} - -impl Default for Config { - fn default() -> Self { - let c = config::Config::builder(); - let c = c.add_source(config::File::from_str( - DEFAULT_CONFIG, - config::FileFormat::Json5, - )); - let c = c.build().unwrap(); - c.try_deserialize::().unwrap() - } -} - -pub(crate) fn get_pkg_name(root: &Path) -> Option { - let pkg_json_path = root.join("package.json"); - - if pkg_json_path.exists() { - let pkg_json = std::fs::read_to_string(pkg_json_path).unwrap(); - let pkg_json: serde_json::Value = serde_json::from_str(&pkg_json).unwrap(); - - pkg_json - .get("name") - .map(|name| name.as_str().unwrap().to_string()) - } else { - None - } -} - -fn get_default_chunk_loading_global(umd: Option, root: &Path) -> String { - let unique_name = umd.unwrap_or_else(|| get_pkg_name(root).unwrap_or("global".to_string())); - - format!("makoChunk_{}", unique_name) -} - -#[derive(Error, Debug)] -pub enum ConfigError { - #[error("define value '{0}' is not an Expression")] - InvalidateDefineConfig(String), -} - -pub struct GenericUsizeDefault; - -impl GenericUsizeDefault { - pub fn value() -> usize { - U - } -} - -#[cfg(test)] -mod tests { - use crate::config::config::GenericUsizeDefault; - use crate::config::{Config, Mode, Platform}; - - #[test] - fn test_config() { - let current_dir = std::env::current_dir().unwrap(); - let config = Config::new(¤t_dir.join("test/config/normal"), None, None).unwrap(); - println!("{:?}", config); - assert_eq!(config.platform, Platform::Node); - } - - #[test] - fn test_config_args_default() { - let current_dir = std::env::current_dir().unwrap(); - let config = Config::new( - ¤t_dir.join("test/config/normal"), - Some(r#"{"mode":"production"}"#), - None, - ) - .unwrap(); - println!("{:?}", config); - assert_eq!(config.mode, Mode::Production); - } - - #[test] - fn test_config_cli_args() { - let current_dir = std::env::current_dir().unwrap(); - let config = Config::new( - ¤t_dir.join("test/config/normal"), - None, - Some(r#"{"platform":"browser"}"#), - ) - .unwrap(); - println!("{:?}", config); - assert_eq!(config.platform, Platform::Browser); - } - - #[test] - fn test_node_env_conflicts_with_mode() { - let current_dir = std::env::current_dir().unwrap(); - let config = Config::new( - ¤t_dir.join("test/config/node-env"), - None, - Some(r#"{"mode":"development"}"#), - ) - .unwrap(); - assert_eq!( - config.define.get("NODE_ENV"), - Some(&serde_json::Value::String("\"development\"".to_string())) - ); - } - - #[test] - #[should_panic(expected = "public_path must end with '/' or be 'runtime'")] - fn test_config_invalid_public_path() { - let current_dir = std::env::current_dir().unwrap(); - Config::new( - ¤t_dir.join("test/config/normal"), - None, - Some(r#"{"publicPath":"abc"}"#), - ) - .unwrap(); - } - - #[test] - fn test_node_platform() { - let current_dir = std::env::current_dir().unwrap(); - let config = - Config::new(¤t_dir.join("test/config/node-platform"), None, None).unwrap(); - assert_eq!( - config.targets.get("node"), - Some(&14.0), - "use node targets by default if platform is node", - ); - assert!( - config.ignores.iter().any(|i| i.contains("|fs|")), - "ignore Node.js standard library by default if platform is node", - ); - } - - #[test] - fn test_generic_usize_default() { - assert!(GenericUsizeDefault::<100>::value() == 100usize) - } -} diff --git a/crates/mako/src/config/dev_server.rs b/crates/mako/src/config/dev_server.rs new file mode 100644 index 000000000..928fb7b8b --- /dev/null +++ b/crates/mako/src/config/dev_server.rs @@ -0,0 +1,12 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct DevServerConfig { + pub host: String, + pub port: u16, +} + +create_deserialize_fn!(deserialize_dev_server, DevServerConfig); diff --git a/crates/mako/src/config/devtool.rs b/crates/mako/src/config/devtool.rs new file mode 100644 index 000000000..367d4b307 --- /dev/null +++ b/crates/mako/src/config/devtool.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +pub enum DevtoolConfig { + /// Generate separate sourcemap file + #[serde(rename = "source-map")] + SourceMap, + /// Generate inline sourcemap + #[serde(rename = "inline-source-map")] + InlineSourceMap, +} + +create_deserialize_fn!(deserialize_devtool, DevtoolConfig); diff --git a/crates/mako/src/config/duplicate_package_checker.rs b/crates/mako/src/config/duplicate_package_checker.rs new file mode 100644 index 000000000..14eedc9b3 --- /dev/null +++ b/crates/mako/src/config/duplicate_package_checker.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct DuplicatePackageCheckerConfig { + #[serde(rename = "verbose", default)] + pub verbose: bool, + #[serde(rename = "emitError", default)] + pub emit_error: bool, + #[serde(rename = "showHelp", default)] + pub show_help: bool, +} + +create_deserialize_fn!( + deserialize_check_duplicate_package, + DuplicatePackageCheckerConfig +); diff --git a/crates/mako/src/config/experimental.rs b/crates/mako/src/config/experimental.rs new file mode 100644 index 000000000..a3bee9264 --- /dev/null +++ b/crates/mako/src/config/experimental.rs @@ -0,0 +1,21 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ExperimentalConfig { + pub webpack_syntax_validate: Vec, + pub require_context: bool, + #[serde(deserialize_with = "deserialize_detect_loop")] + pub detect_circular_dependence: Option, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct DetectCircularDependence { + pub ignores: Vec, + pub graphviz: bool, +} + +create_deserialize_fn!(deserialize_detect_loop, DetectCircularDependence); diff --git a/crates/mako/src/config/external.rs b/crates/mako/src/config/external.rs new file mode 100644 index 000000000..922be0616 --- /dev/null +++ b/crates/mako/src/config/external.rs @@ -0,0 +1,77 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug, Hash)] +#[serde(untagged)] +pub enum ExternalConfig { + Basic(String), + Advanced(ExternalAdvanced), +} + +#[derive(Deserialize, Serialize, Debug, Hash)] +pub struct ExternalAdvancedSubpath { + pub exclude: Option>, + pub rules: Vec, +} + +#[derive(Deserialize, Serialize, Debug, Hash)] +pub struct ExternalAdvanced { + pub root: String, + #[serde(rename = "type")] + pub module_type: Option, + pub script: Option, + pub subpath: Option, +} + +#[derive(Deserialize, Serialize, Debug, Hash)] +pub struct ExternalAdvancedSubpathRule { + pub regex: String, + #[serde(with = "external_target_format")] + pub target: ExternalAdvancedSubpathTarget, + #[serde(rename = "targetConverter")] + pub target_converter: Option, +} + +#[derive(Deserialize, Serialize, Debug, Hash)] +pub enum ExternalAdvancedSubpathConverter { + PascalCase, +} + +#[derive(Deserialize, Serialize, Debug, Hash)] +#[serde(untagged)] +pub enum ExternalAdvancedSubpathTarget { + Empty, + Tpl(String), +} + +/** + * custom formatter for convert $EMPTY to enum, because rename is not supported for $ symbol + * @see https://serde.rs/custom-date-format.html + */ +mod external_target_format { + use serde::{self, Deserialize, Deserializer, Serializer}; + + use super::ExternalAdvancedSubpathTarget; + + pub fn serialize(v: &ExternalAdvancedSubpathTarget, serializer: S) -> Result + where + S: Serializer, + { + match v { + ExternalAdvancedSubpathTarget::Empty => serializer.serialize_str("$EMPTY"), + ExternalAdvancedSubpathTarget::Tpl(s) => serializer.serialize_str(s), + } + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let v = String::deserialize(deserializer)?; + + if v == "$EMPTY" { + Ok(ExternalAdvancedSubpathTarget::Empty) + } else { + Ok(ExternalAdvancedSubpathTarget::Tpl(v)) + } + } +} diff --git a/crates/mako/src/config/generic_usize.rs b/crates/mako/src/config/generic_usize.rs new file mode 100644 index 000000000..8aa1074d7 --- /dev/null +++ b/crates/mako/src/config/generic_usize.rs @@ -0,0 +1,17 @@ +pub struct GenericUsizeDefault; + +impl GenericUsizeDefault { + pub fn value() -> usize { + U + } +} + +#[cfg(test)] +mod tests { + use crate::config::GenericUsizeDefault; + + #[test] + fn test_generic_usize_default() { + assert!(GenericUsizeDefault::<100>::value() == 100usize) + } +} diff --git a/crates/mako/src/config/hmr.rs b/crates/mako/src/config/hmr.rs new file mode 100644 index 000000000..005be10ee --- /dev/null +++ b/crates/mako/src/config/hmr.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct HmrConfig {} + +create_deserialize_fn!(deserialize_hmr, HmrConfig); diff --git a/crates/mako/src/config/inline_css.rs b/crates/mako/src/config/inline_css.rs new file mode 100644 index 000000000..af3c4ec94 --- /dev/null +++ b/crates/mako/src/config/inline_css.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +pub struct InlineCssConfig {} + +create_deserialize_fn!(deserialize_inline_css, InlineCssConfig); diff --git a/crates/mako/src/config/macros.rs b/crates/mako/src/config/macros.rs new file mode 100644 index 000000000..4acdd112a --- /dev/null +++ b/crates/mako/src/config/macros.rs @@ -0,0 +1,33 @@ +/** + * a macro to create deserialize function that allow false value for optional struct + */ +#[macro_export] +macro_rules! create_deserialize_fn { + ($fn_name:ident, $struct_type:ty) => { + pub fn $fn_name<'de, D>(deserializer: D) -> Result, D::Error> + where + D: serde::Deserializer<'de>, + { + let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?; + + match value { + // allow false value for optional struct + serde_json::Value::Bool(false) => Ok(None), + // try deserialize + serde_json::Value::Object(obj) => Ok(Some( + serde_json::from_value::<$struct_type>(serde_json::Value::Object(obj)) + .map_err(serde::de::Error::custom)?, + )), + serde_json::Value::String(s) => Ok(Some( + serde_json::from_value::<$struct_type>(serde_json::Value::String(s.clone())) + .map_err(serde::de::Error::custom)?, + )), + _ => Err(serde::de::Error::custom(format!( + "invalid `{}` value: {}", + stringify!($fn_name).replace("deserialize_", ""), + value + ))), + } + } + }; +} diff --git a/crates/mako/src/config/mako.config.default.json b/crates/mako/src/config/mako.config.default.json new file mode 100644 index 000000000..bfbce56dd --- /dev/null +++ b/crates/mako/src/config/mako.config.default.json @@ -0,0 +1,79 @@ +{ + "entry": {}, + "output": { + "path": "dist", + "mode": "bundle", + "esVersion": "es2022", + "meta": false, + "chunkLoadingGlobal": "", + "preserveModules": false, + "preserveModulesRoot": "", + "skipWrite": false, + "crossOriginLoading": false, + "globalModuleRegistry": false + }, + "resolve": { "alias": [], "extensions": ["js", "jsx", "ts", "tsx"] }, + "mode": "development", + "minify": true, + "devtool": "source-map", + "externals": {}, + "copy": ["public"], + "providers": {}, + "publicPath": "/", + "inlineLimit": 10000, + "inlineExcludesExtensions": [], + "targets": { "chrome": 80 }, + "less": { "theme": {}, "lesscPath": "", "javascriptEnabled": true }, + "define": {}, + "mdx": false, + "platform": "browser", + "hmr": {}, + "moduleIdStrategy": "named", + "hash": false, + "_treeShaking": "basic", + "autoCSSModules": false, + "ignoreCSSParserErrors": false, + "dynamicImportToRequire": false, + "writeToDisk": true, + "transformImport": [], + "chunkParallel": true, + "clean": true, + "nodePolyfill": true, + "ignores": [], + "optimizePackageImports": false, + "emotion": false, + "flexBugs": false, + "cjs": false, + "optimization": { "skipModules": true, "concatenateModules": true }, + "react": { + "pragma": "React.createElement", + "importSource": "react", + "runtime": "automatic", + "pragmaFrag": "React.Fragment" + }, + "progress": { + "progressChars": "▨▨" + }, + "duplicatePackageChecker": { + "verbose": false, + "showHelp": false, + "emitError": false + }, + "emitAssets": true, + "cssModulesExportOnlyLocales": false, + "inlineCSS": false, + "rscServer": false, + "rscClient": false, + "experimental": { + "webpackSyntaxValidate": [], + "requireContext": true, + "detectCircularDependence": { + "ignores": ["node_modules"], + "graphviz": false + } + }, + "useDefineForClassFields": true, + "emitDecoratorMetadata": false, + "watch": { "ignorePaths": [], "_nodeModulesRegexes": [] }, + "devServer": { "host": "127.0.0.1", "port": 3000 } +} diff --git a/crates/mako/src/config/manifest.rs b/crates/mako/src/config/manifest.rs new file mode 100644 index 000000000..5581b8ee7 --- /dev/null +++ b/crates/mako/src/config/manifest.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +use crate::{create_deserialize_fn, plugins}; + +#[derive(Deserialize, Serialize, Debug)] +pub struct ManifestConfig { + #[serde( + rename(deserialize = "fileName"), + default = "plugins::manifest::default_manifest_file_name" + )] + pub file_name: String, + #[serde(rename(deserialize = "basePath"), default)] + pub base_path: String, +} + +create_deserialize_fn!(deserialize_manifest, ManifestConfig); diff --git a/crates/mako/src/config/minifish.rs b/crates/mako/src/config/minifish.rs new file mode 100644 index 000000000..7e25adbe1 --- /dev/null +++ b/crates/mako/src/config/minifish.rs @@ -0,0 +1,27 @@ +use std::collections::HashMap; +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct MinifishConfig { + pub mapping: HashMap, + pub meta_path: Option, + pub inject: Option>, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct InjectItem { + pub from: String, + pub named: Option, + pub namespace: Option, + pub exclude: Option, + pub include: Option, + pub prefer_require: Option, +} + +create_deserialize_fn!(deserialize_minifish, MinifishConfig); diff --git a/crates/mako/src/config/mode.rs b/crates/mako/src/config/mode.rs new file mode 100644 index 000000000..bf18c8d3c --- /dev/null +++ b/crates/mako/src/config/mode.rs @@ -0,0 +1,16 @@ +use clap::ValueEnum; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ValueEnum, Clone)] +pub enum Mode { + #[serde(rename = "development")] + Development, + #[serde(rename = "production")] + Production, +} + +impl std::fmt::Display for Mode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_possible_value().unwrap().get_name().fmt(f) + } +} diff --git a/crates/mako/src/config/module_id_strategy.rs b/crates/mako/src/config/module_id_strategy.rs new file mode 100644 index 000000000..801c8afb8 --- /dev/null +++ b/crates/mako/src/config/module_id_strategy.rs @@ -0,0 +1,11 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Clone, Copy, Debug)] +pub enum ModuleIdStrategy { + #[serde(rename = "hashed")] + Hashed, + #[serde(rename = "named")] + Named, + #[serde(rename = "numeric")] + Numeric, +} diff --git a/crates/mako/src/config/optimization.rs b/crates/mako/src/config/optimization.rs new file mode 100644 index 000000000..8e57ca69e --- /dev/null +++ b/crates/mako/src/config/optimization.rs @@ -0,0 +1,12 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct OptimizationConfig { + pub skip_modules: Option, + pub concatenate_modules: Option, +} + +create_deserialize_fn!(deserialize_optimization, OptimizationConfig); diff --git a/crates/mako/src/config/output.rs b/crates/mako/src/config/output.rs new file mode 100644 index 000000000..da3edb041 --- /dev/null +++ b/crates/mako/src/config/output.rs @@ -0,0 +1,58 @@ +use core::fmt; +use std::path::{Path, PathBuf}; + +use clap::ValueEnum; +use serde::{Deserialize, Serialize}; +use swc_core::ecma::ast::EsVersion; + +use crate::create_deserialize_fn; +use crate::utils::get_pkg_name; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct OutputConfig { + pub path: PathBuf, + pub mode: OutputMode, + pub es_version: EsVersion, + pub meta: bool, + pub chunk_loading_global: String, + pub preserve_modules: bool, + pub preserve_modules_root: PathBuf, + pub skip_write: bool, + #[serde(deserialize_with = "deserialize_cross_origin_loading")] + pub cross_origin_loading: Option, + pub global_module_registry: bool, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ValueEnum, Clone)] +pub enum OutputMode { + #[serde(rename = "bundle")] + Bundle, + #[serde(rename = "bundless")] + Bundless, +} + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub enum CrossOriginLoading { + #[serde(rename = "anonymous")] + Anonymous, + #[serde(rename = "use-credentials")] + UseCredentials, +} + +impl fmt::Display for CrossOriginLoading { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CrossOriginLoading::Anonymous => write!(f, "anonymous"), + CrossOriginLoading::UseCredentials => write!(f, "use-credentials"), + } + } +} + +pub fn get_default_chunk_loading_global(umd: Option, root: &Path) -> String { + let unique_name = umd.unwrap_or_else(|| get_pkg_name(root).unwrap_or("global".to_string())); + + format!("makoChunk_{}", unique_name) +} + +create_deserialize_fn!(deserialize_cross_origin_loading, CrossOriginLoading); diff --git a/crates/mako/src/config/progress.rs b/crates/mako/src/config/progress.rs new file mode 100644 index 000000000..37588b740 --- /dev/null +++ b/crates/mako/src/config/progress.rs @@ -0,0 +1,11 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct ProgressConfig { + #[serde(rename = "progressChars", default)] + pub progress_chars: String, +} + +create_deserialize_fn!(deserialize_progress, ProgressConfig); diff --git a/crates/mako/src/config/provider.rs b/crates/mako/src/config/provider.rs new file mode 100644 index 000000000..21f35463f --- /dev/null +++ b/crates/mako/src/config/provider.rs @@ -0,0 +1,7 @@ +use std::collections::HashMap; + +// format: HashMap +// e.g. +// { "process": ("process", "") } +// { "Buffer": ("buffer", "Buffer") } +pub type Providers = HashMap; diff --git a/crates/mako/src/config/px2rem.rs b/crates/mako/src/config/px2rem.rs new file mode 100644 index 000000000..3e3437710 --- /dev/null +++ b/crates/mako/src/config/px2rem.rs @@ -0,0 +1,40 @@ +use serde::{Deserialize, Serialize}; + +use crate::{create_deserialize_fn, visitors}; + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct Px2RemConfig { + #[serde(default = "visitors::css_px2rem::default_root")] + pub root: f64, + #[serde(rename = "propBlackList", default)] + pub prop_blacklist: Vec, + #[serde(rename = "propWhiteList", default)] + pub prop_whitelist: Vec, + #[serde(rename = "selectorBlackList", default)] + pub selector_blacklist: Vec, + #[serde(rename = "selectorWhiteList", default)] + pub selector_whitelist: Vec, + #[serde(rename = "selectorDoubleList", default)] + pub selector_doublelist: Vec, + #[serde(rename = "minPixelValue", default)] + pub min_pixel_value: f64, + #[serde(rename = "mediaQuery", default)] + pub media_query: bool, +} + +impl Default for Px2RemConfig { + fn default() -> Self { + Px2RemConfig { + root: visitors::css_px2rem::default_root(), + prop_blacklist: vec![], + prop_whitelist: vec![], + selector_blacklist: vec![], + selector_whitelist: vec![], + selector_doublelist: vec![], + min_pixel_value: 0.0, + media_query: false, + } + } +} + +create_deserialize_fn!(deserialize_px2rem, Px2RemConfig); diff --git a/crates/mako/src/config/react.rs b/crates/mako/src/config/react.rs new file mode 100644 index 000000000..38cfa12c7 --- /dev/null +++ b/crates/mako/src/config/react.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug)] +pub struct ReactConfig { + pub pragma: String, + #[serde(rename = "importSource")] + pub import_source: String, + pub runtime: ReactRuntimeConfig, + #[serde(rename = "pragmaFrag")] + pub pragma_frag: String, +} + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub enum ReactRuntimeConfig { + #[serde(rename = "automatic")] + Automatic, + #[serde(rename = "classic")] + Classic, +} diff --git a/crates/mako/src/config/resolve.rs b/crates/mako/src/config/resolve.rs new file mode 100644 index 000000000..dbe1b5029 --- /dev/null +++ b/crates/mako/src/config/resolve.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug)] +pub struct ResolveConfig { + pub alias: Vec<(String, String)>, + pub extensions: Vec, +} diff --git a/crates/mako/src/config/rsc_client.rs b/crates/mako/src/config/rsc_client.rs new file mode 100644 index 000000000..e3517c446 --- /dev/null +++ b/crates/mako/src/config/rsc_client.rs @@ -0,0 +1,20 @@ +use clap::ValueEnum; +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RscClientConfig { + pub log_server_component: LogServerComponent, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, ValueEnum, Clone)] +pub enum LogServerComponent { + #[serde(rename = "error")] + Error, + #[serde(rename = "ignore")] + Ignore, +} + +create_deserialize_fn!(deserialize_rsc_client, RscClientConfig); diff --git a/crates/mako/src/config/rsc_server.rs b/crates/mako/src/config/rsc_server.rs new file mode 100644 index 000000000..980216bde --- /dev/null +++ b/crates/mako/src/config/rsc_server.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RscServerConfig { + pub client_component_tpl: String, + #[serde(rename = "emitCSS")] + pub emit_css: bool, +} + +create_deserialize_fn!(deserialize_rsc_server, RscServerConfig); diff --git a/crates/mako/src/config/stats.rs b/crates/mako/src/config/stats.rs new file mode 100644 index 000000000..9a3dcc04e --- /dev/null +++ b/crates/mako/src/config/stats.rs @@ -0,0 +1,10 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct StatsConfig { + pub modules: bool, +} + +create_deserialize_fn!(deserialize_stats, StatsConfig); diff --git a/crates/mako/src/config/transform_import.rs b/crates/mako/src/config/transform_import.rs new file mode 100644 index 000000000..91384f621 --- /dev/null +++ b/crates/mako/src/config/transform_import.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(untagged)] +pub enum TransformImportStyle { + Built(String), + Source(bool), +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TransformImportConfig { + pub library_name: String, + pub library_directory: Option, + pub style: Option, +} diff --git a/crates/mako/src/config/tree_shaking.rs b/crates/mako/src/config/tree_shaking.rs new file mode 100644 index 000000000..e716201fa --- /dev/null +++ b/crates/mako/src/config/tree_shaking.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; + +use crate::create_deserialize_fn; + +#[derive(Deserialize, Serialize, Clone, Copy, Debug)] +pub enum TreeShakingStrategy { + #[serde(rename = "basic")] + Basic, + #[serde(rename = "advanced")] + Advanced, +} + +create_deserialize_fn!(deserialize_tree_shaking, TreeShakingStrategy); diff --git a/crates/mako/src/config/umd.rs b/crates/mako/src/config/umd.rs new file mode 100644 index 000000000..634c2c41a --- /dev/null +++ b/crates/mako/src/config/umd.rs @@ -0,0 +1,7 @@ +use serde::Deserialize; + +use crate::create_deserialize_fn; + +pub type Umd = String; + +create_deserialize_fn!(deserialize_umd, Umd); diff --git a/crates/mako/src/config/watch.rs b/crates/mako/src/config/watch.rs new file mode 100644 index 000000000..3587c5024 --- /dev/null +++ b/crates/mako/src/config/watch.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct WatchConfig { + pub ignore_paths: Option>, + #[serde(rename = "_nodeModulesRegexes")] + pub node_modules_regexes: Option>, +} diff --git a/crates/mako/src/features/node.rs b/crates/mako/src/features/node.rs index 3a6cd09a7..50356e822 100644 --- a/crates/mako/src/features/node.rs +++ b/crates/mako/src/features/node.rs @@ -139,10 +139,10 @@ pub struct MockFilenameAndDirname { impl VisitMut for MockFilenameAndDirname { fn visit_mut_expr(&mut self, expr: &mut Expr) { if let Expr::Ident(ident) = expr - && ident.span.ctxt.outer() == self.unresolved_mark + && ident.ctxt.outer() == self.unresolved_mark { - let is_filename = ident.sym.to_string() == "__filename"; - let is_dirname = ident.sym.to_string() == "__dirname"; + let is_filename = ident.sym == "__filename"; + let is_dirname = ident.sym == "__dirname"; if is_filename || is_dirname { let path = diff_paths(&self.current_path, &self.context.root).unwrap_or("".into()); let value = if is_filename { diff --git a/crates/mako/src/generate.rs b/crates/mako/src/generate.rs index c8a2ddc57..d3c454892 100644 --- a/crates/mako/src/generate.rs +++ b/crates/mako/src/generate.rs @@ -34,14 +34,6 @@ use crate::stats::StatsJsonMap; use crate::utils::base64_encode; use crate::visitors::async_module::mark_async; -#[derive(Clone)] -pub struct EmitFile { - pub filename: String, - pub content: String, - pub chunk_id: String, - pub hashname: String, -} - #[derive(Serialize)] struct ChunksUrlMap { js: HashMap, diff --git a/crates/mako/src/generate/chunk_pot.rs b/crates/mako/src/generate/chunk_pot.rs index c66602ef0..be774290c 100644 --- a/crates/mako/src/generate/chunk_pot.rs +++ b/crates/mako/src/generate/chunk_pot.rs @@ -12,7 +12,7 @@ use swc_core::css::ast::Stylesheet; use crate::compiler::Context; use crate::config::Mode; -use crate::generate::chunk::{Chunk, ChunkType}; +use crate::generate::chunk::Chunk; pub use crate::generate::chunk_pot::util::CHUNK_FILE_NAME_HASH_LENGTH; use crate::generate::chunk_pot::util::{hash_hashmap, hash_vec}; use crate::generate::generate_chunks::ChunkFile; @@ -22,7 +22,6 @@ use crate::ternary; pub struct ChunkPot<'a> { pub chunk_id: String, - pub chunk_type: ChunkType, pub js_name: String, pub module_map: HashMap, pub js_hash: u64, @@ -39,7 +38,6 @@ impl<'cp> ChunkPot<'cp> { ChunkPot { js_name: chunk.filename(), - chunk_type: chunk.chunk_type.clone(), chunk_id: chunk.id.id.clone(), module_map: js_modules.module_map, js_hash: js_modules.raw_hash, diff --git a/crates/mako/src/generate/chunk_pot/ast_impl.rs b/crates/mako/src/generate/chunk_pot/ast_impl.rs index 44372edce..390261905 100644 --- a/crates/mako/src/generate/chunk_pot/ast_impl.rs +++ b/crates/mako/src/generate/chunk_pot/ast_impl.rs @@ -395,7 +395,9 @@ fn wrap_in_iife(module: SwcModule) -> SwcModule { params: vec![], decorators: vec![], span: DUMMY_SP, + ctxt: Default::default(), body: Some(BlockStmt { + ctxt: Default::default(), span: DUMMY_SP, stmts, }), diff --git a/crates/mako/src/generate/chunk_pot/str_impl.rs b/crates/mako/src/generate/chunk_pot/str_impl.rs index c51a666cb..906759e62 100644 --- a/crates/mako/src/generate/chunk_pot/str_impl.rs +++ b/crates/mako/src/generate/chunk_pot/str_impl.rs @@ -221,11 +221,7 @@ fn pot_to_chunk_module_object_string( chunk_prefix_offset: u32, ) -> Result<(String, RawSourceMap)> { let sorted_kv = { - let mut sorted_kv = pot - .module_map - .iter() - .map(|(k, v)| (k, v)) - .collect::>(); + let mut sorted_kv = pot.module_map.iter().collect::>(); sorted_kv.sort_by_key(|(k, _)| *k); diff --git a/crates/mako/src/generate/chunk_pot/util.rs b/crates/mako/src/generate/chunk_pot/util.rs index 3fcb320df..b0c0966d2 100644 --- a/crates/mako/src/generate/chunk_pot/util.rs +++ b/crates/mako/src/generate/chunk_pot/util.rs @@ -10,7 +10,7 @@ use swc_core::common::comments::{Comment, CommentKind, Comments}; use swc_core::common::errors::HANDLER; use swc_core::common::{Span, DUMMY_SP, GLOBALS}; use swc_core::ecma::ast::{ - ArrayLit, AssignOp, BinaryOp, BlockStmt, CondExpr, Expr, ExprOrSpread, FnExpr, Function, Ident, + ArrayLit, AssignOp, BinaryOp, BlockStmt, CondExpr, Expr, ExprOrSpread, FnExpr, Function, KeyValueProp, Module as SwcModule, ObjectLit, Prop, PropOrSpread, UnaryExpr, UnaryOp, }; use swc_core::ecma::atoms::js_word; @@ -21,10 +21,11 @@ use twox_hash::XxHash64; use crate::ast::sourcemap::build_source_map_to_buf; use crate::compiler::Context; -use crate::config::{get_pkg_name, Mode}; +use crate::config::Mode; use crate::generate::chunk_pot::ChunkPot; use crate::generate::runtime::AppRuntimeTemplate; use crate::module::{relative_to_root, Module, ModuleAst}; +use crate::utils::get_pkg_name; pub(crate) fn render_module_js( ast: &SwcModule, @@ -70,6 +71,7 @@ pub(crate) fn render_module_js( pub(crate) fn empty_module_fn_expr() -> FnExpr { let func = Function { span: DUMMY_SP, + ctxt: Default::default(), params: vec![ quote_ident!("module").into(), quote_ident!("exports").into(), @@ -77,6 +79,7 @@ pub(crate) fn empty_module_fn_expr() -> FnExpr { ], decorators: vec![], body: Some(BlockStmt { + ctxt: Default::default(), span: DUMMY_SP, stmts: vec![], }), @@ -131,7 +134,7 @@ where K: Hash + Eq + Ord, V: Hash, { - let mut sorted_kv = map.iter().map(|(k, v)| (k, v)).collect::>(); + let mut sorted_kv = map.iter().collect::>(); sorted_kv.sort_by_key(|(k, _)| *k); let mut hasher: XxHash64 = Default::default(); @@ -164,11 +167,7 @@ pub(super) fn to_array_lit(elems: Vec) -> ArrayLit { pub(crate) fn pot_to_module_object(pot: &ChunkPot, context: &Arc) -> Result { crate::mako_profile_function!(); - let mut sorted_kv = pot - .module_map - .iter() - .map(|(k, v)| (k, v)) - .collect::>(); + let mut sorted_kv = pot.module_map.iter().collect::>(); sorted_kv.sort_by_key(|(k, _)| *k); let mut props = Vec::new(); @@ -248,9 +247,9 @@ pub(crate) fn pot_to_chunk_module( } .into(), ) - .make_assign_to(AssignOp::Assign, chunk_global_expr.clone().as_pat_or_expr()) + .make_assign_to(AssignOp::Assign, chunk_global_expr.clone().into()) .wrap_with_paren() - .make_member::(quote_ident!("push")); + .make_member(quote_ident!("push")); let chunk_register_stmt = chunk_global_obj .as_call( DUMMY_SP, @@ -301,6 +300,7 @@ fn to_module_fn_expr(module: &Module) -> Result { let func = Function { span: DUMMY_SP, + ctxt: Default::default(), params: vec![ quote_ident!("module").into(), quote_ident!("exports").into(), @@ -309,6 +309,7 @@ fn to_module_fn_expr(module: &Module) -> Result { decorators: vec![], body: Some(BlockStmt { span: DUMMY_SP, + ctxt: Default::default(), stmts, }), is_generator: false, diff --git a/crates/mako/src/generate/generate_chunks.rs b/crates/mako/src/generate/generate_chunks.rs index 68fe12e3e..e14946990 100644 --- a/crates/mako/src/generate/generate_chunks.rs +++ b/crates/mako/src/generate/generate_chunks.rs @@ -40,24 +40,7 @@ pub struct ChunkFile { impl ChunkFile { pub fn disk_name(&self) -> String { - // fixed os error 63 file name too long, reserve 48 bytes for _js-async、extension、.map and others - let reserve_file_name_length = 207; - let file_path = Path::new(&self.file_name); - let mut format_file_name = self.file_name.clone(); - if self.file_name.len() > reserve_file_name_length { - let mut hasher: XxHash64 = Default::default(); - hasher.write_str(self.file_name.as_str()); - let file_extension = file_path.extension().unwrap(); - let file_stem = file_path.file_stem().unwrap().to_string_lossy().to_string(); - let (_, reserve_file_path) = - file_stem.split_at(file_stem.len() - reserve_file_name_length); - format_file_name = format!( - "{}.{}.{}", - reserve_file_path, - &hasher.finish().to_string()[0..8], - file_extension.to_str().unwrap() - ); - } + let format_file_name = hash_too_long_file_name(&self.file_name); if let Some(hash) = &self.hash { hash_file_name(&format_file_name, hash) @@ -191,7 +174,7 @@ impl Compiler { hash_file_name(&js_filename, &placeholder), ); } else { - let js_filename = chunk_pot.js_name; + let js_filename = hash_too_long_file_name(&chunk_pot.js_name); if chunk_pot.stylesheet.is_some() { let css_filename = get_css_chunk_filename(&js_filename); @@ -408,3 +391,26 @@ fn hash_file_name(file_name: &String, hash: &String) -> String { format!("{}.{}.{}", file_stem, hash, file_extension) } + +fn hash_too_long_file_name(file_name: &String) -> String { + // fixed os error 63 file name too long, reserve 48 bytes for _js-async、extension、.map and others + let reserve_file_name_length = 207; + let file_path = Path::new(&file_name); + + let mut format_file_name = file_name.to_string(); + let file_stem = file_path.file_stem().unwrap().to_string_lossy().to_string(); + if file_stem.len() > reserve_file_name_length { + let mut hasher: XxHash64 = Default::default(); + hasher.write_str(file_name.as_str()); + let file_extension = file_path.extension().unwrap(); + let (_, reserve_file_path) = file_stem.split_at(file_stem.len() - reserve_file_name_length); + format_file_name = format!( + "{}.{}.{}", + reserve_file_path, + &hasher.finish().to_string()[0..8], + file_extension.to_str().unwrap() + ); + } + + format_file_name.to_string() +} diff --git a/crates/mako/src/generate/minify.rs b/crates/mako/src/generate/minify.rs index 8b9feff36..7e155d32d 100644 --- a/crates/mako/src/generate/minify.rs +++ b/crates/mako/src/generate/minify.rs @@ -8,7 +8,7 @@ use swc_core::css::ast::Stylesheet; use swc_core::css::minifier; use swc_core::ecma::minifier::optimize; use swc_core::ecma::minifier::option::{ExtraOptions, MinifyOptions}; -use swc_core::ecma::transforms::base::fixer::fixer; +use swc_core::ecma::transforms::base::fixer::{fixer, paren_remover}; use swc_core::ecma::transforms::base::helpers::{Helpers, HELPERS}; use swc_core::ecma::transforms::base::resolver; use swc_core::ecma::visit::VisitMutWith; @@ -28,24 +28,21 @@ pub fn minify_js(ast: &mut JsAst, context: &Arc) -> Result<()> { let unresolved_mark = ast.unresolved_mark; let top_level_mark = ast.top_level_mark; + let comments_lock = context.meta.script.origin_comments.read().unwrap(); + + let comments = comments_lock.get_swc_comments(); + ast.ast.visit_mut_with(&mut resolver( unresolved_mark, top_level_mark, false, )); + ast.ast.visit_mut_with(&mut paren_remover(Some(comments))); let mut minified = optimize( ast.ast.clone().into(), context.meta.script.cm.clone(), - Some( - context - .meta - .script - .origin_comments - .read() - .unwrap() - .get_swc_comments(), - ), + Some(comments), None, &MinifyOptions { compress: Some(Default::default()), @@ -59,15 +56,7 @@ pub fn minify_js(ast: &mut JsAst, context: &Arc) -> Result<()> { ) .expect_module(); - minified.visit_mut_with(&mut fixer(Some( - context - .meta - .script - .origin_comments - .read() - .unwrap() - .get_swc_comments(), - ))); + minified.visit_mut_with(&mut fixer(Some(comments))); ast.ast = minified; Ok(()) diff --git a/crates/mako/src/generate/optimize_chunk.rs b/crates/mako/src/generate/optimize_chunk.rs index 72d6ff928..c5d0b2db9 100644 --- a/crates/mako/src/generate/optimize_chunk.rs +++ b/crates/mako/src/generate/optimize_chunk.rs @@ -3,23 +3,22 @@ use std::string::String; use hashlink::LinkedHashSet; use indexmap::{IndexMap, IndexSet}; -use regex::Regex; use tracing::debug; use crate::compiler::Compiler; use crate::config::{ - CodeSplitting, CodeSplittingAdvancedOptions, CodeSplittingGranularOptions, - CodeSplittingStrategy, CodeSplittingStrategyOptions, GenericUsizeDefault, OptimizeAllowChunks, - OptimizeChunkGroup, OptimizeChunkNameSuffixStrategy, + AllowChunks, ChunkGroup, ChunkNameSuffixStrategy, CodeSplitting, CodeSplittingAdvancedOptions, + CodeSplittingGranularOptions, CodeSplittingStrategy, CodeSplittingStrategyOptions, + GenericUsizeDefault, }; use crate::generate::chunk::{Chunk, ChunkId, ChunkType}; use crate::generate::group_chunk::GroupUpdateResult; use crate::module::{Module, ModuleId, ModuleInfo}; use crate::resolve::{ResolvedResource, ResolverResource}; -use crate::utils::url_safe_base64_encode; +use crate::utils::{create_cached_regex, url_safe_base64_encode}; pub struct OptimizeChunksInfo { - pub group_options: OptimizeChunkGroup, + pub group_options: ChunkGroup, pub module_to_chunks: IndexMap>, } @@ -171,7 +170,7 @@ impl Compiler { // check test regex if let Some(test) = &optimize_info.group_options.test { - if !test.is_match(&module_id.id) { + if !create_cached_regex(test).is_match(&module_id.id) { continue; } } @@ -330,7 +329,7 @@ impl Compiler { for info in &mut *optimize_chunks_infos { if let Some(name_suffix) = &info.group_options.name_suffix { match name_suffix { - OptimizeChunkNameSuffixStrategy::PackageName => { + ChunkNameSuffixStrategy::PackageName => { let mut module_to_package_map: HashMap> = HashMap::new(); info.module_to_chunks.keys().for_each(|module_id| { @@ -367,7 +366,7 @@ impl Compiler { }) }); } - OptimizeChunkNameSuffixStrategy::DependentsHash => { + ChunkNameSuffixStrategy::DependentsHash => { let mut module_to_dependents_md5_map: HashMap> = HashMap::new(); info.module_to_chunks @@ -426,12 +425,11 @@ impl Compiler { let info_chunk_id = ChunkId { id: info.group_options.name.clone(), }; - let info_chunk_type = - if matches!(info.group_options.allow_chunks, OptimizeAllowChunks::Async) { - ChunkType::Sync - } else { - ChunkType::Entry(info_chunk_id.clone(), info.group_options.name.clone(), true) - }; + let info_chunk_type = if matches!(info.group_options.allow_chunks, AllowChunks::Async) { + ChunkType::Sync + } else { + ChunkType::Entry(info_chunk_id.clone(), info.group_options.name.clone(), true) + }; let info_chunk = Chunk { modules: info .module_to_chunks @@ -513,18 +511,14 @@ impl Compiler { /* the following is util methods */ - fn check_chunk_type_allow( - &self, - allow_chunks: &OptimizeAllowChunks, - chunk_type: &ChunkType, - ) -> bool { + fn check_chunk_type_allow(&self, allow_chunks: &AllowChunks, chunk_type: &ChunkType) -> bool { match allow_chunks { - OptimizeAllowChunks::All => matches!( + AllowChunks::All => matches!( chunk_type, &ChunkType::Entry(_, _, false) | &ChunkType::Async ), - OptimizeAllowChunks::Entry => matches!(chunk_type, &ChunkType::Entry(_, _, false)), - OptimizeAllowChunks::Async => chunk_type == &ChunkType::Async, + AllowChunks::Entry => matches!(chunk_type, &ChunkType::Entry(_, _, false)), + AllowChunks::Async => chunk_type == &ChunkType::Async, } } @@ -594,13 +588,13 @@ impl Compiler { fn code_splitting_strategy_auto() -> CodeSplittingAdvancedOptions { CodeSplittingAdvancedOptions { groups: vec![ - OptimizeChunkGroup { + ChunkGroup { name: "vendors".to_string(), - test: Regex::new(r"[/\\]node_modules[/\\]").ok(), + test: Some(r"[/\\]node_modules[/\\]".to_string()), priority: -10, ..Default::default() }, - OptimizeChunkGroup { + ChunkGroup { name: "common".to_string(), min_chunks: 2, // always split, to avoid multi-instance risk @@ -619,34 +613,36 @@ fn code_splitting_strategy_granular( ) -> CodeSplittingAdvancedOptions { CodeSplittingAdvancedOptions { groups: vec![ - OptimizeChunkGroup { + ChunkGroup { name: "framework".to_string(), - allow_chunks: OptimizeAllowChunks::All, + allow_chunks: AllowChunks::All, test: if framework_packages.is_empty() { - Regex::new("^$").ok() + Some("^$".to_string()) } else { - Regex::new(&format!( - r#"[/\\]node_modules[/\\].*({})[/\\]"#, - framework_packages.join("|") - )) - .ok() + Some( + format!( + r#"[/\\]node_modules[/\\].*({})[/\\]"#, + framework_packages.join("|") + ) + .to_string(), + ) }, priority: -10, ..Default::default() }, - OptimizeChunkGroup { + ChunkGroup { name: "lib".to_string(), - name_suffix: Some(OptimizeChunkNameSuffixStrategy::PackageName), - allow_chunks: OptimizeAllowChunks::Async, - test: Regex::new(r"[/\\]node_modules[/\\]").ok(), + name_suffix: Some(ChunkNameSuffixStrategy::PackageName), + allow_chunks: AllowChunks::Async, + test: Some(r"[/\\]node_modules[/\\]".to_string()), min_module_size: Some(lib_min_size), priority: -20, ..Default::default() }, - OptimizeChunkGroup { + ChunkGroup { name: "shared".to_string(), - name_suffix: Some(OptimizeChunkNameSuffixStrategy::DependentsHash), - allow_chunks: OptimizeAllowChunks::Async, + name_suffix: Some(ChunkNameSuffixStrategy::DependentsHash), + allow_chunks: AllowChunks::Async, priority: -30, min_chunks: 2, ..Default::default() diff --git a/crates/mako/src/generate/swc_helpers.rs b/crates/mako/src/generate/swc_helpers.rs index d5284fb5f..270ec7db1 100644 --- a/crates/mako/src/generate/swc_helpers.rs +++ b/crates/mako/src/generate/swc_helpers.rs @@ -3,6 +3,7 @@ use indexmap::IndexSet; use crate::share::helpers::SWC_HELPERS; pub struct SwcHelpers { + #[allow(dead_code)] pub helpers: IndexSet, } diff --git a/crates/mako/src/generate/transform.rs b/crates/mako/src/generate/transform.rs index fc8642131..fc8380cd2 100644 --- a/crates/mako/src/generate/transform.rs +++ b/crates/mako/src/generate/transform.rs @@ -213,7 +213,6 @@ pub fn transform_js_generate(transform_js_param: TransformJsParam) -> Result<()> to_replace: dep_map, context, unresolved_mark, - top_level_mark, }; ast.ast.visit_mut_with(&mut dep_replacer); @@ -323,7 +322,7 @@ mod tests { } fn transform_css_code(content: &str, path: Option<&str>) -> String { - let path = if let Some(p) = path { p } else { "test.css" }; + let path = path.unwrap_or("test.css"); let context: Arc = Arc::new(Default::default()); let mut ast = CssAst::build(path, content, context.clone(), false).unwrap(); transform_css_generate(&mut ast.ast, &context); diff --git a/crates/mako/src/lib.rs b/crates/mako/src/lib.rs index c4a9d15e5..5bc0ede9a 100644 --- a/crates/mako/src/lib.rs +++ b/crates/mako/src/lib.rs @@ -1,7 +1,6 @@ #![feature(box_patterns)] #![feature(hasher_prefixfree_extras)] #![feature(let_chains)] -#![feature(result_option_inspect)] pub mod ast; mod build; @@ -15,7 +14,7 @@ mod module; mod module_graph; pub mod plugin; mod plugins; -mod resolve; +pub mod resolve; pub mod share; pub mod stats; pub mod utils; diff --git a/crates/mako/src/main.rs b/crates/mako/src/main.rs index 45691164d..5663333e6 100644 --- a/crates/mako/src/main.rs +++ b/crates/mako/src/main.rs @@ -1,6 +1,5 @@ #![feature(box_patterns)] #![feature(let_chains)] -#![feature(result_option_inspect)] use std::sync::Arc; diff --git a/crates/mako/src/module.rs b/crates/mako/src/module.rs index ad8e43a95..bd814d952 100644 --- a/crates/mako/src/module.rs +++ b/crates/mako/src/module.rs @@ -453,6 +453,7 @@ impl Module { let func = Function { span: DUMMY_SP, + ctxt: Default::default(), params: vec![ quote_ident!("module").into(), quote_ident!("exports").into(), @@ -461,6 +462,7 @@ impl Module { decorators: vec![], body: Some(BlockStmt { span: DUMMY_SP, + ctxt: Default::default(), stmts, }), is_generator: false, @@ -488,6 +490,7 @@ impl Debug for Module { fn empty_module_fn_expr() -> FnExpr { let func = Function { + ctxt: Default::default(), span: DUMMY_SP, params: vec![ quote_ident!("module").into(), @@ -496,6 +499,7 @@ fn empty_module_fn_expr() -> FnExpr { ], decorators: vec![], body: Some(BlockStmt { + ctxt: Default::default(), span: DUMMY_SP, stmts: vec![], }), diff --git a/crates/mako/src/plugin.rs b/crates/mako/src/plugin.rs index f33b568fc..5d1d54225 100644 --- a/crates/mako/src/plugin.rs +++ b/crates/mako/src/plugin.rs @@ -23,6 +23,11 @@ pub struct PluginLoadParam<'a> { pub file: &'a File, } +#[derive(Debug)] +pub struct PluginResolveIdParams { + pub is_entry: bool, +} + pub struct PluginParseParam<'a> { pub file: &'a File, } @@ -53,6 +58,16 @@ pub trait Plugin: Any + Send + Sync { Ok(None) } + fn resolve_id( + &self, + _source: &str, + _importer: &str, + _params: &PluginResolveIdParams, + _context: &Arc, + ) -> Result> { + Ok(None) + } + fn next_build(&self, _next_build_param: &NextBuildParam) -> bool { true } @@ -208,7 +223,6 @@ impl PluginDriver { Ok(None) } - #[allow(dead_code)] pub fn transform_js( &self, param: &PluginTransformJsParam, @@ -233,7 +247,6 @@ impl PluginDriver { Ok(()) } - #[allow(dead_code)] pub fn before_resolve( &self, param: &mut Vec, @@ -245,6 +258,22 @@ impl PluginDriver { Ok(()) } + pub fn resolve_id( + &self, + source: &str, + importer: &str, + params: &PluginResolveIdParams, + context: &Arc, + ) -> Result> { + for plugin in &self.plugins { + let ret = plugin.resolve_id(source, importer, params, context)?; + if ret.is_some() { + return Ok(ret); + } + } + Ok(None) + } + pub fn before_generate(&self, context: &Arc) -> Result<()> { for plugin in &self.plugins { plugin.generate_begin(context)?; diff --git a/crates/mako/src/plugins/bundless_compiler.rs b/crates/mako/src/plugins/bundless_compiler.rs index 82f9f1024..68c10be36 100644 --- a/crates/mako/src/plugins/bundless_compiler.rs +++ b/crates/mako/src/plugins/bundless_compiler.rs @@ -235,7 +235,6 @@ fn transform_js_generate( to_replace: dep_map, context, unresolved_mark: ast.unresolved_mark, - top_level_mark: ast.top_level_mark, }; ast.ast.visit_mut_with(&mut dep_replacer); diff --git a/crates/mako/src/plugins/context_module.rs b/crates/mako/src/plugins/context_module.rs index e44b528a2..8acfa2870 100644 --- a/crates/mako/src/plugins/context_module.rs +++ b/crates/mako/src/plugins/context_module.rs @@ -13,6 +13,7 @@ use swc_core::ecma::visit::{VisitMut, VisitMutWith}; use crate::ast::file::{Content, JsContent}; use crate::ast::utils::{is_commonjs_require, is_dynamic_import}; +use crate::ast::DUMMY_CTXT; use crate::build::load::JS_EXTENSIONS; use crate::compiler::Context; use crate::plugin::{Plugin, PluginLoadParam}; @@ -151,6 +152,7 @@ impl VisitMut for ContextModuleVisitor { let args_literals = format!("{}?context&glob={}", from, glob); let mut ctxt_call_expr = CallExpr { + ctxt: Default::default(), callee: expr.callee.clone(), args: vec![quote_str!(args_literals.clone()).as_arg()], span: DUMMY_SP, @@ -175,7 +177,7 @@ impl VisitMut for ContextModuleVisitor { .as_callee(); // TODO: allow use await in args // eg: import(`./i18n${await xxx()}`) - expr.args = vec![member_expr!(DUMMY_SP, m.default) + expr.args = vec![member_expr!(DUMMY_CTXT, DUMMY_SP, m.default) .as_call(DUMMY_SP, expr.args.clone()) .as_expr() .to_owned() @@ -203,8 +205,7 @@ fn try_replace_context_arg( // handle `(...)` Expr::Paren(ParenExpr { expr: paren_expr, .. - }) => try_replace_context_arg(paren_expr, has_visit_top_bin) - .map(|(prefix, suffix)| (prefix, suffix)), + }) => try_replace_context_arg(paren_expr, has_visit_top_bin), // handle `'./foo/' + bar` Expr::Bin(BinExpr { diff --git a/crates/mako/src/plugins/duplicate_package_checker.rs b/crates/mako/src/plugins/duplicate_package_checker.rs index 2b3ee1b80..4f283a60b 100644 --- a/crates/mako/src/plugins/duplicate_package_checker.rs +++ b/crates/mako/src/plugins/duplicate_package_checker.rs @@ -99,17 +99,19 @@ impl DuplicatePackageCheckerPlugin { .as_ref() .and_then(|info| info.resolved_resource.as_ref()) { - let package_json = resource.0.package_json().unwrap(); - let raw_json = package_json.raw_json(); - if let Some(name) = package_json.name.clone() { - if let Some(version) = raw_json.as_object().unwrap().get("version") { - let package_info = PackageInfo { - name, - version: semver::Version::parse(version.as_str().unwrap()).unwrap(), - path: package_json.path.clone(), - }; - - packages.push(package_info); + if let Some(package_json) = resource.0.package_json() { + let raw_json = package_json.raw_json(); + if let Some(name) = package_json.name.clone() { + if let Some(version) = raw_json.as_object().unwrap().get("version") { + let package_info = PackageInfo { + name, + version: semver::Version::parse(version.as_str().unwrap()) + .unwrap(), + path: package_json.path.clone(), + }; + + packages.push(package_info); + } } } } diff --git a/crates/mako/src/plugins/invalid_webpack_syntax.rs b/crates/mako/src/plugins/invalid_webpack_syntax.rs index 85ce2708a..568888ab8 100644 --- a/crates/mako/src/plugins/invalid_webpack_syntax.rs +++ b/crates/mako/src/plugins/invalid_webpack_syntax.rs @@ -36,7 +36,6 @@ impl Plugin for InvalidWebpackSyntaxPlugin { ast.visit_with(&mut InvalidSyntaxVisitor { unresolved_mark: param.unresolved_mark, handler: param.handler, - path: param.path, }); Ok(()) } @@ -45,7 +44,6 @@ impl Plugin for InvalidWebpackSyntaxPlugin { pub struct InvalidSyntaxVisitor<'a> { unresolved_mark: Mark, pub handler: &'a Handler, - pub path: &'a str, } impl<'a> Visit for InvalidSyntaxVisitor<'a> { @@ -65,7 +63,7 @@ impl<'a> Visit for InvalidSyntaxVisitor<'a> { let is_webpack_prefix = n.sym.starts_with("__webpack_") && &n.sym != "__webpack_nonce__" && &n.sym != "__webpack_public_path__"; - let has_binding = n.span.ctxt.outer() != self.unresolved_mark; + let has_binding = n.ctxt.outer() != self.unresolved_mark; if is_webpack_prefix && !has_binding { self.handler .struct_span_err( @@ -92,9 +90,9 @@ fn is_member_prop( .. } = expr { - let is_obj_match = ident.sym.to_string() == obj; - let has_binding = ident.span.ctxt.outer() != unresolved_mark; - let is_prop_match = prop_ident.sym.to_string() == prop; + let is_obj_match = ident.sym == obj; + let has_binding = ident.ctxt.outer() != unresolved_mark; + let is_prop_match = prop_ident.sym == prop; is_obj_match && (check_obj_binding && !has_binding) && is_prop_match } else { false diff --git a/crates/mako/src/plugins/minifish/inject.rs b/crates/mako/src/plugins/minifish/inject.rs index c64d25311..fc30874e1 100644 --- a/crates/mako/src/plugins/minifish/inject.rs +++ b/crates/mako/src/plugins/minifish/inject.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use indexmap::IndexSet; use regex::Regex; -use swc_core::common::{Mark, Span, SyntaxContext, DUMMY_SP}; +use swc_core::common::{Mark, SyntaxContext, DUMMY_SP}; use swc_core::ecma::ast::{ ExportSpecifier, Ident, ImportDecl, ImportDefaultSpecifier, ImportNamedSpecifier, ImportSpecifier, ImportStarAsSpecifier, MemberExpr, ModuleDecl, ModuleItem, NamedExport, Stmt, @@ -12,6 +12,8 @@ use swc_core::ecma::ast::{ use swc_core::ecma::utils::{quote_ident, quote_str, ExprFactory}; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; +use crate::ast::DUMMY_CTXT; + pub(super) struct MyInjector<'a> { unresolved_mark: Mark, injects: HashMap, @@ -36,11 +38,11 @@ impl VisitMut for MyInjector<'_> { return; } - if n.span.ctxt.outer() == self.unresolved_mark { + if n.ctxt.outer() == self.unresolved_mark { let name = n.sym.to_string(); if let Some(inject) = self.injects.remove(&name) { - self.will_inject.insert((inject, n.span.ctxt)); + self.will_inject.insert((inject, n.ctxt)); } } } @@ -116,9 +118,10 @@ impl Hash for Inject { impl Inject { fn into_require_with(self, ctxt: SyntaxContext, unresolved_mark: Mark) -> ModuleItem { - let name_span = Span { ctxt, ..DUMMY_SP }; + let name_span = DUMMY_SP; + let unresolved_ctxt = DUMMY_CTXT.apply_mark(unresolved_mark); - let require_source_expr = quote_ident!(DUMMY_SP.apply_mark(unresolved_mark), "require") + let require_source_expr = quote_ident!(unresolved_ctxt, DUMMY_SP, "require") .as_call(DUMMY_SP, vec![quote_str!(self.from).as_arg()]); let stmt: Stmt = match (&self.named, &self.namespace) { @@ -130,14 +133,14 @@ impl Inject { } .into_var_decl( VarDeclKind::Var, - quote_ident!(name_span, self.name.clone()).into(), + quote_ident!(ctxt, name_span, self.name.clone()).into(), ) .into(), // import * as x (None, Some(true)) => require_source_expr .into_var_decl( VarDeclKind::Var, - quote_ident!(name_span, self.name.clone()).into(), + quote_ident!(ctxt, name_span, self.name.clone()).into(), ) .into(), @@ -149,7 +152,7 @@ impl Inject { } .into_var_decl( VarDeclKind::Var, - quote_ident!(name_span, self.name.clone()).into(), + quote_ident!(ctxt, name_span, self.name.clone()).into(), ) .into(), (Some(_), Some(true)) => { @@ -161,12 +164,12 @@ impl Inject { } fn into_with(self, ctxt: SyntaxContext) -> ModuleItem { - let name_span = Span { ctxt, ..DUMMY_SP }; + let name_span = DUMMY_SP; let specifier: ImportSpecifier = match (&self.named, &self.namespace) { // import { named as x } (Some(named), None | Some(false)) => ImportNamedSpecifier { span: DUMMY_SP, - local: quote_ident!(name_span, self.name.clone()), + local: quote_ident!(ctxt, name_span, self.name.clone()), imported: if *named == self.name { None } else { @@ -179,14 +182,14 @@ impl Inject { // import * as x (None, Some(true)) => ImportStarAsSpecifier { span: DUMMY_SP, - local: quote_ident!(name_span, self.name), + local: quote_ident!(ctxt, name_span, self.name), } .into(), // import x (None, None | Some(false)) => ImportDefaultSpecifier { span: DUMMY_SP, - local: quote_ident!(name_span, self.name), + local: quote_ident!(ctxt, name_span, self.name), } .into(), @@ -196,6 +199,7 @@ impl Inject { }; let decl: ModuleDecl = ImportDecl { + phase: Default::default(), span: DUMMY_SP, specifiers: vec![specifier], type_only: false, diff --git a/crates/mako/src/plugins/minifish/unsimplify.rs b/crates/mako/src/plugins/minifish/unsimplify.rs index 587d76a32..b4b8bd987 100644 --- a/crates/mako/src/plugins/minifish/unsimplify.rs +++ b/crates/mako/src/plugins/minifish/unsimplify.rs @@ -3,6 +3,8 @@ use swc_core::common::DUMMY_SP; use swc_core::ecma::ast::{BlockStmt, IfStmt, Stmt}; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; +use crate::ast::DUMMY_CTXT; + pub(super) struct UnSimplify {} impl VisitMut for UnSimplify { @@ -14,6 +16,7 @@ impl VisitMut for UnSimplify { if_stmt.cons = Box::new( BlockStmt { + ctxt: DUMMY_CTXT, span: DUMMY_SP, stmts: vec![*cons], } diff --git a/crates/mako/src/plugins/progress.rs b/crates/mako/src/plugins/progress.rs index 43c89e12d..b68d3b304 100644 --- a/crates/mako/src/plugins/progress.rs +++ b/crates/mako/src/plugins/progress.rs @@ -9,7 +9,7 @@ use crate::ast::file::Content; use crate::compiler::Context; use crate::plugin::{Plugin, PluginLoadParam}; -/** +/* * 插件执行顺序 3 ~ 7 会重复执行 * 1. modify_config * 2. build_start diff --git a/crates/mako/src/plugins/require_context/visitor.rs b/crates/mako/src/plugins/require_context/visitor.rs index ec83ae6ce..229fc0c7e 100644 --- a/crates/mako/src/plugins/require_context/visitor.rs +++ b/crates/mako/src/plugins/require_context/visitor.rs @@ -47,7 +47,7 @@ impl RequireContextVisitor { builder.build() } - fn is_valid_args(&self, args: &Vec) -> bool { + fn is_valid_args(&self, args: &[ExprOrSpread]) -> bool { if !args.is_empty() && args.len() <= 4 { args.iter().all(|arg| { if arg.spread.is_some() { diff --git a/crates/mako/src/plugins/ssu.rs b/crates/mako/src/plugins/ssu.rs index 843e3d152..9060a4794 100644 --- a/crates/mako/src/plugins/ssu.rs +++ b/crates/mako/src/plugins/ssu.rs @@ -8,15 +8,14 @@ use std::sync::{Arc, Mutex}; use anyhow::Result; use dashmap::DashSet; use rayon::prelude::*; -use regex::Regex; use serde::{Deserialize, Serialize}; use tracing::debug; use crate::ast::file::{Content, File, JsContent}; use crate::compiler::{Args, Compiler, Context}; use crate::config::{ - CodeSplitting, CodeSplittingAdvancedOptions, CodeSplittingStrategy, - CodeSplittingStrategyOptions, Config, OptimizeAllowChunks, OptimizeChunkGroup, + AllowChunks, ChunkGroup, CodeSplitting, CodeSplittingAdvancedOptions, CodeSplittingStrategy, + CodeSplittingStrategyOptions, Config, }; use crate::generate::chunk::ChunkType; use crate::generate::chunk_pot::util::{hash_hashmap, hash_vec}; @@ -164,18 +163,18 @@ impl Plugin for SUPlus { CodeSplittingAdvancedOptions { min_size: 0, groups: vec![ - OptimizeChunkGroup { + ChunkGroup { name: "node_modules".to_string(), name_suffix: None, - allow_chunks: OptimizeAllowChunks::All, + allow_chunks: AllowChunks::All, min_chunks: 0, min_size: 0, max_size: usize::MAX, min_module_size: None, priority: 10, - test: Regex::new(r"[/\\]node_modules[/\\]").ok(), + test: Some(r"[/\\]node_modules[/\\]".to_string()), }, - OptimizeChunkGroup { + ChunkGroup { name: "common".to_string(), min_chunks: 0, // always split, to avoid multi-instance risk diff --git a/crates/mako/src/plugins/tree_shaking.rs b/crates/mako/src/plugins/tree_shaking.rs index b425e8de6..86c289e83 100644 --- a/crates/mako/src/plugins/tree_shaking.rs +++ b/crates/mako/src/plugins/tree_shaking.rs @@ -56,13 +56,14 @@ impl VisitMut for TopLevelDeclSplitter { if let ModuleItem::Stmt(Stmt::Decl(Decl::Var(var_decl))) = module_item { if var_decl.decls.len() > 1 { let declarators = var_decl.decls.take(); - + let ctxt = var_decl.ctxt; let kind = var_decl.kind; let items = declarators .into_iter() .map(|decl| { let i: ModuleItem = VarDecl { + ctxt, span: decl.span, kind, declare: false, diff --git a/crates/mako/src/plugins/tree_shaking/module.rs b/crates/mako/src/plugins/tree_shaking/module.rs index 1876bc5c3..3ee2378a3 100644 --- a/crates/mako/src/plugins/tree_shaking/module.rs +++ b/crates/mako/src/plugins/tree_shaking/module.rs @@ -1,4 +1,5 @@ use std::collections::{BTreeMap, HashSet}; +use std::fmt::Display; use swc_core::common::SyntaxContext; use swc_core::ecma::ast::{Module as SwcModule, ModuleItem}; @@ -21,14 +22,15 @@ pub enum UsedIdent { ExportAll, } -impl ToString for UsedIdent { - fn to_string(&self) -> String { - match self { +impl Display for UsedIdent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let str = match self { UsedIdent::SwcIdent(ident) => ident.to_string(), UsedIdent::Default => "default".to_string(), UsedIdent::InExportAll(ident) => ident.to_string(), UsedIdent::ExportAll => "*".to_string(), - } + }; + write!(f, "{}", str) } } diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate.rs index db4ab61be..c5b3ce9fe 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate.rs @@ -1,6 +1,5 @@ mod concatenate_context; mod concatenated_transformer; -mod exports_transform; mod external_transformer; mod module_ref_rewriter; mod ref_link; @@ -13,10 +12,10 @@ use std::sync::Arc; use concatenated_transformer::ConcatenatedTransform; use external_transformer::ExternalTransformer; use swc_core::common::util::take::Take; -use swc_core::common::{Span, SyntaxContext, GLOBALS}; +use swc_core::common::{SyntaxContext, GLOBALS}; use swc_core::ecma::transforms::base::hygiene::hygiene; use swc_core::ecma::transforms::base::resolver; -use swc_core::ecma::visit::{VisitMut, VisitMutWith}; +use swc_core::ecma::visit::{as_folder, Fold, VisitMut, VisitMutWith}; use self::concatenate_context::EsmDependantFlags; use self::utils::uniq_module_prefix; @@ -356,7 +355,7 @@ pub fn optimize_module_graph( ccn_trans.imported(all_import_type); script_ast.ast.visit_mut_with(&mut ccn_trans); - script_ast.ast.visit_mut_with(&mut CleanSyntaxContext {}); + script_ast.ast.visit_mut_with(&mut clean_syntax_context()); if cfg!(debug_assertions) && inner_print { let code = script_ast.generate(context.clone()).unwrap().code; @@ -412,7 +411,7 @@ pub fn optimize_module_graph( println!("root after all:\n{}\n", code); } - root_module_ast.visit_mut_with(&mut CleanSyntaxContext {}); + root_module_ast.visit_mut_with(&mut clean_syntax_context()); let prefix_items = concatenate_context.root_exports_stmts(&config.root); module_items.splice(0..0, prefix_items); @@ -447,13 +446,15 @@ struct ConcatenateConfig { externals: HashMap, } -impl ConcatenateConfig {} +struct CleanSyntaxContext; -pub struct CleanSyntaxContext; +pub fn clean_syntax_context() -> impl VisitMut + Fold { + as_folder(CleanSyntaxContext {}) +} impl VisitMut for CleanSyntaxContext { - fn visit_mut_span(&mut self, n: &mut Span) { - n.ctxt = SyntaxContext::empty(); + fn visit_mut_syntax_context(&mut self, ctxt: &mut SyntaxContext) { + *ctxt = SyntaxContext::empty(); } } diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenate_context.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenate_context.rs index 40a96c7cd..d20b6565a 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenate_context.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenate_context.rs @@ -15,6 +15,7 @@ use swc_core::ecma::utils::{ }; use swc_core::ecma::visit::{Visit, VisitWith}; +use crate::ast::DUMMY_CTXT; use crate::module::{ImportType, ModuleId, NamedExportType, ResolveType}; use crate::module_graph::ModuleGraph; use crate::plugins::tree_shaking::shake::module_concatenate::ConcatenateConfig; @@ -250,10 +251,10 @@ pub type ImportModuleRefMap = HashMap; pub fn module_ref_to_expr(module_ref: &ModuleRef) -> Expr { match module_ref { - (id, None) => quote_ident!(id.sym.clone()).into(), + (id, None) => quote_ident!(DUMMY_CTXT, id.sym.clone()).into(), (id, Some(field)) => MemberExpr { span: DUMMY_SP, - obj: quote_ident!(id.sym.clone()).into(), + obj: quote_ident!(DUMMY_CTXT, id.sym.clone()).into(), prop: quote_ident!(field.clone()).into(), } .into(), @@ -301,7 +302,7 @@ impl ConcatenateContext { pub fn top_level_vars(ast: &Module, top_level_mark: Mark) -> HashSet { let mut top_level_vars = HashSet::new(); top_level_vars.extend( - collect_decls_with_ctxt(ast, SyntaxContext::empty().apply_mark(top_level_mark)) + collect_decls_with_ctxt(ast, DUMMY_CTXT.apply_mark(top_level_mark)) .iter() .map(|id: &Id| id.0.to_string()), ); @@ -327,7 +328,7 @@ impl ConcatenateContext { pub fn global_vars(ast: &Module, unresolved_mark: Mark) -> HashSet { let mut globals = HashSet::new(); - let mut collector = GlobalCollect::new(SyntaxContext::empty().apply_mark(unresolved_mark)); + let mut collector = GlobalCollect::new(DUMMY_CTXT.apply_mark(unresolved_mark)); ast.visit_with(&mut collector); globals.extend( collector @@ -401,7 +402,7 @@ impl ConcatenateContext { .collect(); // __mako_require__.d(exports, __esModule, { value: true }); - let esm_compat = member_expr!(DUMMY_SP, __mako_require__.d) + let esm_compat = member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.d) .as_call( DUMMY_SP, vec![ @@ -426,7 +427,7 @@ impl ConcatenateContext { if !key_value_props.is_empty() { // __mako_require__.e(exports, { exported: function(){ return v}, ... }); - let export_stmt = member_expr!(DUMMY_SP, __mako_require__.e) + let export_stmt = member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.e) .as_call( DUMMY_SP, vec![ @@ -527,7 +528,7 @@ impl GlobalCollect { impl Visit for GlobalCollect { fn visit_ident(&mut self, n: &Ident) { - if n.span.ctxt == self.unresolved_ctxt { + if n.ctxt == self.unresolved_ctxt { self.refed_globals.insert(n.to_id()); } } diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer.rs index 8edbad057..e31ff61fd 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use swc_core::common::collections::AHashSet; use swc_core::common::comments::{Comment, CommentKind}; use swc_core::common::util::take::Take; -use swc_core::common::{Mark, Spanned, SyntaxContext, DUMMY_SP}; +use swc_core::common::{Mark, Spanned, DUMMY_SP}; use swc_core::ecma::ast::{ ClassDecl, DefaultDecl, ExportAll, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, FnDecl, Id, ImportDecl, KeyValueProp, Module, ModuleItem, NamedExport, ObjectLit, Prop, PropOrSpread, @@ -19,6 +19,7 @@ use super::concatenate_context::{ use super::module_ref_rewriter::ModuleRefRewriter; use super::ref_link::{ModuleDeclMapCollector, Symbol, VarLink}; use super::utils::{uniq_module_default_export_name, uniq_module_namespace_name}; +use crate::ast::DUMMY_CTXT; use crate::compiler::Context; use crate::module::{relative_to_root, ImportType, ModuleId}; @@ -119,7 +120,7 @@ impl<'a> ConcatenatedTransform<'a> { if let Some(mf) = map.get("default") { mf.clone() } else { - (quote_ident!("undefined"), None) + (quote_ident!(DUMMY_CTXT, "undefined"), None) } } Symbol::Namespace => map.get("*").unwrap().clone(), @@ -127,7 +128,7 @@ impl<'a> ConcatenatedTransform<'a> { if let Some(mf) = map.get(&ident.sym.to_string()) { mf.clone() } else { - (quote_ident!("undefined"), None) + (quote_ident!(DUMMY_CTXT, "undefined"), None) } } }; @@ -137,7 +138,10 @@ impl<'a> ConcatenatedTransform<'a> { InnerOrExternal::External(external_names) => { ref_map.insert( id.clone(), - (quote_ident!(external_names.1.clone()), symbol.to_field()), + ( + quote_ident!(DUMMY_CTXT, external_names.1.clone()), + symbol.to_field(), + ), ); } } @@ -171,7 +175,7 @@ impl<'a> ConcatenatedTransform<'a> { if let Some(mf) = map.get("default") { mf.clone() } else { - (quote_ident!("undefined"), None) + (quote_ident!(DUMMY_CTXT, "undefined"), None) } } Symbol::Namespace => map.get("*").unwrap().clone(), @@ -179,7 +183,7 @@ impl<'a> ConcatenatedTransform<'a> { if let Some(mf) = map.get(&ident.sym.to_string()) { mf.clone() } else { - (quote_ident!("undefined"), None) + (quote_ident!(DUMMY_CTXT, "undefined"), None) } } }; @@ -188,7 +192,10 @@ impl<'a> ConcatenatedTransform<'a> { InnerOrExternal::External(external_names) => { ref_map.insert( id.0.to_string(), - (quote_ident!(external_names.1.clone()), symbol.to_field()), + ( + quote_ident!(DUMMY_CTXT, external_names.1.clone()), + symbol.to_field(), + ), ); } } @@ -289,7 +296,7 @@ impl<'a> ConcatenatedTransform<'a> { } fn resolve_conflict(&mut self, import_module_ref: &ImportModuleRefMap) { - let top_ctxt = SyntaxContext::empty().apply_mark(self.top_level_mark); + let top_ctxt = DUMMY_CTXT.apply_mark(self.top_level_mark); let imported_reference = all_referenced_variables(import_module_ref); @@ -367,7 +374,7 @@ impl<'a> ConcatenatedTransform<'a> { .map(Into::into) .collect::>(); - let define_exports: Stmt = member_expr!(DUMMY_SP, __mako_require__.e) + let define_exports: Stmt = member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.e) .as_call( DUMMY_SP, vec![ @@ -381,7 +388,10 @@ impl<'a> ConcatenatedTransform<'a> { ) .into_stmt(); - export_ref_map.insert("*".to_string(), (quote_ident!(ns_name.clone()), None)); + export_ref_map.insert( + "*".to_string(), + (quote_ident!(DUMMY_CTXT, ns_name.clone()), None), + ); self.my_top_decls.insert(ns_name); n.body.push(init_stmt.into()); @@ -474,7 +484,8 @@ impl<'a> VisitMut for ConcatenatedTransform<'a> { } fn visit_mut_export_default_expr(&mut self, export_default_expr: &mut ExportDefaultExpr) { - let span = export_default_expr.span.apply_mark(self.top_level_mark); + let span = export_default_expr.span; + let ctxt = DUMMY_CTXT.apply_mark(self.top_level_mark); let default_binding_name = self.default_bind_name.clone(); @@ -486,7 +497,7 @@ impl<'a> VisitMut for ConcatenatedTransform<'a> { .take() .into_var_decl( VarDeclKind::Var, - quote_ident!(span, default_binding_name.clone()).into(), + quote_ident!(ctxt, span, default_binding_name.clone()).into(), ) .into(); self.my_top_decls.insert(default_binding_name.clone()); diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer/tests.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer/tests.rs index ff98a8973..e439a86fb 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer/tests.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/concatenated_transformer/tests.rs @@ -10,6 +10,7 @@ use super::super::ConcatenateContext; use super::utils::describe_export_map; use super::ConcatenatedTransform; use crate::ast::js_ast::JsAst; +use crate::ast::DUMMY_CTXT; use crate::compiler::Context; use crate::config::{Config, Mode, OptimizationConfig}; use crate::module::{ImportType, ModuleId}; @@ -616,7 +617,8 @@ fn test_export_from_var() { let mut ccn_ctx = ConcatenateContext { modules_exports_map: hashmap! { ModuleId::from("src/index.js") => hashmap! { - "default".to_string() => (quote_ident!("src_index_default"), None) + "default".to_string() => (quote_ident!(DUMMY_CTXT,"src_index_default"), + None) } }, ..Default::default() @@ -698,10 +700,10 @@ fn concatenate_context_fixture_with_inner_module() -> ConcatenateContext { }, modules_exports_map: hashmap! { ModuleId::from("src/index.js") => hashmap!{ - "*".to_string() => (quote_ident!("inner_namespace"), None), - "default".to_string() => ( quote_ident!("inner_default_export"), None), - "foo".to_string() => (quote_ident!("bar") ,None), - "named".to_string() => (quote_ident!("named"), None) + "*".to_string() => (quote_ident!(DUMMY_CTXT,"inner_namespace"), None), + "default".to_string() => ( quote_ident!(DUMMY_CTXT,"inner_default_export"), None), + "foo".to_string() => (quote_ident!(DUMMY_CTXT,"bar") ,None), + "named".to_string() => (quote_ident!(DUMMY_CTXT,"named"), None) }, ModuleId::from("src/no_exports.js") => hashmap!{}, }, @@ -739,7 +741,7 @@ fn inner_trans_code_imported_as( let src_to_module = hashmap! { "./src".to_string() => ModuleId::from("src/index.js"), "./no_exports".to_string() => ModuleId::from("src/no_exports.js"), - "external".to_string() => ModuleId::from("external") + "external".to_string() => ModuleId::from("external") }; GLOBALS.set(&context.meta.script.globals, || { diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/exports_transform.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/exports_transform.rs deleted file mode 100644 index d4cbb07d6..000000000 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/exports_transform.rs +++ /dev/null @@ -1,204 +0,0 @@ -use std::collections::HashSet; - -use swc_core::ecma::ast::{ - Decl, ExportSpecifier, Ident, ModuleDecl, ModuleExportName, ObjectPatProp, Pat, -}; -use swc_core::ecma::visit::{Visit, VisitWith}; - -#[derive(Default)] -pub(super) struct PatDefineIdCollector { - defined_idents: HashSet, -} - -impl Visit for PatDefineIdCollector { - fn visit_pat(&mut self, pat: &Pat) { - match pat { - Pat::Ident(bi) => { - self.defined_idents.insert(bi.id.sym.to_string()); - } - Pat::Array(array_pat) => { - for elem in array_pat.elems.iter().flatten() { - self.visit_pat(elem); - } - } - Pat::Rest(rest_pat) => { - self.visit_pat(&rest_pat.arg); - } - Pat::Object(obj_pat) => { - for prop in &obj_pat.props { - match prop { - ObjectPatProp::KeyValue(kv_prop) => { - self.visit_pat(&kv_prop.value); - } - ObjectPatProp::Assign(assign_prop) => { - self.defined_idents.insert(assign_prop.key.sym.to_string()); - } - ObjectPatProp::Rest(rest_prop) => { - self.visit_pat(&rest_prop.arg); - } - } - } - } - Pat::Assign(assign_pat) => { - self.visit_pat(&assign_pat.left); - } - Pat::Invalid(_) => {} - Pat::Expr(_) => {} - } - } -} - -#[derive(Default)] -pub(super) struct ExportsCollector { - exports: HashSet, -} - -impl Visit for ExportsCollector { - fn visit_module_decl(&mut self, n: &ModuleDecl) { - match n { - ModuleDecl::Import(_) => {} - ModuleDecl::ExportDecl(export_decl) => match &export_decl.decl { - Decl::Class(class_decl) => { - self.exports.insert(class_decl.ident.sym.to_string()); - } - Decl::Fn(fn_decl) => { - self.exports.insert(fn_decl.ident.sym.to_string()); - } - Decl::Var(var_decl) => { - for x in var_decl.decls.iter() { - let names = collect_defined_ident_in_pat(&x.name); - self.exports.extend(names); - } - } - Decl::Using(_using_decl) => { - // TODO: when necessary - // for var_decl in using_decl.decls.iter() { - // let names = collect_defined_ident_in_pat(&var_decl.name); - // self.exports.extend(names); - // } - } - Decl::TsInterface(_) => {} - Decl::TsTypeAlias(_) => {} - Decl::TsEnum(_) => {} - Decl::TsModule(_) => {} - }, - ModuleDecl::ExportNamed(export_named) => export_named.specifiers.iter().for_each( - |export_specifier| match &export_specifier { - ExportSpecifier::Namespace(namespace) => { - if let Some(ident) = module_export_name_as_ident(&namespace.name) { - self.exports.insert(ident.sym.to_string()); - } - } - ExportSpecifier::Default(export_default) => { - self.exports.insert(export_default.exported.sym.to_string()); - } - ExportSpecifier::Named(named_export) => { - if let Some(exported) = &named_export.exported - && let Some(ident) = module_export_name_as_ident(exported) - { - self.exports.insert(ident.sym.to_string()); - } else if let Some(ident) = module_export_name_as_ident(&named_export.orig) - { - self.exports.insert(ident.sym.to_string()); - } - } - }, - ), - ModuleDecl::ExportDefaultDecl(_) | ModuleDecl::ExportDefaultExpr(_) => { - self.exports.insert("default".into()); - } - ModuleDecl::ExportAll(_) => { - // not allowed in inner module - } - ModuleDecl::TsImportEquals(_) => {} - ModuleDecl::TsExportAssignment(_) => {} - ModuleDecl::TsNamespaceExport(_) => {} - } - } -} - -fn collect_defined_ident_in_pat(pat: &Pat) -> HashSet { - let mut c: PatDefineIdCollector = Default::default(); - pat.visit_with(&mut c); - c.defined_idents -} - -fn module_export_name_as_ident(module_export_name: &ModuleExportName) -> Option<&Ident> { - match module_export_name { - ModuleExportName::Ident(ident) => Some(ident), - _ => None, - } -} - -#[cfg(test)] -mod tests { - use maplit::hashset; - use swc_core::ecma::visit::VisitWith; - - use super::*; - use crate::ast::tests::TestUtils; - - #[test] - fn collect_default_export() { - assert_eq!( - extract_export("export default 1"), - hashset! {"default".to_string()} - ); - } - - #[test] - fn export_named_fn() { - assert_eq!( - extract_export("export function fn(){}"), - hashset! {"fn".to_string()} - ); - } - - #[test] - fn export_named_class() { - assert_eq!( - extract_export("export class C{}"), - hashset! {"C".to_string()} - ); - } - - #[test] - fn export_names() { - assert_eq!( - extract_export("let a=1,b=2; export {a,b}"), - hashset! {"a".to_string(), "b".to_string()} - ); - } - - #[test] - fn export_object_deconstruct() { - assert_eq!( - extract_export("let A= {a:1,b:2, c:3}; export const {a,b:x, ...z} = A"), - hashset! {"a".to_string(), "x".to_string(), "z".to_string()} - ); - } - - #[test] - fn export_array_deconstruct() { - assert_eq!( - extract_export("let a= [1,2,3]; export const [x,y,...z] = a"), - hashset! {"x".to_string(), "y".to_string(), "z".to_string()} - ); - } - - #[test] - fn export_var_decl_export() { - assert_eq!( - extract_export("export const a =1"), - hashset! {"a".to_string()} - ); - } - - fn extract_export(code: &str) -> HashSet { - let mut ast = TestUtils::gen_js_ast(code); - let mut collectort = ExportsCollector::default(); - - ast.ast.js_mut().ast.visit_with(&mut collectort); - collectort.exports - } -} diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/external_transformer.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/external_transformer.rs index c34db19a5..2d5dd24ef 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/external_transformer.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/external_transformer.rs @@ -26,7 +26,7 @@ impl<'a> ExternalTransformer<'_> { fn require_arg_to_module_namespace( &self, - args: &Vec, + args: &[ExprOrSpread], ) -> Option<((String, String), ModuleId)> { if args.len() == 1 && let Some(arg) = args.first() diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/module_ref_rewriter.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/module_ref_rewriter.rs index e240c597d..ba3a06742 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/module_ref_rewriter.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/module_ref_rewriter.rs @@ -5,11 +5,12 @@ use swc_core::common::{Span, SyntaxContext, DUMMY_SP}; use swc_core::ecma::ast::*; use swc_core::ecma::transforms::base::helpers::HELPERS; use swc_core::ecma::utils::{ - is_valid_prop_ident, quote_ident, quote_str, undefined, ExprFactory, IntoIndirectCall, + is_valid_prop_ident, quote_ident, quote_str, ExprFactory, IntoIndirectCall, }; use swc_core::ecma::visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; use super::concatenate_context::ImportModuleRefMap; +use crate::ast::DUMMY_CTXT; pub struct ModuleRefRewriter<'a> { /// ```javascript @@ -55,7 +56,7 @@ impl<'a> ModuleRefRewriter<'a> { HELPERS .is_set() .then(|| HELPERS.with(|helper| helper.mark())) - .map(|mark| SyntaxContext::empty().apply_mark(mark)) + .map(|mark| DUMMY_CTXT.apply_mark(mark)) }, } } @@ -91,7 +92,7 @@ impl VisitMut for ModuleRefRewriter<'_> { Expr::This(ThisExpr { span }) => { if !self.allow_top_level_this && self.is_global_this { - *n = *undefined(*span); + *n = *Expr::undefined(*span); } } @@ -104,7 +105,7 @@ impl VisitMut for ModuleRefRewriter<'_> { Callee::Expr(e) if e.is_ident() => { let is_indirect_callee = e .as_ident() - .filter(|ident| self.helper_ctxt.iter().all(|ctxt| ctxt != &ident.span.ctxt)) + .filter(|ident| self.helper_ctxt.iter().all(|ctxt| ctxt != &ident.ctxt)) .and_then(|ident| self.import_map.get(&ident.to_id())) .map(|(_, prop)| prop.is_some()) .unwrap_or_default(); @@ -124,7 +125,7 @@ impl VisitMut for ModuleRefRewriter<'_> { let is_indirect = n .tag .as_ident() - .filter(|ident| self.helper_ctxt.iter().all(|ctxt| ctxt != &ident.span.ctxt)) + .filter(|ident| self.helper_ctxt.iter().all(|ctxt| ctxt != &ident.ctxt)) .and_then(|ident| self.import_map.get(&ident.to_id())) .map(|(_, prop)| prop.is_some()) .unwrap_or_default(); @@ -190,7 +191,7 @@ impl ModuleRefRewriter<'_> { .get(&ref_ident.to_id()) .map(|(mod_ident, mod_prop)| -> Expr { let mut mod_ident = mod_ident.clone(); - let span = ref_ident.span.with_ctxt(mod_ident.span.ctxt); + let span = ref_ident.span; mod_ident.span = span; let mod_expr = if self.lazy_record.contains(&mod_ident.to_id()) { @@ -217,7 +218,7 @@ impl ModuleRefRewriter<'_> { fn prop_name(key: &str, span: Span) -> IdentOrStr { if is_valid_prop_ident(key) { - IdentOrStr::Ident(quote_ident!(span, key)) + IdentOrStr::Ident(quote_ident!(DUMMY_CTXT, span, key)) } else { IdentOrStr::Str(quote_str!(span, key)) } @@ -231,7 +232,7 @@ enum IdentOrStr { impl From for PropName { fn from(val: IdentOrStr) -> Self { match val { - IdentOrStr::Ident(i) => Self::Ident(i), + IdentOrStr::Ident(i) => Self::Ident(i.into()), IdentOrStr::Str(s) => Self::Str(s), } } @@ -240,7 +241,7 @@ impl From for PropName { impl From for MemberProp { fn from(val: IdentOrStr) -> Self { match val { - IdentOrStr::Ident(i) => Self::Ident(i), + IdentOrStr::Ident(i) => Self::Ident(i.into()), IdentOrStr::Str(s) => Self::Computed(ComputedPropName { span: DUMMY_SP, expr: s.into(), diff --git a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/ref_link.rs b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/ref_link.rs index f23512ad5..5f9de125f 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/ref_link.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/module_concatenate/ref_link.rs @@ -47,6 +47,8 @@ use swc_core::ecma::ast::{ use swc_core::ecma::utils::quote_ident; use swc_core::ecma::visit::{Visit, VisitWith}; +use crate::ast::DUMMY_CTXT; + #[derive(Default)] pub(super) struct PatDefineIdCollector { defined_idents: HashSet, @@ -73,7 +75,7 @@ impl Visit for PatDefineIdCollector { self.visit_pat(&kv_prop.value); } ObjectPatProp::Assign(assign_prop) => { - self.defined_idents.insert(assign_prop.key.clone()); + self.defined_idents.insert(assign_prop.key.clone().into()); } ObjectPatProp::Rest(rest_prop) => { self.visit_pat(&rest_prop.arg); @@ -284,8 +286,10 @@ impl Visit for ModuleDeclMapCollector { } }; - self.export_map - .insert(quote_ident!("default").to_id(), VarLink::Direct(default_id)); + self.export_map.insert( + quote_ident!(DUMMY_CTXT, "default").to_id(), + VarLink::Direct(default_id), + ); } ModuleDecl::ExportDefaultExpr(export_default_expr) => { let id = match export_default_expr.expr.as_ident() { @@ -296,12 +300,14 @@ impl Visit for ModuleDeclMapCollector { ), }; - self.export_map - .insert(quote_ident!("default").to_id(), VarLink::Direct(id)); + self.export_map.insert( + quote_ident!(DUMMY_CTXT, "default").to_id(), + VarLink::Direct(id), + ); } ModuleDecl::ExportAll(export_all) => { self.export_map.insert( - quote_ident!(format!("*:{}", self.current_stmt_id)).to_id(), + quote_ident!(DUMMY_CTXT, format!("*:{}", self.current_stmt_id)).to_id(), VarLink::All(export_all.src.value.to_string(), self.current_stmt_id), ); } diff --git a/crates/mako/src/plugins/tree_shaking/shake/skip_module.rs b/crates/mako/src/plugins/tree_shaking/shake/skip_module.rs index 48ff402ba..c1a65151e 100644 --- a/crates/mako/src/plugins/tree_shaking/shake/skip_module.rs +++ b/crates/mako/src/plugins/tree_shaking/shake/skip_module.rs @@ -12,6 +12,7 @@ use swc_core::ecma::utils::{quote_ident, quote_str}; use swc_core::quote; use crate::build::analyze_deps; +use crate::ast::DUMMY_CTXT; use crate::compiler::Context; use crate::module::{Dependency, ImportType, ModuleId, NamedExportType, ResolveType}; use crate::module_graph::ModuleGraph; @@ -52,7 +53,7 @@ impl ReExportReplace { ) } else { quote!("export { $local as $ident } from \"$from\";" as ModuleItem, - local: Ident = quote_ident!(local.clone()), + local: Ident = quote_ident!(DUMMY_CTXT, local.clone()), ident: Ident = ident, from: Str = quote_str!(self.from_module_id.id.clone()) ) @@ -105,7 +106,7 @@ impl ReExportReplace { ) } else { quote!("import { $local as $ident } from \"$from\";" as ModuleItem, - local: Ident = quote_ident!(local.clone()), + local: Ident = quote_ident!(DUMMY_CTXT,local.clone()), ident: Ident = ident, from: Str = quote_str!(self.from_module_id.id.clone()) ) @@ -164,7 +165,7 @@ impl From<&ReExportType> for ImportType { pub(super) fn skip_module_optimize( module_graph: &mut ModuleGraph, - tree_shake_modules_ids: &Vec, + tree_shake_modules_ids: &[ModuleId], tree_shake_modules_map: &HashMap>, context: &Arc, ) -> Result<()> { diff --git a/crates/mako/src/plugins/tree_shaking/statement_graph.rs b/crates/mako/src/plugins/tree_shaking/statement_graph.rs index cd77c008f..ad752b042 100644 --- a/crates/mako/src/plugins/tree_shaking/statement_graph.rs +++ b/crates/mako/src/plugins/tree_shaking/statement_graph.rs @@ -31,6 +31,7 @@ pub enum ImportSpecifierInfo { pub struct ImportInfo { pub source: String, pub specifiers: Vec, + #[allow(dead_code)] pub stmt_id: StatementId, } @@ -244,7 +245,9 @@ pub struct Statement { /// transform it to Ident.to_string() is exactly what we want pub defined_idents_map: HashMap>, pub is_self_executed: bool, + #[allow(dead_code)] pub has_side_effects: bool, + #[allow(dead_code)] pub span: Span, } diff --git a/crates/mako/src/resolve.rs b/crates/mako/src/resolve.rs index 89ffde4d5..f283eba13 100644 --- a/crates/mako/src/resolve.rs +++ b/crates/mako/src/resolve.rs @@ -4,15 +4,16 @@ use std::sync::Arc; use std::vec; use anyhow::{anyhow, Result}; -use cached::proc_macro::cached; use convert_case::{Case, Casing}; use oxc_resolver::{Alias, AliasValue, ResolveError as OxcResolveError, ResolveOptions, Resolver}; -use regex::{Captures, Regex}; +use regex::Captures; use thiserror::Error; use tracing::debug; +mod resolution; mod resource; -pub(crate) use resource::{ExternalResource, ResolvedResource, ResolverResource}; +pub use resolution::Resolution; +pub use resource::{ExternalResource, ResolvedResource, ResolverResource}; use crate::ast::file::parse_path; use crate::compiler::Context; @@ -22,6 +23,8 @@ use crate::config::{ }; use crate::features::rsc::Rsc; use crate::module::{Dependency, ResolveType}; +use crate::plugin::PluginResolveIdParams; +use crate::utils::create_cached_regex; #[derive(Debug, Error)] #[error("Resolve {path:?} failed from {from:?}")] @@ -49,6 +52,19 @@ pub fn resolve( crate::mako_profile_function!(); crate::mako_profile_scope!("resolve", &dep.source); + // plugin first + if let Some(resolved) = context.plugin_driver.resolve_id( + &dep.source, + path, + // it's a compatibility feature for unplugin hooks + // is_entry is always false for dependencies + // since entry file does not need be be resolved + &PluginResolveIdParams { is_entry: false }, + context, + )? { + return Ok(resolved); + } + if dep.source.starts_with("virtual:") { return Ok(ResolverResource::Virtual(PathBuf::from(&dep.source))); } @@ -73,11 +89,6 @@ pub fn resolve( do_resolve(path, source, resolver, Some(&context.config.externals)) } -#[cached(key = "String", convert = r#"{ re.to_string() }"#)] -fn create_external_regex(re: &str) -> Regex { - Regex::new(re).unwrap() -} - fn get_external_target( externals: &HashMap, source: &str, @@ -113,7 +124,7 @@ fn get_external_target( externals.iter().find_map(|(key, config)| { match config { ExternalConfig::Advanced(config) if config.subpath.is_some() => { - if let Some(caps) = create_external_regex(&format!( + if let Some(caps) = create_cached_regex(&format!( r#"(?:^|/node_modules/|[a-zA-Z\d]@){}(/|$)"#, key )) @@ -126,7 +137,7 @@ fn get_external_target( // skip if source is excluded Some(exclude) if exclude.iter().any(|e| { - create_external_regex(&format!("(^|/){}(/|$)", e)) + create_cached_regex(&format!("(^|/){}(/|$)", e)) .is_match(subpath.as_str()) }) => { @@ -146,7 +157,7 @@ fn get_external_target( // ex. import Button from 'antd/es/button'; // find matched subpath rule if let Some((rule, caps)) = subpath_config.rules.iter().find_map(|r| { - let regex = create_external_regex(r.regex.as_str()); + let regex = create_cached_regex(r.regex.as_str()); if regex.is_match(subpath.as_str()) { Some((r, regex.captures(subpath.as_str()).unwrap())) @@ -162,7 +173,7 @@ fn get_external_target( } // external to target template ExternalAdvancedSubpathTarget::Tpl(target) => { - let regex = create_external_regex(r"\$(\d+)"); + let regex = create_cached_regex(r"\$(\d+)"); // replace $1, $2, ... with captured groups let mut replaced = regex @@ -249,7 +260,12 @@ fn do_resolve( // TODO: 临时方案,需要改成删除文件时删 resolve cache 里的内容 // 比如把 util.ts 改名为 util.tsx,目前应该是还有问题的 if resolution.path().exists() { - Ok(ResolverResource::Resolved(ResolvedResource(resolution))) + Ok(ResolverResource::Resolved(ResolvedResource(Resolution { + package_json: resolution.package_json().cloned(), + path: resolution.clone().into_path_buf(), + query: resolution.query().map(|q| q.to_string()), + fragment: resolution.fragment().map(|f| f.to_string()), + }))) } else { Err(anyhow!(ResolveError { path: source.to_string(), diff --git a/crates/mako/src/resolve/resolution.rs b/crates/mako/src/resolve/resolution.rs new file mode 100644 index 000000000..52c93dfd1 --- /dev/null +++ b/crates/mako/src/resolve/resolution.rs @@ -0,0 +1,63 @@ +use std::fmt; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use oxc_resolver::PackageJson; + +#[derive(Clone)] +pub struct Resolution { + pub path: PathBuf, + pub query: Option, + pub fragment: Option, + pub package_json: Option>, +} + +impl Resolution { + /// Returns the path without query and fragment + pub fn path(&self) -> &Path { + &self.path + } + + /// Returns the path without query and fragment + pub fn into_path_buf(self) -> PathBuf { + self.path + } + + /// Returns the path query `?query`, contains the leading `?` + pub fn query(&self) -> Option<&str> { + self.query.as_deref() + } + + /// Returns the path fragment `#fragment`, contains the leading `#` + pub fn fragment(&self) -> Option<&str> { + self.fragment.as_deref() + } + + /// Returns serialized package_json + pub fn package_json(&self) -> Option<&Arc> { + self.package_json.as_ref() + } + + /// Returns the full path with query and fragment + pub fn full_path(&self) -> PathBuf { + let mut path = self.path.clone().into_os_string(); + if let Some(query) = &self.query { + path.push(query); + } + if let Some(fragment) = &self.fragment { + path.push(fragment); + } + PathBuf::from(path) + } +} + +impl fmt::Debug for Resolution { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Resolution") + .field("path", &self.path) + .field("query", &self.query) + .field("fragment", &self.fragment) + .field("package_json", &self.package_json.as_ref().map(|p| &p.path)) + .finish() + } +} diff --git a/crates/mako/src/resolve/resource.rs b/crates/mako/src/resolve/resource.rs index 7de6e08af..6e9219481 100644 --- a/crates/mako/src/resolve/resource.rs +++ b/crates/mako/src/resolve/resource.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use oxc_resolver::Resolution; +use crate::resolve::Resolution; #[derive(Debug, Clone)] pub struct ExternalResource { diff --git a/crates/mako/src/stats.rs b/crates/mako/src/stats.rs index 380c48c4b..48da7b61f 100644 --- a/crates/mako/src/stats.rs +++ b/crates/mako/src/stats.rs @@ -9,7 +9,7 @@ use colored::*; use indexmap::IndexMap; use pathdiff::diff_paths; use serde::Serialize; -use swc_core::common::source_map::Pos; +use swc_core::common::source_map::SmallPos; use crate::compiler::{Compiler, Context}; use crate::features::rsc::{RscClientInfo, RscCssModules}; @@ -94,10 +94,7 @@ impl Compiler { let id = module.id.clone(); // 去拿 module 的文件 size 时,有可能 module 不存在,size 则设为 0 // 场景: xlsx 中引入了 fs 模块 - let size = match file_size(&id) { - Ok(size) => size, - Err(..) => 0, - }; + let size = file_size(&id).unwrap_or_default(); let module = StatsJsonChunkModuleItem { module_type: StatsJsonType::Module("module".to_string()), size, diff --git a/crates/mako/src/utils.rs b/crates/mako/src/utils.rs index 2d47f152c..a469dd3a8 100644 --- a/crates/mako/src/utils.rs +++ b/crates/mako/src/utils.rs @@ -4,12 +4,15 @@ pub mod logger; pub mod profile_gui; #[cfg(test)] pub(crate) mod test_helper; -pub(crate) mod thread_pool; +pub mod thread_pool; pub mod tokio_runtime; +use std::path::Path; + use anyhow::{anyhow, Result}; use base64::engine::general_purpose; use base64::Engine; +use cached::proc_macro::cached; use regex::Regex; pub fn base64_encode>(raw: T) -> String { @@ -50,6 +53,26 @@ pub fn process_req_url(public_path: &str, req_url: &str) -> Result { Ok(req_url.to_string()) } +pub(crate) fn get_pkg_name(root: &Path) -> Option { + let pkg_json_path = root.join("package.json"); + + if pkg_json_path.exists() { + let pkg_json = std::fs::read_to_string(pkg_json_path).unwrap(); + let pkg_json: serde_json::Value = serde_json::from_str(&pkg_json).unwrap(); + + pkg_json + .get("name") + .map(|name| name.as_str().unwrap().to_string()) + } else { + None + } +} + +#[cached(key = "String", convert = r#"{ re.to_string() }"#)] +pub fn create_cached_regex(re: &str) -> Regex { + Regex::new(re).unwrap() +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/mako/src/visitors/async_module.rs b/crates/mako/src/visitors/async_module.rs index 185e794e0..88b0baa3f 100644 --- a/crates/mako/src/visitors/async_module.rs +++ b/crates/mako/src/visitors/async_module.rs @@ -4,13 +4,14 @@ use std::sync::Arc; use swc_core::common::util::take::Take; use swc_core::common::{Mark, DUMMY_SP}; use swc_core::ecma::ast::{ - ArrayLit, AssignExpr, AssignOp, AwaitExpr, BlockStmt, BlockStmtOrExpr, CondExpr, Expr, Ident, - Lit, ModuleItem, ParenExpr, Stmt, VarDeclKind, + ArrayLit, ArrayPat, AssignExpr, AssignOp, AwaitExpr, BlockStmt, BlockStmtOrExpr, CondExpr, + Expr, Ident, Lit, ModuleItem, ParenExpr, Stmt, VarDeclKind, }; use swc_core::ecma::utils::{member_expr, quote_expr, quote_ident, ExprFactory}; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; use crate::ast::utils::is_commonjs_require; +use crate::ast::DUMMY_CTXT; use crate::compiler::Context; use crate::module::{Dependency, ModuleId}; @@ -58,7 +59,8 @@ impl VisitMut for AsyncModule<'_> { && let Some(dep_span) = dep.span && dep_span.contains(str.span) { - let ident_name = quote_ident!(format!("{}{}__", ASYNC_IMPORTED_MODULE, idx)); + let ident_name = + quote_ident!(DUMMY_CTXT, format!("{}{}__", ASYNC_IMPORTED_MODULE, idx)); if !self.async_deps_idents.contains(&ident_name) { self.async_deps_idents.push(ident_name.clone()); @@ -124,17 +126,20 @@ impl VisitMut for AsyncModule<'_> { self.prepend_module_items.push(ModuleItem::Stmt( AssignExpr { op: AssignOp::Assign, - left: ArrayLit { + left: ArrayPat { span: DUMMY_SP, + optional: false, elems: self .async_deps_idents .iter() - .map(|ident| Some(ident.clone().as_arg())) + .map(|ident| Some(ident.clone().into())) .collect(), + type_ann: None, } - .as_pat_or_expr(), + .into(), right: CondExpr { - test: member_expr!(DUMMY_SP, __mako_async_dependencies__.then), + test: member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_async_dependencies__.then) + .into(), cons: ParenExpr { expr: AwaitExpr { span: DUMMY_SP, @@ -170,7 +175,7 @@ impl VisitMut for AsyncModule<'_> { // module, async (handleAsyncDeps, asyncResult) => { }, bool // );` *module_items = vec![ModuleItem::Stmt( - member_expr!(DUMMY_SP, __mako_require__._async) + member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__._async) .as_call( DUMMY_SP, vec![ @@ -183,6 +188,7 @@ impl VisitMut for AsyncModule<'_> { arrow_fn.is_async = true; arrow_fn.body = BlockStmtOrExpr::BlockStmt(BlockStmt { span: DUMMY_SP, + ctxt: DUMMY_CTXT, stmts: module_items .iter() .map(|stmt| stmt.as_stmt().unwrap().clone()) @@ -261,9 +267,7 @@ __mako_require__._async(module, async (handleAsyncDeps, asyncResult)=>{ var __mako_async_dependencies__ = handleAsyncDeps([ _async__mako_imported_module_0__ ]); - [ - _async__mako_imported_module_0__ - ] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; + [_async__mako_imported_module_0__] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; var _async = _interop_require_default._(_async__mako_imported_module_0__); 0, _async.default(1, 2); asyncResult(); @@ -296,10 +300,7 @@ __mako_require__._async(module, async (handleAsyncDeps, asyncResult)=>{ _async__mako_imported_module_0__, _async__mako_imported_module_1__ ]); - [ - _async__mako_imported_module_0__, - _async__mako_imported_module_1__ - ] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; + [_async__mako_imported_module_0__, _async__mako_imported_module_1__] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; var _async = _interop_require_default._(_async__mako_imported_module_0__); var _async_2 = _interop_require_default._(_async__mako_imported_module_1__); 0, _async.default(1, 2); @@ -333,9 +334,7 @@ __mako_require__._async(module, async (handleAsyncDeps, asyncResult)=>{ var __mako_async_dependencies__ = handleAsyncDeps([ _async__mako_imported_module_0__ ]); - [ - _async__mako_imported_module_0__ - ] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; + [_async__mako_imported_module_0__] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; var _async = _interop_require_default._(_export_star._(_async__mako_imported_module_0__, exports)); 0, _async.default(1, 2); asyncResult(); @@ -387,9 +386,7 @@ __mako_require__._async(module, async (handleAsyncDeps, asyncResult)=>{ var __mako_async_dependencies__ = handleAsyncDeps([ _async__mako_imported_module_0__ ]); - [ - _async__mako_imported_module_0__ - ] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; + [_async__mako_imported_module_0__] = __mako_async_dependencies__.then ? (await __mako_async_dependencies__)() : __mako_async_dependencies__; var _miexed_async = _interop_require_default._(_async__mako_imported_module_0__); async.add(1, 2); const async = require('./miexed_async'); diff --git a/crates/mako/src/visitors/common_js.rs b/crates/mako/src/visitors/common_js.rs index 9ef7cd5b0..f22fa771d 100644 --- a/crates/mako/src/visitors/common_js.rs +++ b/crates/mako/src/visitors/common_js.rs @@ -19,22 +19,14 @@ pub struct Commonjs { impl VisitMut for Commonjs { fn visit_mut_module(&mut self, n: &mut Module) { - let mut use_strict = false; - if utils::is_esm(n) { - use_strict = true + let use_strict = if utils::is_esm(n) { + true } else { - for item in n.body.iter() { - if let Some(stmt) = item.as_stmt() { - if stmt.is_directive() { - if stmt.is_use_strict() { - use_strict = true; - } - } else { - break; - } - } - } - } + n.body + .iter() + .take_while(|s| s.directive_continue()) + .any(|s| s.is_use_strict()) + }; n.visit_mut_with(&mut swc_common_js( self.unresolved_mark, diff --git a/crates/mako/src/visitors/css_px2rem.rs b/crates/mako/src/visitors/css_px2rem.rs index c125f2092..de7e4bb3a 100644 --- a/crates/mako/src/visitors/css_px2rem.rs +++ b/crates/mako/src/visitors/css_px2rem.rs @@ -99,7 +99,7 @@ impl VisitMut for Px2Rem { } fn visit_mut_length(&mut self, n: &mut Length) { - if n.unit.value.to_string() == "px" && self.should_transform(n.value.value) { + if n.unit.value == "px" && self.should_transform(n.value.value) { n.value.value /= self.config.root; if self.is_any_in_doublelist() { n.value.value *= 2.0; @@ -126,7 +126,7 @@ impl VisitMut for Px2Rem { // .a { --a-b: var(--c-d, 88px); } fn visit_mut_token(&mut self, t: &mut Token) { if let Token::Dimension(dimension) = t { - if dimension.unit.to_string() == "px" && self.should_transform(dimension.value) { + if dimension.unit == "px" && self.should_transform(dimension.value) { let mut rem_val = dimension.value / self.config.root; if self.is_any_in_doublelist() { rem_val *= 2.0; diff --git a/crates/mako/src/visitors/default_export_namer.rs b/crates/mako/src/visitors/default_export_namer.rs index 1c5449deb..25cc12141 100644 --- a/crates/mako/src/visitors/default_export_namer.rs +++ b/crates/mako/src/visitors/default_export_namer.rs @@ -35,6 +35,7 @@ impl VisitMut for DefaultExportNamer { return_type, type_params, span, + ctxt, .. } = arrow_expr.clone(); *item = ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { @@ -50,6 +51,7 @@ impl VisitMut for DefaultExportNamer { BlockStmtOrExpr::BlockStmt(block_stmt) => block_stmt, BlockStmtOrExpr::Expr(expr) => BlockStmt { span, + ctxt, stmts: vec![Stmt::Return(ReturnStmt { span, arg: Some(expr), @@ -59,6 +61,7 @@ impl VisitMut for DefaultExportNamer { is_async, is_generator, span, + ctxt, return_type, type_params, decorators: vec![], diff --git a/crates/mako/src/visitors/dep_replacer.rs b/crates/mako/src/visitors/dep_replacer.rs index ab18f64e6..ee90a23f7 100644 --- a/crates/mako/src/visitors/dep_replacer.rs +++ b/crates/mako/src/visitors/dep_replacer.rs @@ -11,6 +11,7 @@ use swc_core::ecma::visit::{VisitMut, VisitMutWith}; use crate::ast::file::parse_path; use crate::ast::utils::{is_commonjs_require, is_dynamic_import, is_remote_or_data}; +use crate::ast::DUMMY_CTXT; use crate::compiler::Context; use crate::module::{Dependency, ModuleId}; use crate::visitors::virtual_css_modules::is_css_path; @@ -20,7 +21,6 @@ pub struct DepReplacer<'a> { pub to_replace: &'a DependenciesToReplace, pub context: &'a Arc, pub unresolved_mark: Mark, - pub top_level_mark: Mark, } type ResolvedModuleId = String; @@ -49,18 +49,23 @@ pub fn miss_throw_stmt>(source: T) -> Expr { // e.code = "MODULE_NOT_FOUND" let assign_error = quote_str!("MODULE_NOT_FOUND") - .make_assign_to(AssignOp::Assign, member_expr!(DUMMY_SP, e.code).into()) + .make_assign_to( + AssignOp::Assign, + member_expr!(DUMMY_CTXT, DUMMY_SP, e.code).into(), + ) .into_stmt(); // function() { ...; throw e } let fn_expr = Expr::Fn(FnExpr { - ident: Some(quote_ident!("makoMissingModule")), + ident: Some(quote_ident!(DUMMY_CTXT, "makoMissingModule")), function: Box::new(Function { is_async: false, params: vec![], decorators: vec![], span: DUMMY_SP, + ctxt: DUMMY_CTXT, body: Some(BlockStmt { + ctxt: Default::default(), span: DUMMY_SP, stmts: vec![ decl_error.into(), @@ -144,8 +149,9 @@ impl VisitMut for DepReplacer<'_> { if let Some(chunk) = chunk { let chunk_id = chunk.id.id.clone(); // `import('./xxx.css')` => `__mako_require__.ensure('./xxx.css')` - *expr = member_expr!(DUMMY_SP, __mako_require__.ensure) - .as_call(DUMMY_SP, vec![quote_str!(chunk_id).as_arg()]); + *expr = + member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.ensure) + .as_call(DUMMY_SP, vec![quote_str!(chunk_id).as_arg()]); return; } else { *expr = Expr::Lit(quote_str!("").into()); @@ -198,9 +204,9 @@ pub fn resolve_web_worker_mut(new_expr: &mut NewExpr, unresolved_mark: Mark) -> return None; } - if let box Expr::Ident(Ident { span, sym, .. }) = &mut new_expr.callee { + if let box Expr::Ident(Ident { sym, ctxt, .. }) = &mut new_expr.callee { // `Worker` must be unresolved - if sym == "Worker" && (span.ctxt.outer() == unresolved_mark) { + if sym == "Worker" && (ctxt.outer() == unresolved_mark) { let args = new_expr.args.as_mut().unwrap(); // new Worker(new URL(''), base); @@ -211,8 +217,8 @@ pub fn resolve_web_worker_mut(new_expr: &mut NewExpr, unresolved_mark: Mark) -> return None; } - if let box Expr::Ident(Ident { span, sym, .. }) = &new_expr.callee { - if sym == "URL" && (span.ctxt.outer() == unresolved_mark) { + if let box Expr::Ident(Ident { sym, ctxt, .. }) = &new_expr.callee { + if sym == "URL" && (ctxt.outer() == unresolved_mark) { // new URL(''); let args = new_expr.args.as_mut().unwrap(); if let box Expr::Lit(Lit::Str(ref mut str)) = &mut args[0].expr { @@ -380,7 +386,6 @@ try { to_replace: &DependenciesToReplace { resolved, missing }, context: &test_utils.context, unresolved_mark: ast.unresolved_mark, - top_level_mark: ast.top_level_mark, }; ast.ast.visit_mut_with(&mut visitor); }); diff --git a/crates/mako/src/visitors/dynamic_import.rs b/crates/mako/src/visitors/dynamic_import.rs index 9af78bc09..91014fde8 100644 --- a/crates/mako/src/visitors/dynamic_import.rs +++ b/crates/mako/src/visitors/dynamic_import.rs @@ -10,6 +10,7 @@ use swc_core::ecma::utils::{ use swc_core::ecma::visit::{VisitMut, VisitMutWith}; use crate::ast::utils::{is_dynamic_import, promise_all, require_ensure}; +use crate::ast::DUMMY_CTXT; use crate::compiler::Context; use crate::generate::chunk::ChunkId; use crate::visitors::dep_replacer::DependenciesToReplace; @@ -42,11 +43,7 @@ impl<'a> VisitMut for DynamicImport<'a> { let insert_at = n .body .iter() - .position(|module_item| { - !module_item - .as_stmt() - .map_or(false, |stmt| stmt.is_directive()) - }) + .position(|module_item| !module_item.directive_continue()) .unwrap(); let (id, _) = self @@ -138,18 +135,19 @@ impl<'a> VisitMut for DynamicImport<'a> { .into(), }); - let lazy_require_call = member_expr!(DUMMY_SP, __mako_require__.bind) - .as_call( + let lazy_require_call = + member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.bind).as_call( DUMMY_SP, vec![ quote_ident!("__mako_require__").as_arg(), quote_str!(resolved_source.clone()).as_arg(), ], ); - let dr_call = member_expr!(DUMMY_SP, __mako_require__.dr).as_call( - DUMMY_SP, - vec![self.interop.clone().as_arg(), lazy_require_call.as_arg()], - ); + let dr_call = member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.dr) + .as_call( + DUMMY_SP, + vec![self.interop.clone().as_arg(), lazy_require_call.as_arg()], + ); member_expr!(@EXT, DUMMY_SP, load_promise.into(), then) .as_call(call_expr.span, vec![dr_call.as_arg()]) diff --git a/crates/mako/src/visitors/dynamic_import_to_require.rs b/crates/mako/src/visitors/dynamic_import_to_require.rs index 2992006d0..2890b477d 100644 --- a/crates/mako/src/visitors/dynamic_import_to_require.rs +++ b/crates/mako/src/visitors/dynamic_import_to_require.rs @@ -6,6 +6,8 @@ use swc_core::ecma::utils::{ use swc_core::ecma::visit::{VisitMut, VisitMutWith}; use crate::ast::utils::is_dynamic_import; +use crate::ast::DUMMY_CTXT; + pub struct DynamicImportToRequire { pub unresolved_mark: Mark, changed: bool, @@ -31,11 +33,7 @@ impl VisitMut for DynamicImportToRequire { let insert_at = n .body .iter() - .position(|module_item| { - !module_item - .as_stmt() - .map_or(false, |stmt| stmt.is_directive()) - }) + .position(|module_item| !module_item.directive_continue()) .unwrap(); let require_interop = quote_ident!("__mako_require__").as_call( DUMMY_SP, @@ -62,17 +60,19 @@ impl VisitMut for DynamicImportToRequire { .. } = &mut call_expr.args[0] { - let source_lazy_require = - quote_ident!(DUMMY_SP.apply_mark(self.unresolved_mark), "require") - .as_call(DUMMY_SP, vec![quote_str!(source.value.clone()).as_arg()]) - .into_lazy_arrow(vec![]); + let ctxt = DUMMY_CTXT.apply_mark(self.unresolved_mark); + + let source_lazy_require = quote_ident!(ctxt, "require") + .as_call(DUMMY_SP, vec![quote_str!(source.value.clone()).as_arg()]) + .into_lazy_arrow(vec![]); // Promise.resolve() - let promise_resolve: Box = member_expr!(DUMMY_SP, Promise.resolve) - .as_call(DUMMY_SP, vec![]) - .into(); + let promise_resolve: Box = + member_expr!(DUMMY_CTXT, DUMMY_SP, Promise.resolve) + .as_call(DUMMY_SP, vec![]) + .into(); - let interop_call = quote_ident!(DUMMY_SP, self.interop.as_ref()); + let interop_call = quote_ident!(DUMMY_CTXT, self.interop.as_ref()); let promised_require: Expr = member_expr!(@EXT,DUMMY_SP, promise_resolve, then) .as_call(DUMMY_SP, vec![source_lazy_require.as_arg()]); let interop_require = diff --git a/crates/mako/src/visitors/env_replacer.rs b/crates/mako/src/visitors/env_replacer.rs index 37f691c32..87b873ae8 100644 --- a/crates/mako/src/visitors/env_replacer.rs +++ b/crates/mako/src/visitors/env_replacer.rs @@ -6,8 +6,8 @@ use anyhow::{anyhow, Result}; use serde_json::Value; use swc_core::common::{Mark, Span, DUMMY_SP}; use swc_core::ecma::ast::{ - ArrayLit, Bool, ComputedPropName, Expr, ExprOrSpread, Ident, KeyValueProp, Lit, MemberExpr, - MemberProp, ModuleItem, Null, Number, ObjectLit, Prop, PropOrSpread, Stmt, Str, + ArrayLit, Bool, ComputedPropName, Expr, ExprOrSpread, Ident, IdentName, KeyValueProp, Lit, + MemberExpr, MemberProp, ModuleItem, Null, Number, ObjectLit, Prop, PropOrSpread, Stmt, Str, }; use swc_core::ecma::utils::{quote_ident, ExprExt}; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; @@ -36,9 +36,9 @@ impl EnvReplacer { } impl VisitMut for EnvReplacer { fn visit_mut_expr(&mut self, expr: &mut Expr) { - if let Expr::Ident(Ident { span, .. }) = expr { + if let Expr::Ident(Ident { ctxt, .. }) = expr { // 先判断 env 中的变量名称,是否是上下文中已经存在的变量名称 - if span.ctxt.outer() != self.unresolved_mark { + if ctxt.outer() != self.unresolved_mark { expr.visit_mut_children_with(self); return; } @@ -47,12 +47,11 @@ impl VisitMut for EnvReplacer { match expr { Expr::Member(MemberExpr { obj, prop, .. }) => { let mut member_visit_path = match prop { - MemberProp::Ident(Ident { sym, .. }) => sym.to_string(), + MemberProp::Ident(IdentName { sym, .. }) => sym.to_string(), MemberProp::Computed(ComputedPropName { expr: expr_compute, .. }) => match expr_compute.as_ref() { Expr::Lit(Lit::Str(Str { value, .. })) => value.to_string(), - Expr::Lit(Lit::Num(Number { value, .. })) => value.to_string(), _ => { obj.visit_mut_with(self); @@ -67,7 +66,7 @@ impl VisitMut for EnvReplacer { while let Expr::Member(MemberExpr { obj, prop, .. }) = current_member_obj { match prop { - MemberProp::Ident(Ident { sym, .. }) => { + MemberProp::Ident(IdentName { sym, .. }) => { member_visit_path.push('.'); member_visit_path.push_str(sym.as_ref()); } @@ -94,8 +93,8 @@ impl VisitMut for EnvReplacer { current_member_obj = obj.as_mut(); } - if let Expr::Ident(Ident { sym, span, .. }) = current_member_obj { - if span.ctxt.outer() != self.unresolved_mark { + if let Expr::Ident(Ident { sym, ctxt, .. }) = current_member_obj { + if ctxt.outer() != self.unresolved_mark { return; } member_visit_path.push('.'); diff --git a/crates/mako/src/visitors/fix_symbol_conflict.rs b/crates/mako/src/visitors/fix_symbol_conflict.rs index be5d5ff50..83c44d85f 100644 --- a/crates/mako/src/visitors/fix_symbol_conflict.rs +++ b/crates/mako/src/visitors/fix_symbol_conflict.rs @@ -8,6 +8,8 @@ use swc_core::ecma::ast::{Id, Ident, Module}; use swc_core::ecma::utils::IdentRenamer; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; +use crate::ast::DUMMY_CTXT; + pub(crate) struct FixSymbolConflict { idents_named_symbol: HashSet, top_level_ctxt: SyntaxContext, @@ -17,14 +19,14 @@ impl FixSymbolConflict { pub fn new(top_level_mark: Mark) -> Self { Self { idents_named_symbol: Default::default(), - top_level_ctxt: SyntaxContext::empty().apply_mark(top_level_mark), + top_level_ctxt: DUMMY_CTXT.apply_mark(top_level_mark), } } } impl VisitMut for FixSymbolConflict { fn visit_mut_ident(&mut self, n: &mut Ident) { - if n.sym.eq("Symbol") && n.span.ctxt == self.top_level_ctxt { + if n.sym.eq("Symbol") && n.ctxt == self.top_level_ctxt { self.idents_named_symbol.insert(n.to_id()); } } diff --git a/crates/mako/src/visitors/import_meta_env_replacer.rs b/crates/mako/src/visitors/import_meta_env_replacer.rs index 366a4789e..b8e38931d 100644 --- a/crates/mako/src/visitors/import_meta_env_replacer.rs +++ b/crates/mako/src/visitors/import_meta_env_replacer.rs @@ -1,9 +1,8 @@ use swc_core::common::DUMMY_SP; use swc_core::ecma::ast::{ - Expr, Ident, KeyValueProp, MemberExpr, MemberProp, MetaPropExpr, MetaPropKind, ObjectLit, Prop, - PropOrSpread, + Expr, IdentName, KeyValueProp, MemberExpr, MemberProp, MetaPropExpr, MetaPropKind, ObjectLit, + Prop, PropOrSpread, }; -use swc_core::ecma::atoms::js_word; use swc_core::ecma::utils::{quote_ident, quote_str, ExprFactory}; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; @@ -27,13 +26,9 @@ impl VisitMut for ImportMetaEnvReplacer { kind: MetaPropKind::ImportMeta, .. }), - prop: - MemberProp::Ident(Ident { - sym: js_word!("env"), - .. - }), + prop: MemberProp::Ident(IdentName { sym, .. }), .. - }) => { + }) if sym == "env" => { // replace import.meta.env with "({ MODE: 'production' })" *expr = ObjectLit { props: vec![PropOrSpread::Prop( @@ -54,7 +49,6 @@ impl VisitMut for ImportMetaEnvReplacer { #[cfg(test)] mod tests { - use swc_core::common::GLOBALS; use swc_core::ecma::visit::VisitMutWith; diff --git a/crates/mako/src/visitors/mako_require.rs b/crates/mako/src/visitors/mako_require.rs index dd060d766..02da722cf 100644 --- a/crates/mako/src/visitors/mako_require.rs +++ b/crates/mako/src/visitors/mako_require.rs @@ -16,7 +16,7 @@ impl MakoRequire { fn replace_require(&mut self, ident: &mut Ident) { // replace native require to __mako_require__ except ignored identities if is_ident_undefined(ident, "require", &self.unresolved_mark) { - *ident = Ident::new(MAKO_REQUIRE.into(), ident.span); + *ident = Ident::new(MAKO_REQUIRE.into(), ident.span, ident.ctxt); } } } diff --git a/crates/mako/src/visitors/meta_url_replacer.rs b/crates/mako/src/visitors/meta_url_replacer.rs index 7e822234d..3fd8f95be 100644 --- a/crates/mako/src/visitors/meta_url_replacer.rs +++ b/crates/mako/src/visitors/meta_url_replacer.rs @@ -4,6 +4,7 @@ use swc_core::ecma::utils::member_expr; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; use crate::ast::utils::is_import_meta_url; +use crate::ast::DUMMY_CTXT; pub struct MetaUrlReplacer {} @@ -13,9 +14,9 @@ impl VisitMut for MetaUrlReplacer { // Compatible with workers: self.document ? self.document.baseURI : self.location.href *expr = Expr::Cond(CondExpr { span: DUMMY_SP, - test: member_expr!(DUMMY_SP, self.document), - cons: member_expr!(DUMMY_SP, self.document.baseURI), - alt: member_expr!(DUMMY_SP, self.location.href), + test: member_expr!(DUMMY_CTXT, DUMMY_SP, self.document).into(), + cons: member_expr!(DUMMY_CTXT, DUMMY_SP, self.document.baseURI).into(), + alt: member_expr!(DUMMY_CTXT, DUMMY_SP, self.location.href).into(), }); } diff --git a/crates/mako/src/visitors/new_url_assets.rs b/crates/mako/src/visitors/new_url_assets.rs index 4b672858c..665f6c7e5 100644 --- a/crates/mako/src/visitors/new_url_assets.rs +++ b/crates/mako/src/visitors/new_url_assets.rs @@ -8,7 +8,7 @@ use swc_core::ecma::utils::{member_expr, quote_str}; use swc_core::ecma::visit::VisitMut; use crate::ast::file::File; -use crate::ast::utils; +use crate::ast::{utils, DUMMY_CTXT}; use crate::build::load::Load; use crate::compiler::Context; use crate::config::Platform; @@ -51,8 +51,8 @@ impl NewUrlAssets { Expr::Bin(BinExpr { span: DUMMY_SP, op: BinaryOp::LogicalOr, - left: member_expr!(DUMMY_SP, document.baseURI), - right: member_expr!(DUMMY_SP, self.location.href), + left: member_expr!(DUMMY_CTXT, DUMMY_SP, document.baseURI).into(), + right: member_expr!(DUMMY_CTXT, DUMMY_SP, self.location.href).into(), }) } else { Expr::Lit( @@ -91,7 +91,12 @@ impl VisitMut for NewUrlAssets { Expr::Bin(BinExpr { span: DUMMY_SP, op: BinaryOp::Add, - left: member_expr!(DUMMY_SP, __mako_require__.publicPath), + left: member_expr!( + DUMMY_CTXT, + DUMMY_SP, + __mako_require__.publicPath + ) + .into(), right: Lit::Str(url.into()).into(), }) .into() diff --git a/crates/mako/src/visitors/optimize_define_utils.rs b/crates/mako/src/visitors/optimize_define_utils.rs index 47b836d5d..e0ac7c83a 100644 --- a/crates/mako/src/visitors/optimize_define_utils.rs +++ b/crates/mako/src/visitors/optimize_define_utils.rs @@ -1,8 +1,10 @@ use swc_core::common::{Mark, DUMMY_SP}; use swc_core::ecma::ast::{CallExpr, Expr, ExprOrSpread, ExprStmt, Lit, ModuleItem, Stmt, Str}; -use swc_core::ecma::utils::member_expr; +use swc_core::ecma::utils::{member_expr, ExprFactory}; use swc_core::ecma::visit::VisitMut; +use crate::ast::DUMMY_CTXT; + // TODO: add testcases pub struct OptimizeDefineUtils { pub top_level_mark: Mark, @@ -34,8 +36,12 @@ impl VisitMut for OptimizeDefineUtils { && is_string_lit_arg_with_value(call_expr.args.get(1), "__esModule") && is_obj_lit_arg(call_expr.args.get(2)) { - call_expr.callee = - member_expr!(DUMMY_SP.apply_mark(self.unresolved_mark), require.d).into(); + call_expr.callee = member_expr!( + DUMMY_CTXT.apply_mark(self.unresolved_mark), + DUMMY_SP, + require.d + ) + .as_callee(); } else { return; } @@ -55,8 +61,12 @@ impl VisitMut for OptimizeDefineUtils { && is_string_lit_arg(call_expr.args.get(1)) && is_obj_lit_arg(call_expr.args.get(2)) { - call_expr.callee = - member_expr!(DUMMY_SP.apply_mark(self.unresolved_mark), require.d).into(); + call_expr.callee = member_expr!( + DUMMY_CTXT.apply_mark(self.unresolved_mark), + DUMMY_SP, + require.d + ) + .as_callee(); return; } @@ -66,16 +76,19 @@ impl VisitMut for OptimizeDefineUtils { && call_expr.args.len() == 2 && is_export_arg(call_expr.args.first()) && is_obj_lit_arg(call_expr.args.get(1)) - && callee_ident.sym.to_string() == "_export" + && callee_ident.sym == "_export" // is private ident && !callee_ident - .span .ctxt .outer() .is_descendant_of(self.top_level_mark) { - call_expr.callee = - member_expr!(DUMMY_SP.apply_mark(self.unresolved_mark), require.e).into(); + call_expr.callee = member_expr!( + DUMMY_CTXT.apply_mark(self.unresolved_mark), + DUMMY_SP, + require.e + ) + .as_callee(); return; } } @@ -95,14 +108,14 @@ fn is_object_define(expr: &Expr) -> bool { let is_object = member .obj .as_ident() - .map(|ident| ident.sym.to_string() == "Object") + .map(|ident| ident.sym == "Object") .unwrap_or(false); is_object && member .prop .as_ident() - .map(|ident| ident.sym.to_string() == "defineProperty") + .map(|ident| ident.sym == "defineProperty") .unwrap_or(false) }) .unwrap_or(false) @@ -114,7 +127,7 @@ fn is_export_arg(arg: Option<&ExprOrSpread>) -> bool { && arg .expr .as_ident() - .map(|ident| ident.sym.to_string() == "exports") + .map(|ident| ident.sym == "exports") .unwrap_or(false) }) .unwrap_or(false) @@ -140,7 +153,7 @@ fn is_string_lit_arg_with_value(arg: Option<&ExprOrSpread>, value: &str) -> bool .as_lit() .map(|lit| { if let Lit::Str(str_lit) = lit { - str_lit.value.to_string() == value + str_lit.value == value } else { false } diff --git a/crates/mako/src/visitors/provide.rs b/crates/mako/src/visitors/provide.rs index bdba70854..5b62e70be 100644 --- a/crates/mako/src/visitors/provide.rs +++ b/crates/mako/src/visitors/provide.rs @@ -6,7 +6,9 @@ use swc_core::ecma::ast::{Expr, Ident, MemberExpr, Module, ModuleItem, VarDeclKi use swc_core::ecma::utils::{quote_ident, quote_str, ExprFactory}; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; +use crate::ast::DUMMY_CTXT; use crate::config::Providers; + pub struct Provide { unresolved_mark: Mark, top_level_mark: Mark, @@ -38,7 +40,7 @@ impl VisitMut for Provide { )) } fn visit_mut_ident(&mut self, n: &mut Ident) { - let has_binding = n.span.ctxt.outer() != self.unresolved_mark; + let has_binding = n.ctxt.outer() != self.unresolved_mark; let name = &n.sym.to_string(); let provider = self.providers.get(name); @@ -87,7 +89,7 @@ impl ToTopLevelVars { let mut replaces: HashMap = Default::default(); vars.iter().for_each(|(k, _)| { - let ctxt = SyntaxContext::empty().apply_mark(top_level_mark); + let ctxt = DUMMY_CTXT.apply_mark(top_level_mark); replaces.insert(k.clone(), ctxt); }); @@ -100,9 +102,9 @@ impl ToTopLevelVars { impl VisitMut for ToTopLevelVars { fn visit_mut_ident(&mut self, i: &mut Ident) { - if i.span.ctxt.outer() == self.unresolved_mark { + if i.ctxt.outer() == self.unresolved_mark { if let Some(ctxt) = self.replaces_map.get(&i.sym.to_string()) { - i.span.ctxt = *ctxt; + i.ctxt = *ctxt; } } } diff --git a/crates/mako/src/visitors/public_path_assignment.rs b/crates/mako/src/visitors/public_path_assignment.rs index 97f054128..fc22ebad6 100644 --- a/crates/mako/src/visitors/public_path_assignment.rs +++ b/crates/mako/src/visitors/public_path_assignment.rs @@ -1,26 +1,28 @@ use swc_core::common::{Mark, DUMMY_SP}; -use swc_core::ecma::ast::{AssignExpr, AssignOp, Pat, PatOrExpr}; +use swc_core::ecma::ast::{AssignExpr, AssignOp, BindingIdent, Ident}; use swc_core::ecma::utils::member_expr; use swc_core::ecma::visit::{VisitMut, VisitMutWith}; +use crate::ast::DUMMY_CTXT; + pub struct PublicPathAssignment { pub unresolved_mark: Mark, } impl VisitMut for PublicPathAssignment { fn visit_mut_assign_expr(&mut self, n: &mut AssignExpr) { - if n.op == AssignOp::Assign { - if let PatOrExpr::Pat(box Pat::Ident(ident)) = &n.left { - let sym = ident.sym.as_ref(); - if ident.span.ctxt.outer() == self.unresolved_mark - && (sym == "__webpack_public_path__" || sym == "__mako_public_path__") - { - *n = AssignExpr { - left: PatOrExpr::Expr(member_expr!(DUMMY_SP, __mako_require__.publicPath)), - ..n.clone() - }; - } - } + if n.op == AssignOp::Assign + && let Some(BindingIdent { + id: Ident { sym, ctxt, .. }, + .. + }) = n.left.as_ident() + && (sym == "__webpack_public_path__" || sym == "__mako_public_path__") + && ctxt.outer() == self.unresolved_mark + { + *n = AssignExpr { + left: member_expr!(DUMMY_CTXT, DUMMY_SP, __mako_require__.publicPath).into(), + ..n.clone() + }; } n.visit_mut_children_with(self); } diff --git a/crates/mako/src/visitors/ts_strip.rs b/crates/mako/src/visitors/ts_strip.rs index b4066bfb0..dbcb81bb3 100644 --- a/crates/mako/src/visitors/ts_strip.rs +++ b/crates/mako/src/visitors/ts_strip.rs @@ -6,17 +6,21 @@ use swc_core::ecma::visit::{VisitMut, VisitMutWith}; pub struct TypescriptStrip { top_level_mark: Mark, + unresolved_mark: Mark, } impl VisitMut for TypescriptStrip { fn visit_mut_module(&mut self, n: &mut Module) { let mut p = Program::Module(n.take()); - p.visit_mut_with(&mut strip(self.top_level_mark)); + p.visit_mut_with(&mut strip(self.unresolved_mark, self.top_level_mark)); *n = p.module().unwrap(); } } -pub fn ts_strip(top_level_mark: Mark) -> impl VisitMut { - TypescriptStrip { top_level_mark } +pub fn ts_strip(unresolved_mark: Mark, top_level_mark: Mark) -> impl VisitMut { + TypescriptStrip { + top_level_mark, + unresolved_mark, + } } diff --git a/crates/mako/src/visitors/tsx_strip.rs b/crates/mako/src/visitors/tsx_strip.rs index 0d1d6e801..d8a170c85 100644 --- a/crates/mako/src/visitors/tsx_strip.rs +++ b/crates/mako/src/visitors/tsx_strip.rs @@ -14,6 +14,7 @@ pub struct TsxStrip { cm: Arc, context: Arc, top_level_mark: Mark, + unresolved_mark: Mark, } impl VisitMut for TsxStrip { @@ -29,6 +30,7 @@ impl VisitMut for TsxStrip { Default::default(), tsx_config, comments, + self.unresolved_mark, self.top_level_mark, )); *n = p.module().unwrap(); @@ -39,10 +41,12 @@ pub fn tsx_strip( cm: Arc, context: Arc, top_level_mark: Mark, + unresolved_mark: Mark, ) -> impl VisitMut { TsxStrip { cm, context, top_level_mark, + unresolved_mark, } } diff --git a/crates/svgr-rs/Cargo.toml b/crates/svgr-rs/Cargo.toml new file mode 100644 index 000000000..fecb95be5 --- /dev/null +++ b/crates/svgr-rs/Cargo.toml @@ -0,0 +1,41 @@ +[package] +authors = ["SyMind "] +description = "A tool to transform SVG into React components" +name = "svgr-rs" +edition = "2021" +license = "MIT" +repository = "https://github.com/svg-rust/svgr-rs.git" +version = "0.1.3" + +[features] +node = ["dep:napi", "dep:napi-derive"] + +[dependencies] +# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix +napi = { version = "2.12.0", default-features = false, features = ["async", "napi4"], optional = true } +napi-derive = { version = "2.12.2", optional = true } + +clap = { version = "4.2.0", features = ["derive"] } +html-escape = "0.2.13" +linked-hash-map = { version = "0.5.6", features = ["serde_impl"] } +linked_hash_set = "0.1.4" +regex = { workspace = true } +serde = { workspace = true, features = ["derive"] } +swc_core = { workspace = true, features = [ + "bundler", + "common_concurrent", + "ecma_ast", + "ecma_ast_serde", + "ecma_codegen", + "ecma_loader", + "ecma_parser", + "ecma_transforms", + "ecma_visit", +] } +swc_xml = "0.17.0" +thiserror = "1.0.56" + +testing = { version = "0.38.1" } + +[profile.release] +lto = true diff --git a/crates/svgr-rs/__fixture__/basic/input.svg b/crates/svgr-rs/__fixture__/basic/input.svg new file mode 100644 index 000000000..478f6e682 --- /dev/null +++ b/crates/svgr-rs/__fixture__/basic/input.svg @@ -0,0 +1,13 @@ + + + + Dismiss + Created with Sketch. + + + + + + + + diff --git a/crates/svgr-rs/__fixture__/basic/output.jsx b/crates/svgr-rs/__fixture__/basic/output.jsx new file mode 100644 index 000000000..302e28a67 --- /dev/null +++ b/crates/svgr-rs/__fixture__/basic/output.jsx @@ -0,0 +1 @@ +{"Dismiss"}{"Created with Sketch."}; diff --git a/crates/svgr-rs/__fixture__/should-handle-spaces-and-tab/input.svg b/crates/svgr-rs/__fixture__/should-handle-spaces-and-tab/input.svg new file mode 100644 index 000000000..1f3b04f46 --- /dev/null +++ b/crates/svgr-rs/__fixture__/should-handle-spaces-and-tab/input.svg @@ -0,0 +1,11 @@ + + + diff --git a/crates/svgr-rs/__fixture__/should-handle-spaces-and-tab/output.jsx b/crates/svgr-rs/__fixture__/should-handle-spaces-and-tab/output.jsx new file mode 100644 index 000000000..0cd3a2605 --- /dev/null +++ b/crates/svgr-rs/__fixture__/should-handle-spaces-and-tab/output.jsx @@ -0,0 +1 @@ +; diff --git a/crates/svgr-rs/src/add_jsx_attribute.rs b/crates/svgr-rs/src/add_jsx_attribute.rs new file mode 100644 index 000000000..5ca4016c2 --- /dev/null +++ b/crates/svgr-rs/src/add_jsx_attribute.rs @@ -0,0 +1,368 @@ +use swc_core::common::{SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; +use swc_core::ecma::visit::VisitMut; + +use super::core; + +pub enum AttributePosition { + Start, + End, +} + +#[derive(Default)] +pub struct Attribute { + pub name: String, + pub value: Option, + pub spread: bool, + pub literal: bool, + pub position: Option, +} + +pub struct Visitor { + elements: Vec, + attributes: Vec, +} + +impl Visitor { + pub fn new(config: &core::config::Config) -> Self { + let mut attributes = Vec::new(); + + if let Some(svg_props) = &config.svg_props { + for (k, v) in svg_props { + let attr = svg_prop_to_attr(k, v); + attributes.push(attr); + } + } + + let _ref = config._ref.unwrap_or(false); + if _ref { + attributes.push(Attribute { + name: "ref".to_string(), + value: Some("ref".to_string()), + literal: true, + ..Default::default() + }); + } + + let title_prop = config.title_prop.unwrap_or(false); + if title_prop { + attributes.push(Attribute { + name: "aria-labelledby".to_string(), + value: Some("titleId".to_string()), + literal: true, + ..Default::default() + }); + } + + let desc_prop = config.desc_prop.unwrap_or(false); + if desc_prop { + attributes.push(Attribute { + name: "aria-describedby".to_string(), + value: Some("descId".to_string()), + literal: true, + ..Default::default() + }); + } + + let expand_props = match config.expand_props { + core::config::ExpandProps::Bool(b) => b, + _ => true, + }; + let position = match config.expand_props { + core::config::ExpandProps::Start => Some(AttributePosition::Start), + core::config::ExpandProps::End => Some(AttributePosition::End), + _ => None, + }; + if expand_props { + attributes.push(Attribute { + name: "props".to_string(), + spread: true, + position, + ..Default::default() + }); + } + + Self { + elements: vec!["svg".to_string(), "Svg".to_string()], + attributes, + } + } +} + +impl VisitMut for Visitor { + fn visit_mut_jsx_opening_element(&mut self, n: &mut JSXOpeningElement) { + if let JSXElementName::Ident(ident) = &n.name { + if !self.elements.contains(&ident.sym.to_string()) { + return; + } + } else { + return; + } + + for attribute in self.attributes.iter() { + let Attribute { + name, + value, + spread, + literal, + position, + } = attribute; + + let position = match position { + Some(position) => position, + None => &AttributePosition::End, + }; + + let new_attr = get_attr(*spread, name, value.as_ref(), *literal); + + let is_equal_attr = |attr: &JSXAttrOrSpread| -> bool { + if *spread { + if let JSXAttrOrSpread::SpreadElement(spread) = attr { + if let Expr::Ident(ident) = spread.expr.as_ref() { + return ident.sym == *name; + } + } + false + } else { + if let JSXAttrOrSpread::JSXAttr(attr) = attr { + if let JSXAttrName::Ident(ident) = &attr.name { + return ident.sym == *name; + } + } + false + } + }; + + let replaced = n.attrs.clone().iter().enumerate().any(|(index, attr)| { + if !is_equal_attr(attr) { + return false; + } + n.attrs[index] = new_attr.clone(); + true + }); + + if !replaced { + match position { + AttributePosition::Start => { + n.attrs.insert(0, new_attr); + } + AttributePosition::End => { + n.attrs.push(new_attr); + } + } + } + } + } +} + +fn get_attr(spread: bool, name: &str, value: Option<&String>, literal: bool) -> JSXAttrOrSpread { + if spread { + JSXAttrOrSpread::SpreadElement(SpreadElement { + dot3_token: DUMMY_SP, + expr: Box::new(Expr::Ident(Ident { + sym: name.to_string().into(), + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + optional: false, + })), + }) + } else { + JSXAttrOrSpread::JSXAttr(JSXAttr { + span: DUMMY_SP, + name: JSXAttrName::Ident(IdentName { + sym: name.to_string().into(), + span: DUMMY_SP, + }), + value: get_attr_value(literal, value), + }) + } +} + +fn get_attr_value(literal: bool, attr_value: Option<&String>) -> Option { + match attr_value { + Some(value) => { + if literal { + Some(JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Ident(Ident { + sym: value.to_string().into(), + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + optional: false, + }))), + })) + } else { + Some(JSXAttrValue::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: value.to_string().into(), + raw: None, + }))) + } + } + None => None, + } +} + +fn svg_prop_to_attr(key: &str, value: &str) -> Attribute { + let literal = value.starts_with('{') && value.ends_with('}'); + let str = if literal { + &value[1..value.len() - 1] + } else { + value + }; + Attribute { + name: key.to_string(), + value: Some(str.to_string()), + literal, + ..Default::default() + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::ast::*; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser::lexer::Lexer; + use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax}; + use swc_core::ecma::visit::{as_folder, FoldWith}; + + use super::*; + + pub struct Options { + elements: Vec, + attributes: Vec, + } + + fn code_test(input: &str, opts: Options, expected: &str) { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + decorators: true, + jsx: true, + ..Default::default() + }), + EsVersion::EsNext, + StringInput::from(&*fm), + None, + ); + + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().unwrap(); + + let module = module.fold_with(&mut as_folder(Visitor { + elements: opts.elements, + attributes: opts.attributes, + })); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "", &mut buf, None), + }; + emitter.emit_module(&module).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + #[test] + fn should_add_simple_attribute() { + code_test( + r#"
;"#, + Options { + elements: vec!["div".to_string()], + attributes: vec![Attribute { + name: "disabled".to_string(), + ..Default::default() + }], + }, + r#"
;"#, + ); + } + + #[test] + fn should_add_attribute_with_value() { + code_test( + r#"
;"#, + Options { + elements: vec!["div".to_string()], + attributes: vec![Attribute { + name: "disabled".to_string(), + value: Some("true".to_string()), + ..Default::default() + }], + }, + r#"
;"#, + ); + } + + #[test] + fn should_add_literal_attribute() { + code_test( + r#"
;"#, + Options { + elements: vec!["div".to_string()], + attributes: vec![Attribute { + name: "ref".to_string(), + value: Some("ref".to_string()), + literal: true, + ..Default::default() + }], + }, + r#"
;"#, + ); + + code_test( + r#"
;"#, + Options { + elements: vec!["div".to_string()], + attributes: vec![Attribute { + name: "ref".to_string(), + value: Some("ref ? ref : null".to_string()), + literal: true, + ..Default::default() + }], + }, + r#"
;"#, + ); + } + + #[test] + fn should_add_spread_attribute() { + code_test( + r#"
;"#, + Options { + elements: vec!["div".to_string()], + attributes: vec![Attribute { + name: "props".to_string(), + position: Some(AttributePosition::Start), + spread: true, + ..Default::default() + }], + }, + r#"
;"#, + ); + + code_test( + r#"
;"#, + Options { + elements: vec!["span".to_string()], + attributes: vec![Attribute { + name: "props".to_string(), + position: Some(AttributePosition::End), + spread: true, + ..Default::default() + }], + }, + r#"
;"#, + ); + } +} diff --git a/crates/svgr-rs/src/core/config.rs b/crates/svgr-rs/src/core/config.rs new file mode 100644 index 000000000..d8f297e02 --- /dev/null +++ b/crates/svgr-rs/src/core/config.rs @@ -0,0 +1,186 @@ +use linked_hash_map::LinkedHashMap; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum Icon { + Bool(bool), + Str(String), + Num(f64), +} + +impl Default for Icon { + fn default() -> Self { + Icon::Bool(false) + } +} + +// Untagged enums with empty variants (de)serialize in unintuitive ways +// here: https://github.com/serde-rs/serde/issues/1560 +macro_rules! named_unit_variant { + ($variant:ident) => { + pub mod $variant { + pub fn serialize(serializer: S) -> Result + where + S: serde::Serializer, + { + let s = stringify!($variant).replace("_", "-"); + serializer.serialize_str(&s) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result<(), D::Error> + where + D: serde::Deserializer<'de>, + { + struct V; + impl<'de> serde::de::Visitor<'de> for V { + type Value = (); + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let mut s = String::new(); + s.push_str("\""); + s.push_str(stringify!($variant).replace("_", "-").as_str()); + s.push_str("\""); + f.write_str(&s) + } + fn visit_str(self, value: &str) -> Result { + let s = stringify!($variant).replace("_", "-"); + if value == s { + Ok(()) + } else { + Err(E::invalid_value(serde::de::Unexpected::Str(value), &self)) + } + } + } + deserializer.deserialize_str(V) + } + } + }; +} + +mod strings { + named_unit_variant!(start); + named_unit_variant!(end); + named_unit_variant!(classic); + named_unit_variant!(classic_preact); + named_unit_variant!(automatic); +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[serde(untagged)] +pub enum ExpandProps { + Bool(bool), + #[serde(with = "strings::start")] + Start, + #[serde(with = "strings::end")] + #[default] + End, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum JSXRuntime { + #[serde(with = "strings::classic")] + Classic, + #[serde(with = "strings::classic_preact")] + ClassicPreact, + #[serde(with = "strings::automatic")] + Automatic, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct JSXRuntimeImport { + pub source: String, + pub namespace: Option, + pub default_specifier: Option, + pub specifiers: Option>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum ExportType { + Named, + Default, +} + +/// The options used to transform the SVG. +#[derive(Debug, Clone, Default, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Config { + /// Setting this to `true` will forward ref to the root SVG tag. + #[serde(default)] + #[serde(rename(serialize = "ref"))] + pub _ref: Option, + + /// Add title tag via title property. + /// If title_prop is set to true and no title is provided at render time, this will fallback to an existing title element in the svg if exists. + #[serde(default)] + pub title_prop: Option, + + /// Add desc tag via desc property. + /// If desc_prop is set to true and no description is provided at render time, this will fallback to an existing desc element in the svg if exists. + #[serde(default)] + pub desc_prop: Option, + + /// All properties given to component will be forwarded on SVG tag. + /// Possible values: "start", "end" or false. + #[serde(default)] + pub expand_props: ExpandProps, + + /// Keep `width` and `height` attributes from the root SVG tag. + /// Removal is guaranteed if `dimensions: false`, unlike the `remove_dimensions: true` SVGO plugin option which also generates a `viewBox` from the dimensions if no `viewBox` is present. + #[serde(default)] + pub dimensions: Option, + + /// Replace SVG `width` and `height` by a custom value. + /// If value is omitted, it uses `1em` in order to make SVG size inherits from text size. + #[serde(default)] + pub icon: Option, + + /// Modify all SVG nodes with uppercase and use a specific template with `react-native-svg` imports. + /// All unsupported nodes will be removed. + #[serde(default)] + pub native: Option, + + /// Add props to the root SVG tag. + #[serde(default)] + // Deserialize object/map while maintaining order + // here: https://github.com/serde-rs/serde/issues/269 + pub svg_props: Option>, + + /// Generates `.tsx` files with TypeScript typings. + #[serde(default)] + pub typescript: Option, + + /// Setting this to `true` will wrap the exported component in `React.memo`. + #[serde(default)] + pub memo: Option, + + /// Replace an attribute value by an other. + /// The main usage of this option is to change an icon color to "currentColor" in order to inherit from text color. + #[serde(default)] + pub replace_attr_values: Option>, + + /// Specify a JSX runtime to use. + /// * "classic": adds `import * as React from 'react'` on the top of file + /// * "automatic": do not add anything + /// * "classic-preact": adds `import { h } from 'preact'` on the top of file + #[serde(default)] + pub jsx_runtime: Option, + + /// Specify a custom JSX runtime source to use. Allows to customize the import added at the top of generated file. + #[serde(default)] + pub jsx_runtime_import: Option, + + /// The named export defaults to `ReactComponent`, can be customized with the `named_export` option. + #[serde(default = "default_named_export")] + pub named_export: String, + + /// If you prefer named export in any case, you may set the `export_type` option to `named`. + #[serde(default)] + pub export_type: Option, +} + +fn default_named_export() -> String { + "ReactComponent".to_string() +} diff --git a/crates/svgr-rs/src/core/mod.rs b/crates/svgr-rs/src/core/mod.rs new file mode 100644 index 000000000..0b0fd7ebb --- /dev/null +++ b/crates/svgr-rs/src/core/mod.rs @@ -0,0 +1,2 @@ +pub mod config; +pub mod state; diff --git a/crates/svgr-rs/src/core/state.rs b/crates/svgr-rs/src/core/state.rs new file mode 100644 index 000000000..7d9633d3d --- /dev/null +++ b/crates/svgr-rs/src/core/state.rs @@ -0,0 +1,225 @@ +use std::path::Path; + +use regex::Regex; + +#[cfg(feature = "node")] +#[napi(object)] +#[derive(Debug, Clone, Default)] +pub struct Caller { + pub name: Option, + pub previous_export: Option, +} + +#[cfg(not(feature = "node"))] +#[derive(Debug, Clone, Default)] +pub struct Caller { + pub name: Option, + pub previous_export: Option, +} + +/// The state linked to the transformation. +#[cfg(feature = "node")] +#[napi(object, js_name = "State")] +pub struct Config { + /// The name of the file that is generated, mainly used to find runtime config file to apply. + pub file_path: Option, + + /// The name of the component that will be used in the generated component. + pub component_name: Option, + + /// If you create a tool based on SVGR, it is always better to specify `state.caller`. + /// It permits the inter-operability betweens plugins. + /// If someone create a SVGR plugin it could adapt it specifically to your tool. + pub caller: Option, +} + +impl Default for Config { + fn default() -> Self { + Config { + file_path: None, + component_name: Some("SvgComponent".to_string()), + caller: None, + } + } +} + +#[cfg(not(feature = "node"))] +pub struct Config { + pub file_path: Option, + pub component_name: Option, + pub caller: Option, +} + +#[derive(Debug)] +pub struct InternalConfig { + #[allow(dead_code)] + pub file_path: Option, + pub component_name: String, + pub caller: Option, +} + +impl Default for InternalConfig { + fn default() -> Self { + InternalConfig { + file_path: None, + component_name: "SvgComponent".to_string(), + caller: None, + } + } +} + +fn uppercase_first_letter(s: &str) -> String { + let mut cs = s.chars(); + match cs.next() { + None => String::new(), + Some(f) => f.to_uppercase().chain(cs).collect(), + } +} + +const IDENTIFIER: &str = r"([\p{Alpha}\p{N}_]|$)"; +const SEPARATORS: &str = r"[_.\- ]+"; + +fn pascal_case(input: &str) -> String { + let separators_and_identifier = + Regex::new(format!("{}{}", SEPARATORS, IDENTIFIER).as_str()).unwrap(); + let numbers_and_identifier = Regex::new(format!("(\\d+){}", IDENTIFIER).as_str()).unwrap(); + let result = separators_and_identifier + .replace_all(input, |caps: ®ex::Captures| { + let identifier = caps.get(1).unwrap().as_str(); + identifier.to_uppercase() + }) + .to_string(); + let result = numbers_and_identifier + .replace_all(&result, |caps: ®ex::Captures| { + let num = caps.get(1).unwrap().as_str(); + let identifier = caps.get(2).unwrap().as_str(); + format!("{}{}", num, identifier.to_uppercase()) + }) + .to_string(); + uppercase_first_letter(&result) +} + +fn get_component_name(file_path: &str) -> String { + let valid_char_regex = Regex::new(r"[^a-zA-Z0-9 _-]").unwrap(); + let file_name = valid_char_regex + .replace_all( + Path::new(file_path) + .file_prefix() + .unwrap() + .to_str() + .unwrap(), + "", + ) + .to_string(); + let pascal_case_file_name = pascal_case(&file_name); + format!("Svg{}", pascal_case_file_name) +} + +pub fn expand_state(state: &Config) -> InternalConfig { + InternalConfig { + file_path: state.file_path.clone(), + component_name: match state.component_name.clone() { + Some(component_name) => component_name, + None => match state.file_path.clone() { + None => "SvgComponent".to_string(), + Some(path) => get_component_name(&path), + }, + }, + caller: state.caller.clone(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1() { + let internal_config = expand_state(&Default::default()); + assert_eq!(internal_config.component_name, "SvgComponent"); + } + + #[test] + fn test_2() { + let input = Config { + file_path: Some("hello.svg".to_string()), + component_name: None, + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "hello.svg"); + assert_eq!(internal_config.component_name, "SvgHello"); + } + + #[test] + fn test_3() { + let input = Config { + file_path: Some("hello-you.svg".to_string()), + component_name: None, + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "hello-you.svg"); + assert_eq!(internal_config.component_name, "SvgHelloYou"); + } + + #[test] + fn test_4() { + let input = Config { + file_path: Some("hello_you.svg".to_string()), + component_name: None, + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "hello_you.svg"); + assert_eq!(internal_config.component_name, "SvgHelloYou"); + } + + #[test] + fn test_5() { + let input = Config { + file_path: Some("1_big_svg.svg".to_string()), + component_name: None, + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "1_big_svg.svg"); + assert_eq!(internal_config.component_name, "Svg1BigSvg"); + } + + #[test] + fn test_6() { + let input = Config { + file_path: Some("a&b~c-d_e.svg".to_string()), + component_name: None, + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "a&b~c-d_e.svg"); + assert_eq!(internal_config.component_name, "SvgAbcDE"); + } + + #[test] + fn test_7() { + let input = Config { + file_path: Some("Arrow up.svg".to_string()), + component_name: None, + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "Arrow up.svg"); + assert_eq!(internal_config.component_name, "SvgArrowUp"); + } + + #[test] + fn test_8() { + let input = Config { + file_path: Some("Arrow up.svg".to_string()), + component_name: Some("MyComponent".to_string()), + caller: None, + }; + let internal_config = expand_state(&input); + assert_eq!(internal_config.file_path.unwrap(), "Arrow up.svg"); + assert_eq!(internal_config.component_name, "MyComponent"); + } +} diff --git a/crates/svgr-rs/src/error.rs b/crates/svgr-rs/src/error.rs new file mode 100644 index 000000000..c9bb99d3e --- /dev/null +++ b/crates/svgr-rs/src/error.rs @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum SvgrError { + #[error("failed to parse SVG: {0}")] + Parse(String), + #[error("this is invalid SVG")] + InvalidSvg, + #[error("invalid configuration option: {0}")] + Configuration(String), +} diff --git a/crates/svgr-rs/src/hast_to_swc_ast/decode_xml.rs b/crates/svgr-rs/src/hast_to_swc_ast/decode_xml.rs new file mode 100644 index 000000000..cf14af172 --- /dev/null +++ b/crates/svgr-rs/src/hast_to_swc_ast/decode_xml.rs @@ -0,0 +1,33 @@ +pub fn decode_xml(s: &str) -> String { + let mut decoded = String::new(); + html_escape::decode_html_entities_to_string(s, &mut decoded); + decoded +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn escape_xml_text() { + let test_cases = vec![ + ("&", "&"), + ("'", "'"), + (""", "\""), + (">", ">"), + ("<", "<"), + ("&中文", "&中文"), + ("&amp;", "&"), + ("&#38;", "&"), + ("&#x26;", "&"), + ("&#38;", "&"), + ("&#38;", "&"), + (":", ":"), + ("&>", "&>"), + ("id=770&#anchor", "id=770&#anchor"), + ]; + test_cases.into_iter().for_each(|(input, expected)| { + assert_eq!(decode_xml(input), expected); + }); + } +} diff --git a/crates/svgr-rs/src/hast_to_swc_ast/mappings.rs b/crates/svgr-rs/src/hast_to_swc_ast/mappings.rs new file mode 100644 index 000000000..91c4d72b7 --- /dev/null +++ b/crates/svgr-rs/src/hast_to_swc_ast/mappings.rs @@ -0,0 +1,492 @@ +use std::collections::HashMap; + +// From https://raw.githubusercontent.com/facebook/react/master/packages/react-dom/src/shared/possibleStandardNames.js +pub fn create_attr_mappings() -> HashMap<&'static str, &'static str> { + HashMap::from([ + // HTML + ("accept", "accept"), + ("acceptcharset", "acceptCharset"), + ("accept-charset", "acceptCharset"), + ("accesskey", "accessKey"), + ("action", "action"), + ("allowfullscreen", "allowFullScreen"), + ("alt", "alt"), + ("as", "as"), + ("async", "async"), + ("autocapitalize", "autoCapitalize"), + ("autocomplete", "autoComplete"), + ("autocorrect", "autoCorrect"), + ("autofocus", "autoFocus"), + ("autoplay", "autoPlay"), + ("autosave", "autoSave"), + ("capture", "capture"), + ("cellpadding", "cellPadding"), + ("cellspacing", "cellSpacing"), + ("challenge", "challenge"), + ("charset", "charSet"), + ("checked", "checked"), + ("children", "children"), + ("cite", "cite"), + ("class", "className"), + ("classid", "classID"), + ("classname", "className"), + ("cols", "cols"), + ("colspan", "colSpan"), + ("content", "content"), + ("contenteditable", "contentEditable"), + ("contextmenu", "contextMenu"), + ("controls", "controls"), + ("controlslist", "controlsList"), + ("coords", "coords"), + ("crossorigin", "crossOrigin"), + ("dangerouslysetinnerhtml", "dangerouslySetInnerHTML"), + ("data", "data"), + ("datetime", "dateTime"), + ("default", "default"), + ("defaultchecked", "defaultChecked"), + ("defaultvalue", "defaultValue"), + ("defer", "defer"), + ("dir", "dir"), + ("disabled", "disabled"), + ("download", "download"), + ("draggable", "draggable"), + ("enctype", "encType"), + ("for", "htmlFor"), + ("form", "form"), + ("formmethod", "formMethod"), + ("formaction", "formAction"), + ("formenctype", "formEncType"), + ("formnovalidate", "formNoValidate"), + ("formtarget", "formTarget"), + ("frameborder", "frameBorder"), + ("headers", "headers"), + ("height", "height"), + ("hidden", "hidden"), + ("high", "high"), + ("href", "href"), + ("hreflang", "hrefLang"), + ("htmlfor", "htmlFor"), + ("httpequiv", "httpEquiv"), + ("http-equiv'", "httpEquiv"), + ("icon", "icon"), + ("id", "id"), + ("innerhtml", "innerHTML"), + ("inputmode", "inputMode"), + ("integrity", "integrity"), + ("is", "is"), + ("itemid", "itemID"), + ("itemprop", "itemProp"), + ("itemref", "itemRef"), + ("itemscope", "itemScope"), + ("itemtype", "itemType"), + ("keyparams", "keyParams"), + ("keytype", "keyType"), + ("kind", "kind"), + ("label", "label"), + ("lang", "lang"), + ("list", "list"), + ("loop", "loop"), + ("low", "low"), + ("manifest", "manifest"), + ("marginwidth", "marginWidth"), + ("marginheight", "marginHeight"), + ("max", "max"), + ("maxlength", "maxLength"), + ("media", "media"), + ("mediagroup", "mediaGroup"), + ("method", "method"), + ("min", "min"), + ("minlength", "minLength"), + ("multiple", "multiple"), + ("muted", "muted"), + ("name", "name"), + ("nomodule", "noModule"), + ("nonce", "nonce"), + ("novalidate", "noValidate"), + ("open", "open"), + ("optimum", "optimum"), + ("pattern", "pattern"), + ("placeholder", "placeholder"), + ("playsinline", "playsInline"), + ("poster", "poster"), + ("preload", "preload"), + ("profile", "profile"), + ("radiogroup", "radioGroup"), + ("readonly", "readOnly"), + ("referrerpolicy", "referrerPolicy"), + ("rel", "rel"), + ("required", "required"), + ("reversed", "reversed"), + ("role", "role"), + ("rows", "rows"), + ("rowspan", "rowSpan"), + ("sandbox", "sandbox"), + ("scope", "scope"), + ("scoped", "scoped"), + ("scrolling", "scrolling"), + ("seamless", "seamless"), + ("selected", "selected"), + ("shape", "shape"), + ("size", "size"), + ("sizes", "sizes"), + ("span", "span"), + ("spellcheck", "spellCheck"), + ("src", "src"), + ("srcdoc", "srcDoc"), + ("srclang", "srcLang"), + ("srcset", "srcSet"), + ("start", "start"), + ("step", "step"), + ("style", "style"), + ("summary", "summary"), + ("tabindex", "tabIndex"), + ("target", "target"), + ("title", "title"), + ("type", "type"), + ("usemap", "useMap"), + ("value", "value"), + ("width", "width"), + ("wmode", "wmode"), + ("wrap", "wrap"), + // SVG + ("about", "about"), + ("accentheight", "accentHeight"), + ("accent-height", "accentHeight"), + ("accumulate", "accumulate"), + ("additive", "additive"), + ("alignmentbaseline", "alignmentBaseline"), + ("alignment-baseline", "alignmentBaseline"), + ("allowreorder", "allowReorder"), + ("alphabetic", "alphabetic"), + ("amplitude", "amplitude"), + ("arabicform", "arabicForm"), + ("arabic-form", "arabicForm"), + ("ascent", "ascent"), + ("attributename", "attributeName"), + ("attributetype", "attributeType"), + ("autoreverse", "autoReverse"), + ("azimuth", "azimuth"), + ("basefrequency", "baseFrequency"), + ("baselineshift", "baselineShift"), + ("baseline-shift", "baselineShift"), + ("baseprofile", "baseProfile"), + ("bbox", "bbox"), + ("begin", "begin"), + ("bias", "bias"), + ("by", "by"), + ("calcmode", "calcMode"), + ("capheight", "capHeight"), + ("cap-height", "capHeight"), + ("clip", "clip"), + ("clippath", "clipPath"), + ("clip-path", "clipPath"), + ("clippathunits", "clipPathUnits"), + ("cliprule", "clipRule"), + ("clip-rule", "clipRule"), + ("color", "color"), + ("colorinterpolation", "colorInterpolation"), + ("color-interpolation", "colorInterpolation"), + ("colorinterpolationfilters", "colorInterpolationFilters"), + ("color-interpolation-filters", "colorInterpolationFilters"), + ("colorprofile", "colorProfile"), + ("color-profile", "colorProfile"), + ("colorrendering", "colorRendering"), + ("color-rendering", "colorRendering"), + ("contentscripttype", "contentScriptType"), + ("contentstyletype", "contentStyleType"), + ("cursor", "cursor"), + ("cx", "cx"), + ("cy", "cy"), + ("d", "d"), + ("datatype", "datatype"), + ("decelerate", "decelerate"), + ("descent", "descent"), + ("diffuseconstant", "diffuseConstant"), + ("direction", "direction"), + ("display", "display"), + ("divisor", "divisor"), + ("dominantbaseline", "dominantBaseline"), + ("dominant-baseline", "dominantBaseline"), + ("dur", "dur"), + ("dx", "dx"), + ("dy", "dy"), + ("edgemode", "edgeMode"), + ("elevation", "elevation"), + ("enablebackground", "enableBackground"), + ("enable-background", "enableBackground"), + ("end", "end"), + ("exponent", "exponent"), + ("externalresourcesrequired", "externalResourcesRequired"), + ("fill", "fill"), + ("fillopacity", "fillOpacity"), + ("fill-opacity", "fillOpacity"), + ("fillrule", "fillRule"), + ("fill-rule", "fillRule"), + ("filter", "filter"), + ("filterres", "filterRes"), + ("filterunits", "filterUnits"), + ("floodopacity", "floodOpacity"), + ("flood-opacity", "floodOpacity"), + ("floodcolor", "floodColor"), + ("flood-color", "floodColor"), + ("focusable", "focusable"), + ("fontfamily", "fontFamily"), + ("font-family", "fontFamily"), + ("fontsize", "fontSize"), + ("font-size", "fontSize"), + ("fontsizeadjust", "fontSizeAdjust"), + ("font-size-adjust", "fontSizeAdjust"), + ("fontstretch", "fontStretch"), + ("font-stretch", "fontStretch"), + ("fontstyle", "fontStyle"), + ("font-style", "fontStyle"), + ("fontvariant", "fontVariant"), + ("font-variant", "fontVariant"), + ("fontweight", "fontWeight"), + ("font-weight", "fontWeight"), + ("format", "format"), + ("from", "from"), + ("fx", "fx"), + ("fy", "fy"), + ("g1", "g1"), + ("g2", "g2"), + ("glyphname", "glyphName"), + ("glyph-name", "glyphName"), + ("glyphorientationhorizontal", "glyphOrientationHorizontal"), + ("glyph-orientation-horizontal", "glyphOrientationHorizontal"), + ("glyphorientationvertical", "glyphOrientationVertical"), + ("glyph-orientation-vertical", "glyphOrientationVertical"), + ("glyphref", "glyphRef"), + ("gradienttransform", "gradientTransform"), + ("gradientunits", "gradientUnits"), + ("hanging", "hanging"), + ("horizadvx", "horizAdvX"), + ("horiz-adv-x", "horizAdvX"), + ("horizoriginx", "horizOriginX"), + ("horiz-origin-x", "horizOriginX"), + ("ideographic", "ideographic"), + ("imagerendering", "imageRendering"), + ("image-rendering", "imageRendering"), + ("in2", "in2"), + ("in", "in"), + ("inlist", "inlist"), + ("intercept", "intercept"), + ("k1", "k1"), + ("k2", "k2"), + ("k3", "k3"), + ("k4", "k4"), + ("k", "k"), + ("kernelmatrix", "kernelMatrix"), + ("kernelunitlength", "kernelUnitLength"), + ("kerning", "kerning"), + ("keypoints", "keyPoints"), + ("keysplines", "keySplines"), + ("keytimes", "keyTimes"), + ("lengthadjust", "lengthAdjust"), + ("letterspacing", "letterSpacing"), + ("letter-spacing", "letterSpacing"), + ("lightingcolor", "lightingColor"), + ("lighting-color", "lightingColor"), + ("limitingconeangle", "limitingConeAngle"), + ("local", "local"), + ("markerend", "markerEnd"), + ("marker-end", "markerEnd"), + ("markerheight", "markerHeight"), + ("markermid", "markerMid"), + ("marker-mid", "markerMid"), + ("markerstart", "markerStart"), + ("marker-start", "markerStart"), + ("markerunits", "markerUnits"), + ("markerwidth", "markerWidth"), + ("mask", "mask"), + ("maskcontentunits", "maskContentUnits"), + ("maskunits", "maskUnits"), + ("mathematical", "mathematical"), + ("mode", "mode"), + ("numoctaves", "numOctaves"), + ("offset", "offset"), + ("opacity", "opacity"), + ("operator", "operator"), + ("order", "order"), + ("orient", "orient"), + ("orientation", "orientation"), + ("origin", "origin"), + ("overflow", "overflow"), + ("overlineposition", "overlinePosition"), + ("overline-position", "overlinePosition"), + ("overlinethickness", "overlineThickness"), + ("overline-thickness", "overlineThickness"), + ("paintorder", "paintOrder"), + ("paint-order", "paintOrder"), + ("panose1", "panose1"), + ("panose-1", "panose1"), + ("pathlength", "pathLength"), + ("patterncontentunits", "patternContentUnits"), + ("patterntransform", "patternTransform"), + ("patternunits", "patternUnits"), + ("pointerevents", "pointerEvents"), + ("pointer-events", "pointerEvents"), + ("points", "points"), + ("pointsatx", "pointsAtX"), + ("pointsaty", "pointsAtY"), + ("pointsatz", "pointsAtZ"), + ("prefix", "prefix"), + ("preservealpha", "preserveAlpha"), + ("preserveaspectratio", "preserveAspectRatio"), + ("primitiveunits", "primitiveUnits"), + ("property", "property"), + ("r", "r"), + ("radius", "radius"), + ("refx", "refX"), + ("refy", "refY"), + ("renderingintent", "renderingIntent"), + ("rendering-intent", "renderingIntent"), + ("repeatcount", "repeatCount"), + ("repeatdur", "repeatDur"), + ("requiredextensions", "requiredExtensions"), + ("requiredfeatures", "requiredFeatures"), + ("resource", "resource"), + ("restart", "restart"), + ("result", "result"), + ("results", "results"), + ("rotate", "rotate"), + ("rx", "rx"), + ("ry", "ry"), + ("scale", "scale"), + ("security", "security"), + ("seed", "seed"), + ("shaperendering", "shapeRendering"), + ("shape-rendering", "shapeRendering"), + ("slope", "slope"), + ("spacing", "spacing"), + ("specularconstant", "specularConstant"), + ("specularexponent", "specularExponent"), + ("speed", "speed"), + ("spreadmethod", "spreadMethod"), + ("startoffset", "startOffset"), + ("stddeviation", "stdDeviation"), + ("stemh", "stemh"), + ("stemv", "stemv"), + ("stitchtiles", "stitchTiles"), + ("stopcolor", "stopColor"), + ("stop-color", "stopColor"), + ("stopopacity", "stopOpacity"), + ("stop-opacity", "stopOpacity"), + ("strikethroughposition", "strikethroughPosition"), + ("strikethrough-position", "strikethroughPosition"), + ("strikethroughthickness", "strikethroughThickness"), + ("strikethrough-thickness", "strikethroughThickness"), + ("string", "string"), + ("stroke", "stroke"), + ("strokedasharray", "strokeDasharray"), + ("stroke-dasharray", "strokeDasharray"), + ("strokedashoffset", "strokeDashoffset"), + ("stroke-dashoffset", "strokeDashoffset"), + ("strokelinecap", "strokeLinecap"), + ("stroke-linecap", "strokeLinecap"), + ("strokelinejoin", "strokeLinejoin"), + ("stroke-linejoin", "strokeLinejoin"), + ("strokemiterlimit", "strokeMiterlimit"), + ("stroke-miterlimit", "strokeMiterlimit"), + ("strokewidth", "strokeWidth"), + ("stroke-width", "strokeWidth"), + ("strokeopacity", "strokeOpacity"), + ("stroke-opacity", "strokeOpacity"), + ( + "suppresscontenteditablewarning", + "suppressContentEditableWarning", + ), + ("suppresshydrationwarning", "suppressHydrationWarning"), + ("surfacescale", "surfaceScale"), + ("systemlanguage", "systemLanguage"), + ("tablevalues", "tableValues"), + ("targetx", "targetX"), + ("targety", "targetY"), + ("textanchor", "textAnchor"), + ("text-anchor", "textAnchor"), + ("textdecoration", "textDecoration"), + ("text-decoration", "textDecoration"), + ("textlength", "textLength"), + ("textrendering", "textRendering"), + ("text-rendering", "textRendering"), + ("to", "to"), + ("transform", "transform"), + ("typeof", "typeof"), + ("u1", "u1"), + ("u2", "u2"), + ("underlineposition", "underlinePosition"), + ("underline-position", "underlinePosition"), + ("underlinethickness", "underlineThickness"), + ("underline-thickness", "underlineThickness"), + ("unicode", "unicode"), + ("unicodebidi", "unicodeBidi"), + ("unicode-bidi", "unicodeBidi"), + ("unicoderange", "unicodeRange"), + ("unicode-range", "unicodeRange"), + ("unitsperem", "unitsPerEm"), + ("units-per-em", "unitsPerEm"), + ("unselectable", "unselectable"), + ("valphabetic", "vAlphabetic"), + ("v-alphabetic", "vAlphabetic"), + ("values", "values"), + ("vectoreffect", "vectorEffect"), + ("vector-effect", "vectorEffect"), + ("version", "version"), + ("vertadvy", "vertAdvY"), + ("vert-adv-y", "vertAdvY"), + ("vertoriginx", "vertOriginX"), + ("vert-origin-x", "vertOriginX"), + ("vertoriginy", "vertOriginY"), + ("vert-origin-y", "vertOriginY"), + ("vhanging", "vHanging"), + ("v-hanging", "vHanging"), + ("videographic", "vIdeographic"), + ("v-ideographic", "vIdeographic"), + ("viewbox", "viewBox"), + ("viewtarget", "viewTarget"), + ("visibility", "visibility"), + ("vmathematical", "vMathematical"), + ("v-mathematical", "vMathematical"), + ("vocab", "vocab"), + ("widths", "widths"), + ("wordspacing", "wordSpacing"), + ("word-spacing", "wordSpacing"), + ("writingmode", "writingMode"), + ("writing-mode", "writingMode"), + ("x1", "x1"), + ("x2", "x2"), + ("x", "x"), + ("xchannelselector", "xChannelSelector"), + ("xheight", "xHeight"), + ("x-height", "xHeight"), + ("xlinkactuate", "xlinkActuate"), + ("xlink:actuate", "xlinkActuate"), + ("xlinkarcrole", "xlinkArcrole"), + ("xlink:arcrole", "xlinkArcrole"), + ("xlinkhref", "xlinkHref"), + ("xlink:href", "xlinkHref"), + ("xlinkrole", "xlinkRole"), + ("xlink:role", "xlinkRole"), + ("xlinkshow", "xlinkShow"), + ("xlink:show", "xlinkShow"), + ("xlinktitle", "xlinkTitle"), + ("xlink:title", "xlinkTitle"), + ("xlinktype", "xlinkType"), + ("xlink:type", "xlinkType"), + ("xmlbase", "xmlBase"), + ("xml:base", "xmlBase"), + ("xmllang", "xmlLang"), + ("xml:lang", "xmlLang"), + ("xmlns", "xmlns"), + ("xml:space", "xmlSpace"), + ("xmlnsxlink", "xmlnsXlink"), + ("xmlns:xlink", "xmlnsXlink"), + ("xmlspace", "xmlSpace"), + ("y1", "y1"), + ("y2", "y2"), + ("y", "y"), + ("ychannelselector", "yChannelSelector"), + ("z", "z"), + ("zoomandpan", "zoomAndPan"), + ]) +} diff --git a/crates/svgr-rs/src/hast_to_swc_ast/mod.rs b/crates/svgr-rs/src/hast_to_swc_ast/mod.rs new file mode 100644 index 000000000..b3b49aec9 --- /dev/null +++ b/crates/svgr-rs/src/hast_to_swc_ast/mod.rs @@ -0,0 +1,357 @@ +use std::collections::HashMap; + +use regex::{Captures, Regex}; +use swc_core::common::{SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; +use swc_core::ecma::atoms::JsWord; +use swc_xml::visit::{Visit, VisitWith}; + +mod decode_xml; +mod mappings; +mod string_to_object_style; +mod util; + +use self::decode_xml::*; +use self::mappings::*; +use self::string_to_object_style::*; +use self::util::*; + +fn kebab_case(str: &str) -> String { + let kebab_regex = Regex::new(r"[A-Z\u00C0-\u00D6\u00D8-\u00DE]").unwrap(); + kebab_regex + .replace_all(str, |caps: &Captures| { + format!("-{}", &caps[0].to_lowercase()) + }) + .to_string() +} + +fn convert_aria_attribute(kebab_key: &str) -> String { + let parts: Vec<&str> = kebab_key.split('-').collect(); + let aria = parts[0]; + let lowercase_parts: String = parts[1..].join("").to_lowercase(); + format!("{}-{}", aria, lowercase_parts) +} + +fn replace_spaces(s: &str) -> String { + let spaces_regex = Regex::new(r"[\t\r\n\u0085\u2028\u2029]+").unwrap(); + spaces_regex.replace_all(s, |_: &Captures| " ").to_string() +} + +fn get_value(attr_name: &str, value: &JsWord) -> JSXAttrValue { + if attr_name == "style" { + let style = string_to_object_style(value); + + return JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(style)), + }); + } + + if is_numeric(value) { + return JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Lit(Lit::Num(Number { + span: DUMMY_SP, + value: value.parse().unwrap(), + raw: None, + })))), + }); + } + + JSXAttrValue::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: replace_spaces(value).into(), + raw: None, + })) +} + +fn text(n: &swc_xml::ast::Text) -> Option { + let value = n.data.to_string(); + + let space_regex = Regex::new(r"^\s+$").unwrap(); + if space_regex.is_match(&value) { + return None; + } + + Some(JSXElementChild::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: decode_xml(&value).into(), + raw: None, + })))), + })) +} + +pub struct HastVisitor { + jsx: Option, + attr_mappings: HashMap<&'static str, &'static str>, +} + +impl HastVisitor { + fn new() -> Self { + Self { + jsx: None, + attr_mappings: create_attr_mappings(), + } + } + + pub fn get_jsx(&self) -> Option { + self.jsx.clone() + } + + fn element(&self, n: &swc_xml::ast::Element) -> JSXElement { + let attrs = n + .attributes + .iter() + .map(|attr| { + let value = attr.value.clone().map(|v| get_value(&attr.name, &v)); + JSXAttrOrSpread::JSXAttr(JSXAttr { + span: DUMMY_SP, + name: JSXAttrName::Ident(self.get_key(&attr.name, &n.tag_name).into()), + value, + }) + }) + .collect::>(); + + let name = JSXElementName::Ident(Ident::new( + n.tag_name.clone(), + DUMMY_SP, + SyntaxContext::empty(), + )); + let children = self.all(&n.children); + + let opening = JSXOpeningElement { + span: DUMMY_SP, + name: name.clone(), + attrs, + self_closing: children.is_empty(), + type_args: None, + }; + + let closing = if !children.is_empty() { + Some(JSXClosingElement { + span: DUMMY_SP, + name, + }) + } else { + None + }; + + JSXElement { + span: DUMMY_SP, + opening, + children, + closing, + } + } + + fn all(&self, children: &[swc_xml::ast::Child]) -> Vec { + children + .iter() + .filter_map(|n| match n { + swc_xml::ast::Child::Element(e) => { + Some(JSXElementChild::JSXElement(Box::new(self.element(e)))) + } + swc_xml::ast::Child::Text(t) => text(t), + _ => None, + }) + .collect() + } + + fn get_key(&self, attr_name: &str, tag_name: &str) -> Ident { + let lower_case_name = attr_name.to_lowercase(); + let rc_key = { + match tag_name { + "input" => match lower_case_name.as_str() { + "checked" => Some("defaultChecked"), + "value" => Some("defaultValue"), + "maxlength" => Some("maxLength"), + _ => None, + }, + "form" => match lower_case_name.as_str() { + "enctype" => Some("encType"), + _ => None, + }, + _ => None, + } + }; + + if let Some(k) = rc_key { + return Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: k.into(), + optional: false, + }; + } + + let mapped_attr = self.attr_mappings.get(lower_case_name.as_str()); + if let Some(k) = mapped_attr { + return Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: JsWord::from(*k), + optional: false, + }; + } + + let kebab_key = kebab_case(attr_name); + + if kebab_key.starts_with("aria-") { + return Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: convert_aria_attribute(attr_name).into(), + optional: false, + }; + } + + if kebab_key.starts_with("data-") { + return Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: attr_name.into(), + optional: false, + }; + } + + Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: attr_name.into(), + optional: false, + } + } +} + +impl Visit for HastVisitor { + fn visit_element(&mut self, n: &swc_xml::ast::Element) { + self.jsx = Some(self.element(n)); + } +} + +pub fn to_swc_ast(hast: swc_xml::ast::Document) -> Option { + let mut v = HastVisitor::new(); + hast.visit_with(&mut v); + v.get_jsx() +} + +#[cfg(test)] +mod tests { + use std::borrow::Borrow; + use std::path::PathBuf; + use std::sync::Arc; + + use swc_core::common::{FileName, SourceFile, SourceMap}; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::{Config, Emitter}; + use swc_xml::parser::parse_file_as_document; + use testing::NormalizedOutput; + + use super::*; + + fn transform(cm: Arc, fm: Arc, minify: bool) -> String { + let mut errors = vec![]; + let doc = parse_file_as_document(fm.borrow(), Default::default(), &mut errors).unwrap(); + + let jsx = to_swc_ast(doc).unwrap(); + + let mut buf = vec![]; + + let new_line = match minify { + true => "", + false => "\n", + }; + let mut emitter = Emitter { + cfg: Config::default().with_minify(minify), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, new_line, &mut buf, None), + }; + + emitter + .emit_module_item(&ModuleItem::Stmt(Stmt::Expr(ExprStmt { + span: DUMMY_SP, + expr: Box::new(Expr::JSXElement(Box::new(jsx))), + }))) + .unwrap(); + + String::from_utf8_lossy(&buf).to_string() + } + + fn document_test(input: PathBuf) { + let jsx_path = input.parent().unwrap().join("output.jsx"); + + let cm = Arc::::default(); + let fm = cm.load_file(&input).expect("failed to load fixture file"); + + let res = transform(cm, fm, false); + + NormalizedOutput::from(res) + .compare_to_file(jsx_path) + .unwrap(); + } + + fn code_test(input: &str, expected: &str) { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let res = transform(cm, fm, true); + + assert_eq!(res, expected) + } + + #[testing::fixture("__fixture__/*/*.svg")] + fn pass(input: PathBuf) { + document_test(input); + } + + #[test] + fn transforms_data_x() { + code_test( + r#""#, + r#";"#, + ); + } + + #[test] + fn preserves_mask_type() { + code_test( + r#""#, + r#";"#, + ); + } + + #[test] + fn string_literals_children_of_text_nodes_should_have_decoded_xml_entities() { + code_test( + r#"<"#, + r#"{"<"};"#, + ); + } + + #[test] + fn string_literals_children_of_tspan_nodes_should_have_decoded_xml_entities() { + code_test( + r#"<"#, + r#"{"<"};"#, + ); + } + + #[test] + fn transforms_style() { + code_test( + r#""#, + r#";"#, + ); + } + + #[test] + fn transforms_class() { + code_test( + r#""#, + r#";"#, + ); + } +} diff --git a/crates/svgr-rs/src/hast_to_swc_ast/string_to_object_style.rs b/crates/svgr-rs/src/hast_to_swc_ast/string_to_object_style.rs new file mode 100644 index 000000000..67c3c5793 --- /dev/null +++ b/crates/svgr-rs/src/hast_to_swc_ast/string_to_object_style.rs @@ -0,0 +1,99 @@ +use regex::{Captures, Regex}; +use swc_core::common::DUMMY_SP; +use swc_core::ecma::ast::*; + +use super::util::*; + +const PX_REGEX: &str = r#"^\d+px$"#; +const MS_REGEX: &str = r#"^-ms-"#; +const VAR_REGEX: &str = r#"^--"#; + +pub fn hyphen_to_camel_case(s: &str) -> String { + let regex = Regex::new(r#"-(.)"#).unwrap(); + regex + .replace_all(s, |caps: &Captures| caps[1].to_uppercase()) + .into() +} + +// Format style key into JSX style object key. +pub fn format_key(key: &str) -> PropName { + let var_regex = Regex::new(VAR_REGEX).unwrap(); + if var_regex.is_match(key) { + return PropName::Str(Str { + span: DUMMY_SP, + value: key.into(), + raw: None, + }); + } + + let mut key = key.to_lowercase(); + let ms_regex = Regex::new(MS_REGEX).unwrap(); + if ms_regex.is_match(&key) { + key = key[1..].into(); + } + + PropName::Ident(IdentName::new(hyphen_to_camel_case(&key).into(), DUMMY_SP)) +} + +fn is_convertible_pixel_value(s: &str) -> bool { + let px_regex = Regex::new(PX_REGEX).unwrap(); + px_regex.is_match(s) +} + +// Format style value into JSX style object value. +pub fn format_value(value: &str) -> Expr { + if is_numeric(value) { + return Expr::Lit(Lit::Num(Number { + span: DUMMY_SP, + value: value.parse().unwrap(), + raw: None, + })); + } + + if is_convertible_pixel_value(value) { + return Expr::Lit(Lit::Num(Number { + span: DUMMY_SP, + value: value[..value.len() - 2].parse().unwrap(), + raw: None, + })); + } + + Expr::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: value.into(), + raw: None, + })) +} + +pub fn string_to_object_style(raw_style: &str) -> Expr { + let entries = raw_style.split(';'); + + let properties = entries + .into_iter() + .filter_map(|entry| { + let style = entry.trim(); + if style.is_empty() { + return None; + } + + let first_colon = style.find(':'); + match first_colon { + Some(i) => { + let value = format_value(style[(i + 1)..].trim()); + let key = format_key(style[..i].trim()); + + Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key, + value: Box::new(value), + })))) + } + None => None, + } + }) + .collect::>(); + + Expr::Object(ObjectLit { + span: DUMMY_SP, + props: properties, + }) +} diff --git a/crates/svgr-rs/src/hast_to_swc_ast/util.rs b/crates/svgr-rs/src/hast_to_swc_ast/util.rs new file mode 100644 index 000000000..c7ed0d437 --- /dev/null +++ b/crates/svgr-rs/src/hast_to_swc_ast/util.rs @@ -0,0 +1,6 @@ +use regex::Regex; + +pub fn is_numeric(s: &str) -> bool { + let regex = Regex::new(r#"^(\-|\+)?\d+(\.\d+)?$"#).unwrap(); + regex.is_match(s) +} diff --git a/crates/svgr-rs/src/lib.rs b/crates/svgr-rs/src/lib.rs new file mode 100644 index 000000000..d7bd668ce --- /dev/null +++ b/crates/svgr-rs/src/lib.rs @@ -0,0 +1,134 @@ +#![feature(path_file_prefix)] +#![deny(clippy::all)] + +#[cfg(feature = "node")] +#[macro_use] +extern crate napi_derive; + +use std::borrow::Borrow; +use std::sync::Arc; + +use swc_core::common::comments::SingleThreadedComments; +use swc_core::common::{FileName, SourceMap}; +use swc_core::ecma::codegen::text_writer::JsWriter; +use swc_core::ecma::codegen::Emitter; +use swc_core::ecma::visit::{as_folder, FoldWith}; +use swc_xml::parser::parse_file_as_document; + +mod add_jsx_attribute; +mod core; +mod error; +mod hast_to_swc_ast; +mod remove_jsx_attribute; +mod replace_jsx_attribute; +mod svg_dynamic_title; +mod svg_em_dimensions; +mod transform_react_native_svg; +mod transform_svg_component; + +pub use error::SvgrError; + +pub use self::core::config::{Config, ExpandProps, ExportType, Icon, JSXRuntime, JSXRuntimeImport}; +pub use self::core::state::{Caller, Config as State}; + +/// Transform SVG into React components. +/// +/// It takes three arguments: +/// +/// * source: the SVG source code to transform +/// * options: the options used to transform the SVG +/// * state: a state linked to the transformation +/// +/// # Examples +/// +/// Basic usage: +/// +/// ```rust +/// use svgr_rs::transform; +/// +/// let result = transform( +/// r#""#.to_string(), +/// Default::default(), +/// Default::default(), +/// ); +/// ``` +pub fn transform(code: String, config: Config, state: State) -> Result { + let state = core::state::expand_state(&state); + + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), code); + + let mut errors = vec![]; + let document = parse_file_as_document(fm.borrow(), Default::default(), &mut errors) + .map_err(|e| SvgrError::Parse(e.message().to_string()))?; + + let jsx_element = hast_to_swc_ast::to_swc_ast(document); + if jsx_element.is_none() { + return Err(SvgrError::InvalidSvg); + } + let jsx_element = jsx_element.unwrap(); + + let m = transform_svg_component::transform(jsx_element, &config, &state)?; + + let m = m.fold_with(&mut as_folder(remove_jsx_attribute::Visitor::new(&config))); + let m = m.fold_with(&mut as_folder(add_jsx_attribute::Visitor::new(&config))); + + let icon = match config.icon { + Some(core::config::Icon::Bool(b)) => b, + None => false, + _ => true, + }; + let dimensions = config.dimensions.unwrap_or(true); + let m = if icon && dimensions { + m.fold_with(&mut as_folder(svg_em_dimensions::Visitor::new(&config))) + } else { + m + }; + + let replace_attr_values = config.replace_attr_values.is_some(); + let m = if replace_attr_values { + m.fold_with(&mut as_folder(replace_jsx_attribute::Visitor::new(&config))) + } else { + m + }; + + let title_prop = config.title_prop.unwrap_or(false); + let m = if title_prop { + m.fold_with(&mut as_folder(svg_dynamic_title::Visitor::new( + "title".to_string(), + ))) + } else { + m + }; + + let desc_prop = config.desc_prop.unwrap_or(false); + let m = if desc_prop { + m.fold_with(&mut as_folder(svg_dynamic_title::Visitor::new( + "desc".to_string(), + ))) + } else { + m + }; + + let native = config.native.unwrap_or(false); + let m = if native { + let comments = SingleThreadedComments::default(); + m.fold_with(&mut as_folder(transform_react_native_svg::Visitor::new( + &comments, + ))) + } else { + m + }; + + let mut buf = vec![]; + + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "\n", &mut buf, None), + }; + emitter.emit_module(&m).unwrap(); + + Ok(String::from_utf8_lossy(&buf).to_string()) +} diff --git a/crates/svgr-rs/src/remove_jsx_attribute.rs b/crates/svgr-rs/src/remove_jsx_attribute.rs new file mode 100644 index 000000000..31962e223 --- /dev/null +++ b/crates/svgr-rs/src/remove_jsx_attribute.rs @@ -0,0 +1,132 @@ +use swc_core::ecma::ast::*; +use swc_core::ecma::visit::VisitMut; + +use super::core; + +pub struct Visitor { + elements: Vec, + attributes: Vec, +} + +impl Visitor { + pub fn new(config: &core::config::Config) -> Self { + let mut attributes = vec!["version".to_string()]; + + let dimensions = config.dimensions.unwrap_or(true); + if !dimensions { + attributes.push("width".to_string()); + attributes.push("height".to_string()); + } + + Self { + elements: vec!["svg".to_string(), "Svg".to_string()], + attributes, + } + } +} + +impl VisitMut for Visitor { + fn visit_mut_jsx_opening_element(&mut self, n: &mut JSXOpeningElement) { + if let JSXElementName::Ident(ident) = &n.name { + if !self.elements.contains(&ident.sym.to_string()) { + return; + } + } else { + return; + } + + let len = n.attrs.len(); + let mut attrs = n.attrs.clone(); + attrs.reverse(); + attrs.iter().enumerate().for_each(|(index, attr)| { + if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr { + if let JSXAttrName::Ident(ident) = &jsx_attr.name { + if self.attributes.contains(&ident.sym.to_string()) { + n.attrs.remove(len - index - 1); + } + } + } + }); + } +} + +#[cfg(test)] +mod tests { + use std::default::Default; + use std::sync::Arc; + + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::ast::*; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser::lexer::Lexer; + use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax}; + use swc_core::ecma::visit::{as_folder, FoldWith}; + + use super::*; + + pub struct Options { + elements: Vec, + attributes: Vec, + } + + fn code_test(input: &str, opts: Options, expected: &str) { + let cm = Arc::new(SourceMap::default()); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + decorators: true, + jsx: true, + ..Default::default() + }), + EsVersion::EsNext, + StringInput::from(&*fm), + None, + ); + + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().unwrap(); + + let module = module.fold_with(&mut as_folder(Visitor { + elements: opts.elements, + attributes: opts.attributes, + })); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "", &mut buf, None), + }; + emitter.emit_module(&module).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + #[test] + fn should_remove_attributes_from_an_element() { + code_test( + r#"
;"#, + Options { + elements: vec!["span".to_string()], + attributes: vec!["foo".to_string()], + }, + r#"
;"#, + ); + } + + #[test] + fn should_not_throw_error_when_spread_operator_is_used() { + code_test( + r#"
;"#, + Options { + elements: vec!["span".to_string()], + attributes: vec!["foo".to_string()], + }, + r#"
;"#, + ); + } +} diff --git a/crates/svgr-rs/src/replace_jsx_attribute.rs b/crates/svgr-rs/src/replace_jsx_attribute.rs new file mode 100644 index 000000000..00c12e48a --- /dev/null +++ b/crates/svgr-rs/src/replace_jsx_attribute.rs @@ -0,0 +1,133 @@ +use linked_hash_map::LinkedHashMap; +use swc_core::common::{SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; +use swc_core::ecma::visit::VisitMut; + +use super::core; + +pub struct Visitor { + values: LinkedHashMap, +} + +impl Visitor { + pub fn new(config: &core::config::Config) -> Self { + let replace_attr_values = config.replace_attr_values.as_ref().unwrap(); + + Self { + values: replace_attr_values.clone(), + } + } +} + +impl VisitMut for Visitor { + fn visit_mut_jsx_opening_element(&mut self, n: &mut JSXOpeningElement) { + n.attrs.iter_mut().for_each(|attr| { + if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr { + if let Some(JSXAttrValue::Lit(Lit::Str(str))) = &jsx_attr.value { + let old_value = str.value.to_string(); + + if self.values.contains_key(&old_value) { + let attr_value = get_attr_value(self.values.get(&old_value).unwrap()); + jsx_attr.value = Some(attr_value); + } + } + } + }); + } +} + +fn get_attr_value(new: &str) -> JSXAttrValue { + let literal = new.starts_with('{') && new.ends_with('}'); + let s = if literal { &new[1..new.len() - 1] } else { new }; + + if literal { + JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Ident(Ident { + sym: s.to_string().into(), + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + optional: false, + }))), + }) + } else { + JSXAttrValue::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: s.to_string().into(), + raw: None, + })) + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::ast::*; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser::lexer::Lexer; + use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax}; + use swc_core::ecma::visit::{as_folder, FoldWith}; + + use super::*; + + fn code_test(input: &str, replace_attr_values: LinkedHashMap, expected: &str) { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + decorators: true, + jsx: true, + ..Default::default() + }), + EsVersion::EsNext, + StringInput::from(&*fm), + None, + ); + + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().unwrap(); + + let module = module.fold_with(&mut as_folder(Visitor::new(&core::config::Config { + replace_attr_values: Some(replace_attr_values), + ..Default::default() + }))); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "", &mut buf, None), + }; + emitter.emit_module(&module).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + #[test] + fn should_replace_attribute_values_1() { + let mut replace_attr_values = LinkedHashMap::new(); + replace_attr_values.insert("cool".to_string(), "not cool".to_string()); + code_test( + r#"
;"#, + replace_attr_values, + r#"
;"#, + ); + } + + #[test] + fn should_replace_attribute_values_2() { + let mut replace_attr_values = LinkedHashMap::new(); + replace_attr_values.insert("cool".to_string(), "{props.color}".to_string()); + code_test( + r#"
;"#, + replace_attr_values, + r#"
;"#, + ); + } +} diff --git a/crates/svgr-rs/src/svg_dynamic_title.rs b/crates/svgr-rs/src/svg_dynamic_title.rs new file mode 100644 index 000000000..26bad4e5b --- /dev/null +++ b/crates/svgr-rs/src/svg_dynamic_title.rs @@ -0,0 +1,384 @@ +use swc_core::common::{SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; +use swc_core::ecma::visit::VisitMut; + +const ELEMENTS: [&str; 2] = ["svg", "Svg"]; + +pub struct Visitor { + tag: String, + tag_id: String, +} + +impl Visitor { + pub fn new(tag: String) -> Self { + let tag_id = format!("{}Id", tag); + + Self { tag, tag_id } + } + + fn get_tag_expr(&self, value: JSXAttrValue) -> Expr { + let cons = Box::new(Expr::JSXElement(Box::new(JSXElement { + span: DUMMY_SP, + opening: JSXOpeningElement { + span: DUMMY_SP, + name: JSXElementName::Ident(Ident::new( + self.tag.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + attrs: vec![JSXAttrOrSpread::JSXAttr(JSXAttr { + span: DUMMY_SP, + name: JSXAttrName::Ident(IdentName::new("id".to_string().into(), DUMMY_SP)), + value: Some(value), + })], + self_closing: false, + type_args: None, + }, + children: vec![JSXElementChild::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Ident(Ident::new( + self.tag.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + })], + closing: Some(JSXClosingElement { + span: DUMMY_SP, + name: JSXElementName::Ident(Ident::new( + self.tag.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + }), + }))); + + Expr::Cond(CondExpr { + span: DUMMY_SP, + test: Box::new(Expr::Ident(Ident::new( + self.tag.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + cons, + alt: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), + }) + } + + fn get_tag_element(&self) -> JSXElementChild { + let value = JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Ident(Ident::new( + self.tag_id.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + }); + + let expr = self.get_tag_expr(value); + + JSXElementChild::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(expr)), + }) + } + + fn get_tag_element_with_existing_title( + &self, + existing_title: &mut JSXElement, + ) -> JSXElementChild { + let test = Expr::Bin(BinExpr { + span: DUMMY_SP, + left: Box::new(Expr::Ident(Ident::new( + self.tag.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + op: op!("==="), + right: Box::new(Expr::Ident(Ident::new( + "undefined".into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + }); + + let existing_id = existing_title.opening.attrs.iter_mut().find(|attr| { + if let JSXAttrOrSpread::JSXAttr(JSXAttr { + name: JSXAttrName::Ident(ident), + .. + }) = attr + { + if ident.sym == "id" { + return true; + } + } + false + }); + + let id_attr_value = if let Some(JSXAttrOrSpread::JSXAttr(attr)) = existing_id { + let jsx_attr_value = match &attr.value { + Some(JSXAttrValue::Lit(Lit::Str(Str { value, .. }))) => { + JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: Box::new(Expr::Ident(Ident::new( + self.tag_id.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + op: op!("||"), + right: Box::new(Expr::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: value.clone(), + raw: None, + }))), + }))), + }) + } + _ => JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Ident(Ident::new( + self.tag_id.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + }), + }; + + attr.value = Some(jsx_attr_value.clone()); + + jsx_attr_value + } else { + let jsx_attr_value = JSXAttrValue::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Ident(Ident::new( + self.tag_id.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + }); + + let id_attr = JSXAttrOrSpread::JSXAttr(JSXAttr { + span: DUMMY_SP, + name: JSXAttrName::Ident(IdentName::new("id".into(), DUMMY_SP)), + value: Some(jsx_attr_value.clone()), + }); + existing_title.opening.attrs.push(id_attr); + + jsx_attr_value + }; + + if existing_title.children.is_empty() { + return JSXElementChild::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(self.get_tag_expr(id_attr_value))), + }); + } + + JSXElementChild::JSXExprContainer(JSXExprContainer { + span: DUMMY_SP, + expr: JSXExpr::Expr(Box::new(Expr::Cond(CondExpr { + span: DUMMY_SP, + test: Box::new(test), + cons: Box::new(Expr::JSXElement(Box::new(existing_title.clone()))), + alt: Box::new(self.get_tag_expr(id_attr_value)), + }))), + }) + } +} + +impl VisitMut for Visitor { + fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) { + if let JSXElementName::Ident(ident) = &n.opening.name { + let name = ident.sym.to_string(); + if !ELEMENTS.iter().any(|e| *e == name) { + return; + } + + let has_tag = n.children.clone().iter_mut().enumerate().any(|(i, c)| { + if let JSXElementChild::JSXElement(e) = c { + if let JSXElementName::Ident(ident) = &e.opening.name { + if ident.sym == self.tag { + let tag_element = self.get_tag_element_with_existing_title(e); + n.children[i] = tag_element; + return true; + } + } + } + false + }); + + if !has_tag { + n.children.insert(0, self.get_tag_element()); + } + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::ast::*; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser::lexer::Lexer; + use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax}; + use swc_core::ecma::visit::{as_folder, FoldWith}; + + use super::*; + + fn code_test(input: &str, tag: String, expected: &str) { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + decorators: true, + jsx: true, + ..Default::default() + }), + EsVersion::EsNext, + StringInput::from(&*fm), + None, + ); + + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().unwrap(); + + let module = module.fold_with(&mut as_folder(Visitor::new(tag))); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "", &mut buf, None), + }; + emitter.emit_module(&module).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + #[test] + fn title_plugin_should_add_title_attribute_if_not_present() { + code_test( + r#";"#, + "title".to_string(), + r#"{title ? {title} : null};"#, + ); + } + + #[test] + fn title_plugin_should_add_title_element_and_fallback_to_existing_title() { + code_test( + r#"Hello;"#, + "title".to_string(), + r#"{title === undefined ? Hello : title ? {title} : null};"#, + ); + + code_test( + r#"{"Hello"};"#, + "title".to_string(), + r#"{title === undefined ? {"Hello"} : title ? {title} : null};"#, + ); + } + + #[test] + fn title_plugin_should_preserve_any_existing_title_attributes() { + code_test( + r#"Hello;"#, + "title".to_string(), + r#"{title === undefined ? Hello : title ? {title} : null};"#, + ); + } + + #[test] + fn title_plugin_should_support_empty_title() { + code_test( + r#";"#, + "title".to_string(), + r#"{title ? {title} : null};"#, + ); + } + + #[test] + fn title_plugin_should_support_self_closing_title() { + code_test( + r#";"#, + "title".to_string(), + r#"{title ? {title} : null};"#, + ); + } + + #[test] + fn title_plugin_should_work_if_an_attribute_is_already_present() { + code_test( + r#";"#, + "title".to_string(), + r#"{title ? {title} : null};"#, + ); + } + + #[test] + fn desc_plugin_should_add_desc_attribute_if_not_present() { + code_test( + r#";"#, + "desc".to_string(), + r#"{desc ? {desc} : null};"#, + ); + } + + #[test] + fn desc_plugin_should_add_desc_element_and_fallback_to_existing_desc() { + code_test( + r#"Hello;"#, + "desc".to_string(), + r#"{desc === undefined ? Hello : desc ? {desc} : null};"#, + ); + + code_test( + r#"{"Hello"};"#, + "desc".to_string(), + r#"{desc === undefined ? {"Hello"} : desc ? {desc} : null};"#, + ); + } + + #[test] + fn desc_plugin_should_preserve_any_existing_desc_attributes() { + code_test( + r#"Hello;"#, + "desc".to_string(), + r#"{desc === undefined ? Hello : desc ? {desc} : null};"#, + ); + } + + #[test] + fn desc_plugin_should_support_empty_desc() { + code_test( + r#";"#, + "desc".to_string(), + r#"{desc ? {desc} : null};"#, + ); + } + + #[test] + fn desc_plugin_should_support_self_closing_desc() { + code_test( + r#";"#, + "desc".to_string(), + r#"{desc ? {desc} : null};"#, + ); + } + + #[test] + fn desc_plugin_should_work_if_an_attribute_is_already_present() { + code_test( + r#";"#, + "desc".to_string(), + r#"{desc ? {desc} : null};"#, + ); + } +} diff --git a/crates/svgr-rs/src/svg_em_dimensions.rs b/crates/svgr-rs/src/svg_em_dimensions.rs new file mode 100644 index 000000000..e99283b9b --- /dev/null +++ b/crates/svgr-rs/src/svg_em_dimensions.rs @@ -0,0 +1,235 @@ +use swc_core::common::DUMMY_SP; +use swc_core::ecma::ast::*; +use swc_core::ecma::visit::VisitMut; + +use super::core; + +const ELEMENTS: [&str; 2] = ["svg", "Svg"]; + +enum Size { + Str(String), + Num(f64), +} + +pub struct Visitor { + height: Option, + width: Option, +} + +impl Visitor { + pub fn new(config: &core::config::Config) -> Self { + let height: Option; + let width: Option; + + let icon = config + .icon + .clone() + .unwrap_or(core::config::Icon::Bool(false)); + match icon { + core::config::Icon::Str(s) => { + height = Some(Size::Str(s.clone())); + width = Some(Size::Str(s)); + } + core::config::Icon::Num(n) => { + height = Some(Size::Num(n)); + width = Some(Size::Num(n)); + } + core::config::Icon::Bool(_) => { + let native = config.native.unwrap_or(false); + if native { + height = Some(Size::Num(24.0)); + width = Some(Size::Num(24.0)); + } else { + height = None; + width = None; + } + } + } + + Self { height, width } + } +} + +impl VisitMut for Visitor { + fn visit_mut_jsx_opening_element(&mut self, n: &mut JSXOpeningElement) { + let is_svg = ELEMENTS.iter().any(|element| { + if let JSXElementName::Ident(ident) = n.name.clone() { + return ident.sym == *element; + } + false + }); + + if !is_svg { + return; + } + + let mut required_attrs = vec!["width", "height"]; + + n.attrs.iter_mut().for_each(|attr| { + if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr { + if let JSXAttrName::Ident(ident) = &jsx_attr.name { + required_attrs + .clone() + .iter() + .enumerate() + .for_each(|(index, attr)| { + if ident.sym == *attr { + match *attr { + "height" => { + jsx_attr.value.replace(get_value(self.height.as_ref())); + } + "width" => { + jsx_attr.value.replace(get_value(self.width.as_ref())); + } + _ => {} + } + required_attrs.remove(index); + } + }); + } + } + }); + + required_attrs.iter().for_each(|attr| { + n.attrs.push(JSXAttrOrSpread::JSXAttr(JSXAttr { + span: DUMMY_SP, + name: JSXAttrName::Ident(IdentName::new((*attr).into(), DUMMY_SP)), + value: Some(get_value(match *attr { + "height" => self.height.as_ref(), + "width" => self.width.as_ref(), + _ => None, + })), + })); + }); + } +} + +fn get_value(raw: Option<&Size>) -> JSXAttrValue { + match raw { + None => JSXAttrValue::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: "1em".into(), + raw: None, + })), + Some(str_or_num) => match str_or_num { + Size::Str(str) => JSXAttrValue::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: str.clone().into(), + raw: None, + })), + Size::Num(num) => JSXAttrValue::JSXExprContainer(JSXExprContainer { + expr: JSXExpr::Expr(Box::new(Expr::Lit(Lit::Num(Number { + span: DUMMY_SP, + value: *num, + raw: None, + })))), + span: DUMMY_SP, + }), + }, + } +} + +#[cfg(test)] +mod tests { + use std::default::Default; + use std::sync::Arc; + + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::ast::*; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser::lexer::Lexer; + use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax}; + use swc_core::ecma::visit::{as_folder, FoldWith}; + + use super::*; + + struct Options { + height: Option, + width: Option, + } + + fn code_test(input: &str, opts: Options, expected: &str) { + let cm = Arc::new(SourceMap::default()); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + decorators: true, + jsx: true, + ..Default::default() + }), + EsVersion::EsNext, + StringInput::from(&*fm), + None, + ); + + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().unwrap(); + + let module = module.fold_with(&mut as_folder(Visitor { + height: opts.height, + width: opts.width, + })); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "", &mut buf, None), + }; + emitter.emit_module(&module).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + #[test] + fn replaces_width_or_height_attributes() { + code_test( + r#";"#, + Options { + height: None, + width: None, + }, + r#";"#, + ); + } + + #[test] + fn adds_em_if_they_are_not_present() { + code_test( + r#";"#, + Options { + height: None, + width: None, + }, + r#";"#, + ); + } + + #[test] + fn accepts_numeric_values() { + code_test( + r#";"#, + Options { + height: Some(Size::Num(24.0)), + width: Some(Size::Num(24.0)), + }, + r#";"#, + ); + } + + #[test] + fn accepts_string_values() { + code_test( + r#";"#, + Options { + height: Some(Size::Str("2em".to_string())), + width: Some(Size::Str("2em".to_string())), + }, + r#";"#, + ); + } +} diff --git a/crates/svgr-rs/src/transform_react_native_svg.rs b/crates/svgr-rs/src/transform_react_native_svg.rs new file mode 100644 index 000000000..64c8a1a95 --- /dev/null +++ b/crates/svgr-rs/src/transform_react_native_svg.rs @@ -0,0 +1,305 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + +use linked_hash_set::LinkedHashSet; +use swc_core::common::comments::{Comment, CommentKind, Comments}; +use swc_core::common::{Span, SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; +use swc_core::ecma::atoms::JsWord; +use swc_core::ecma::visit::{VisitMut, VisitMutWith}; + +pub struct Visitor<'a> { + replaced_components: Rc>>, + unsupported_components: Rc>>, + comments: &'a dyn Comments, +} + +impl<'a> Visitor<'a> { + pub fn new(comments: &'a dyn Comments) -> Self { + Visitor { + replaced_components: Rc::new(RefCell::new(LinkedHashSet::new())), + unsupported_components: Rc::new(RefCell::new(LinkedHashSet::new())), + comments, + } + } +} + +impl VisitMut for Visitor<'_> { + fn visit_mut_module(&mut self, n: &mut Module) { + let mut svg_element_visitor = SvgElementVisitor::new( + self.replaced_components.clone(), + self.unsupported_components.clone(), + ); + n.visit_mut_with(&mut svg_element_visitor); + + let mut import_decl_visitor = ImportDeclVisitor::new(self.replaced_components.clone()); + n.visit_mut_with(&mut import_decl_visitor); + + if let Some(span) = import_decl_visitor.import_decl_span { + let component_list = self + .unsupported_components + .borrow() + .clone() + .into_iter() + .collect::>() + .join(", "); + self.comments.add_trailing_comments( + span.hi, + vec![Comment { + kind: CommentKind::Block, + span: DUMMY_SP, + text: format!( + " SVGR has dropped some elements not supported by react-native-svg: {} ", + component_list + ) + .into(), + }], + ); + } + } +} + +struct SvgElementVisitor { + replaced_components: Rc>>, + unsupported_components: Rc>>, +} + +impl SvgElementVisitor { + fn new( + replaced_components: Rc>>, + unsupported_components: Rc>>, + ) -> Self { + SvgElementVisitor { + replaced_components, + unsupported_components, + } + } +} + +impl VisitMut for SvgElementVisitor { + fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) { + if let JSXElementName::Ident(ident) = &mut n.opening.name { + if ident.sym == "svg" { + let mut jsx_element_visitor = JSXElementVisitor::new( + self.replaced_components.clone(), + self.unsupported_components.clone(), + ); + ident.sym = "Svg".into(); + if let Some(closing) = &mut n.closing { + if let JSXElementName::Ident(ident) = &mut closing.name { + ident.sym = "Svg".into(); + } + } + n.visit_mut_with(&mut jsx_element_visitor); + } + } + } +} + +struct JSXElementVisitor { + element_to_component: HashMap<&'static str, &'static str>, + + replaced_components: Rc>>, + unsupported_components: Rc>>, +} + +impl JSXElementVisitor { + fn new( + replaced_components: Rc>>, + unsupported_components: Rc>>, + ) -> Self { + JSXElementVisitor { + element_to_component: get_element_to_component(), + replaced_components, + unsupported_components, + } + } + + fn replace_element(&self, n: &mut JSXElement) -> bool { + if let JSXElementName::Ident(ident) = &mut n.opening.name { + let element = ident.sym.to_string(); + if let Some(component) = self.element_to_component.get(&element.as_str()) { + self.replaced_components + .borrow_mut() + .insert(component.to_string()); + ident.sym = JsWord::from(*component); + if let Some(closing) = &mut n.closing { + if let JSXElementName::Ident(ident) = &mut closing.name { + ident.sym = JsWord::from(*component); + } + } + } else { + // Remove element if not supported + self.unsupported_components.borrow_mut().insert(element); + return true; + } + } + false + } +} + +impl VisitMut for JSXElementVisitor { + fn visit_mut_jsx_element(&mut self, n: &mut JSXElement) { + n.visit_mut_children_with(self); + + let mut i = n.children.len(); + while i > 0 { + i -= 1; + if let JSXElementChild::JSXElement(jsx_element) = &mut n.children[i] { + let unsupported = self.replace_element(jsx_element); + if unsupported { + n.children.remove(i); + } + } + } + } +} + +fn get_element_to_component() -> HashMap<&'static str, &'static str> { + HashMap::from([ + ("svg", "Svg"), + ("circle", "Circle"), + ("clipPath", "ClipPath"), + ("ellipse", "Ellipse"), + ("g", "G"), + ("linearGradient", "LinearGradient"), + ("radialGradient", "RadialGradient"), + ("line", "Line"), + ("path", "Path"), + ("pattern", "Pattern"), + ("polygon", "Polygon"), + ("polyline", "Polyline"), + ("rect", "Rect"), + ("symbol", "Symbol"), + ("text", "Text"), + ("textPath", "TextPath"), + ("tspan", "TSpan"), + ("use", "Use"), + ("defs", "Defs"), + ("stop", "Stop"), + ("mask", "Mask"), + ("image", "Image"), + ("foreignObject", "ForeignObject"), + ]) +} + +struct ImportDeclVisitor { + replaced_components: Rc>>, + import_decl_span: Option, +} + +impl ImportDeclVisitor { + fn new(replaced_components: Rc>>) -> Self { + ImportDeclVisitor { + replaced_components, + import_decl_span: None, + } + } +} + +impl VisitMut for ImportDeclVisitor { + fn visit_mut_import_decl(&mut self, n: &mut ImportDecl) { + if n.src.value == "react-native-svg" { + for component in self.replaced_components.borrow().iter() { + if n.specifiers.iter().any(|specifier| { + if let ImportSpecifier::Named(named) = specifier { + if named.local.sym == *component { + return true; + } + } + false + }) { + break; + } + + n.specifiers + .push(ImportSpecifier::Named(ImportNamedSpecifier { + local: Ident::new( + JsWord::from(component.as_str()), + DUMMY_SP, + SyntaxContext::empty(), + ), + imported: None, + span: DUMMY_SP, + is_type_only: false, + })); + } + + self.import_decl_span = Some(n.span); + } else if n.src.value == "expo" { + n.specifiers + .push(ImportSpecifier::Named(ImportNamedSpecifier { + local: Ident::new("Svg".into(), DUMMY_SP, SyntaxContext::empty()), + imported: None, + span: DUMMY_SP, + is_type_only: false, + })); + + self.import_decl_span = Some(n.span); + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use swc_core::common::comments::SingleThreadedComments; + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::ast::*; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser::lexer::Lexer; + use swc_core::ecma::parser::{EsSyntax, Parser, StringInput, Syntax}; + use swc_core::ecma::visit::{as_folder, FoldWith}; + + use super::*; + + fn code_test(input: &str, expected: &str) { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + decorators: true, + jsx: true, + ..Default::default() + }), + EsVersion::EsNext, + StringInput::from(&*fm), + None, + ); + + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().unwrap(); + + let comments = SingleThreadedComments::default(); + let module = module.fold_with(&mut as_folder(Visitor::new(&comments))); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: Some(&comments), + wr: JsWriter::new(cm, "", &mut buf, None), + }; + emitter.emit_module(&module).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + #[test] + fn should_transform_elements() { + code_test(r#"
;"#, r#";"#); + } + + #[test] + fn should_add_import() { + code_test( + r#"import Svg from 'react-native-svg';
;"#, + r#"import Svg, { G } from 'react-native-svg'; /* SVGR has dropped some elements not supported by react-native-svg: div */ ;"#, + ); + } +} diff --git a/crates/svgr-rs/src/transform_svg_component/mod.rs b/crates/svgr-rs/src/transform_svg_component/mod.rs new file mode 100644 index 000000000..0a3783d6a --- /dev/null +++ b/crates/svgr-rs/src/transform_svg_component/mod.rs @@ -0,0 +1,856 @@ +use swc_core::common::{SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; + +use crate::{core, SvgrError}; + +mod variables; + +fn get_variables_options(config: &core::config::Config) -> variables::Options { + let expand_props = match config.expand_props { + core::config::ExpandProps::Bool(b) => Some(variables::ExpandProps::Bool(b)), + core::config::ExpandProps::Start => Some(variables::ExpandProps::Start), + core::config::ExpandProps::End => Some(variables::ExpandProps::End), + }; + + let export_type = match config.export_type { + Some(core::config::ExportType::Named) => variables::ExportType::Named, + _ => variables::ExportType::Default, + }; + + let mut opts = variables::Options { + typescript: config.typescript.unwrap_or(false), + title_prop: config.title_prop.unwrap_or(false), + desc_prop: config.desc_prop.unwrap_or(false), + expand_props, + _ref: config._ref.unwrap_or(false), + native: config.native.unwrap_or(false), + memo: config.memo.unwrap_or(false), + named_export: Some(config.named_export.clone()), + export_type, + ..Default::default() + }; + + if let Some(jsx_runtime_import) = &config.jsx_runtime_import { + opts.import_source = Some(jsx_runtime_import.source.clone()); + opts.jsx_runtime_import = Some(jsx_runtime_import.clone()); + return opts; + } + + let jsx_runtime = config + .jsx_runtime + .clone() + .unwrap_or(core::config::JSXRuntime::Classic); + + match jsx_runtime { + core::config::JSXRuntime::Classic => { + opts.jsx_runtime = variables::JSXRuntime::Classic; + opts.import_source = Some("react".to_string()); + opts.jsx_runtime_import = Some(core::config::JSXRuntimeImport { + source: "react".to_string(), + namespace: Some("React".to_string()), + ..Default::default() + }); + } + core::config::JSXRuntime::ClassicPreact => { + opts.jsx_runtime = variables::JSXRuntime::Classic; + opts.import_source = Some("preact".to_string()); + opts.jsx_runtime_import = Some(core::config::JSXRuntimeImport { + source: "preact".to_string(), + specifiers: Some(vec!["h".to_string()]), + ..Default::default() + }); + } + core::config::JSXRuntime::Automatic => { + opts.jsx_runtime = variables::JSXRuntime::Automatic; + } + } + + opts +} + +pub fn transform( + jsx_element: JSXElement, + config: &core::config::Config, + state: &core::state::InternalConfig, +) -> Result { + let variables_options = get_variables_options(config); + + let variables = variables::get_variables(variables_options, state, jsx_element)?; + + let mut body = vec![]; + + for import in variables.imports { + body.push(import); + } + + for interface in variables.interfaces { + body.push(interface); + } + + body.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + kind: VarDeclKind::Const, + declare: false, + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent::from(Ident::new( + state.component_name.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + definite: false, + init: Some(Box::new(Expr::Arrow(ArrowExpr { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + params: variables.props, + body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::JSXElement(Box::new( + variables.jsx, + ))))), + is_async: false, + is_generator: false, + type_params: None, + return_type: None, + }))), + }], + }))))); + + for export in variables.exports { + body.push(export); + } + + Ok(Module { + span: DUMMY_SP, + body, + shebang: None, + }) +} + +#[cfg(test)] +mod tests { + use std::borrow::Borrow; + use std::sync::Arc; + + use swc_core::common::{FileName, SourceMap}; + use swc_core::ecma::codegen::text_writer::JsWriter; + use swc_core::ecma::codegen::Emitter; + use swc_core::ecma::parser; + + use super::*; + use crate::core; + + fn test_code( + input: &str, + config: &core::config::Config, + state: &core::state::InternalConfig, + expected: &str, + ) { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), input.to_string()); + + let mut recovered_errors = vec![]; + let expr = parser::parse_file_as_expr( + fm.borrow(), + parser::Syntax::Es(parser::EsSyntax { + jsx: true, + ..Default::default() + }), + EsVersion::Es2020, + None, + &mut recovered_errors, + ) + .unwrap(); + + let jsx_element = expr.as_jsx_element().unwrap(); + + let m = transform(*jsx_element.clone(), config, state).unwrap(); + + let mut buf = vec![]; + let mut emitter = Emitter { + cfg: Default::default(), + cm: cm.clone(), + comments: None, + wr: JsWriter::new(cm, "\n", &mut buf, None), + }; + emitter.emit_module(&m).unwrap(); + let result = String::from_utf8_lossy(&buf).to_string(); + + assert_eq!(result, expected); + } + + fn test_js_n_ts( + input: &str, + config: &core::config::Config, + state: &core::state::InternalConfig, + js: &str, + ts: &str, + ) { + test_code(input, config, state, js); + + let mut config = config.clone(); + config.typescript = Some(true); + test_code(input, &config, state, ts); + } + + #[test] + fn transforms_whole_program() { + test_js_n_ts( + r#""#, + &core::config::Config { + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_native_option_adds_import_from_react_native_svg() { + test_js_n_ts( + r#""#, + &core::config::Config { + native: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +import Svg from "react-native-svg"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +import Svg from "react-native-svg"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_ref_option_adds_forward_ref_component() { + test_js_n_ts( + r#""#, + &core::config::Config { + _ref: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import { forwardRef } from "react"; +const SvgComponent = (_, ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + r#"import * as React from "react"; +import { Ref, forwardRef } from "react"; +const SvgComponent = (_, ref: Ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + ); + } + + #[test] + fn with_title_prop_adds_title_and_title_id_prop() { + test_js_n_ts( + r#""#, + &core::config::Config { + title_prop: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ({ title, titleId })=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +interface SVGRProps { + title?: string; + titleId?: string; +} +const SvgComponent = ({ title, titleId }: SVGRProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_title_prop_and_expand_props_adds_title_title_id_props_and_expands_props() { + test_js_n_ts( + r#""#, + &core::config::Config { + title_prop: Some(true), + expand_props: core::config::ExpandProps::Bool(true), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ({ title, titleId, ...props })=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +import { SVGProps } from "react"; +interface SVGRProps { + title?: string; + titleId?: string; +} +const SvgComponent = ({ title, titleId, ...props }: SVGProps & SVGRProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_desc_prop_adds_desc_and_desc_id_prop() { + test_js_n_ts( + r#""#, + &core::config::Config { + desc_prop: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ({ desc, descId })=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +interface SVGRProps { + desc?: string; + descId?: string; +} +const SvgComponent = ({ desc, descId }: SVGRProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_desc_prop_and_expand_props_adds_desc_desc_id_props_and_expands_prop() { + test_js_n_ts( + r#""#, + &core::config::Config { + expand_props: core::config::ExpandProps::Bool(true), + desc_prop: Some(true), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ({ desc, descId, ...props })=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +import { SVGProps } from "react"; +interface SVGRProps { + desc?: string; + descId?: string; +} +const SvgComponent = ({ desc, descId, ...props }: SVGProps & SVGRProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_title_prop_and_desc_prop_adds_title_title_id_desc_and_desc_id_prop() { + test_js_n_ts( + r#""#, + &core::config::Config { + title_prop: Some(true), + desc_prop: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ({ title, titleId, desc, descId })=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +interface SVGRProps { + title?: string; + titleId?: string; + desc?: string; + descId?: string; +} +const SvgComponent = ({ title, titleId, desc, descId }: SVGRProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_title_prop_desc_prop_and_expand_props_adds_title_title_id_desc_desc_id_props_and_expands_props( + ) { + test_js_n_ts( + r#""#, + &core::config::Config { + expand_props: core::config::ExpandProps::Bool(true), + title_prop: Some(true), + desc_prop: Some(true), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ({ title, titleId, desc, descId, ...props })=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +import { SVGProps } from "react"; +interface SVGRProps { + title?: string; + titleId?: string; + desc?: string; + descId?: string; +} +const SvgComponent = ({ title, titleId, desc, descId, ...props }: SVGProps & SVGRProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_expand_props_add_props() { + test_js_n_ts( + r#""#, + &core::config::Config { + expand_props: core::config::ExpandProps::Bool(true), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = (props)=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +import { SVGProps } from "react"; +const SvgComponent = (props: SVGProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_ref_and_expand_props_option_expands_props() { + test_js_n_ts( + r#""#, + &core::config::Config { + expand_props: core::config::ExpandProps::Bool(true), + _ref: Some(true), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import { forwardRef } from "react"; +const SvgComponent = (props, ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + r#"import * as React from "react"; +import { SVGProps, Ref, forwardRef } from "react"; +const SvgComponent = (props: SVGProps, ref: Ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + ); + } + + #[test] + fn with_native_ref_option_adds_import_from_react_native_svg_and_adds_forward_ref_component() { + test_js_n_ts( + r#""#, + &core::config::Config { + native: Some(true), + _ref: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import Svg from "react-native-svg"; +import { forwardRef } from "react"; +const SvgComponent = (_, ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + r#"import * as React from "react"; +import Svg from "react-native-svg"; +import { Ref, forwardRef } from "react"; +const SvgComponent = (_, ref: Ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + ); + } + + #[test] + fn with_native_and_expand_props_option() { + test_js_n_ts( + r#""#, + &core::config::Config { + native: Some(true), + expand_props: core::config::ExpandProps::Bool(true), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import Svg from "react-native-svg"; +const SvgComponent = (props)=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +import Svg, { SvgProps } from "react-native-svg"; +const SvgComponent = (props: SvgProps)=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn with_native_ref_and_expand_props_option_adds_import_from_react_native_svg_and_adds_props_and_adds_forward_ref_component( + ) { + test_js_n_ts( + r#""#, + &core::config::Config { + native: Some(true), + expand_props: core::config::ExpandProps::Bool(true), + _ref: Some(true), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import Svg from "react-native-svg"; +import { forwardRef } from "react"; +const SvgComponent = (props, ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + r#"import * as React from "react"; +import Svg, { SvgProps } from "react-native-svg"; +import { Ref, forwardRef } from "react"; +const SvgComponent = (props: SvgProps, ref: Ref)=>; +const ForwardRef = forwardRef(SvgComponent); +export default ForwardRef; +"#, + ); + } + + #[test] + fn with_memo_option_wrap_component_in_react_memo() { + test_js_n_ts( + r#""#, + &core::config::Config { + memo: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import { memo } from "react"; +const SvgComponent = ()=>; +const Memo = memo(SvgComponent); +export default Memo; +"#, + r#"import * as React from "react"; +import { memo } from "react"; +const SvgComponent = ()=>; +const Memo = memo(SvgComponent); +export default Memo; +"#, + ); + } + + #[test] + fn with_both_memo_and_ref_option_wrap_component_in_react_memo_and_react_forward_ref() { + test_js_n_ts( + r#""#, + &core::config::Config { + memo: Some(true), + _ref: Some(true), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +import { forwardRef, memo } from "react"; +const SvgComponent = (_, ref)=>; +const ForwardRef = forwardRef(SvgComponent); +const Memo = memo(ForwardRef); +export default Memo; +"#, + r#"import * as React from "react"; +import { Ref, forwardRef, memo } from "react"; +const SvgComponent = (_, ref: Ref)=>; +const ForwardRef = forwardRef(SvgComponent); +const Memo = memo(ForwardRef); +export default Memo; +"#, + ); + } + + #[test] + fn with_named_export_option_and_previous_export_state_has_custom_named_export() { + test_js_n_ts( + r#""#, + &core::config::Config { + named_export: "Component".to_string(), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + caller: Some(core::state::Caller { + previous_export: Some( + "var img = new Image(); img.src = '...'; export default img;".to_string(), + ), + ..Default::default() + }), + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export { SvgComponent as Component }; +var img = new Image(); +img.src = '...'; +export default img; +"#, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export { SvgComponent as Component }; +var img = new Image(); +img.src = '...'; +export default img; +"#, + ); + } + + #[test] + fn with_named_export_and_export_type_option_and_without_previous_export_state_exports_via_named_export( + ) { + test_js_n_ts( + r#""#, + &core::config::Config { + named_export: "ReactComponent".to_string(), + export_type: Some(core::config::ExportType::Named), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + component_name: "SvgComponent".to_string(), + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export { SvgComponent as ReactComponent }; +"#, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export { SvgComponent as ReactComponent }; +"#, + ); + } + + // TODO: custom templates + + #[test] + fn jsx_runtime_supports_automatic_jsx_runtime() { + test_js_n_ts( + r#""#, + &core::config::Config { + jsx_runtime: Some(core::config::JSXRuntime::Automatic), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn jsx_runtime_supports_classic_jsx_runtime() { + test_js_n_ts( + r#""#, + &core::config::Config { + jsx_runtime: Some(core::config::JSXRuntime::Classic), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"import * as React from "react"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn allows_to_specify_a_custom_classic_jsx_runtime_using_specifiers() { + test_js_n_ts( + r#""#, + &core::config::Config { + jsx_runtime: Some(core::config::JSXRuntime::Classic), + jsx_runtime_import: Some(core::config::JSXRuntimeImport { + specifiers: Some(vec!["h".to_string()]), + source: "preact".to_string(), + ..Default::default() + }), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import { h } from "preact"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"import { h } from "preact"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn allows_to_specify_a_custom_classic_jsx_runtime_using_namespace() { + test_js_n_ts( + r#""#, + &core::config::Config { + jsx_runtime: Some(core::config::JSXRuntime::Classic), + jsx_runtime_import: Some(core::config::JSXRuntimeImport { + namespace: Some("Preact".to_string()), + source: "preact".to_string(), + ..Default::default() + }), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import * as Preact from "preact"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"import * as Preact from "preact"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + fn allows_to_specify_a_custom_classic_jsx_runtime_using_default_specifier() { + test_js_n_ts( + r#""#, + &core::config::Config { + jsx_runtime: Some(core::config::JSXRuntime::Classic), + jsx_runtime_import: Some(core::config::JSXRuntimeImport { + default_specifier: Some("h".to_string()), + source: "hyperapp-jsx-pragma".to_string(), + ..Default::default() + }), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#"import h from "hyperapp-jsx-pragma"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + r#"import h from "hyperapp-jsx-pragma"; +const SvgComponent = ()=>; +export default SvgComponent; +"#, + ); + } + + #[test] + #[should_panic( + expected = r#"called `Result::unwrap()` on an `Err` value: Configuration("Specify \"namespace\", \"defaultSpecifier\", or \"specifiers\" in \"jsxRuntimeImport\" option")"# + )] + fn throws_with_invalid_configuration() { + test_code( + r#""#, + &core::config::Config { + jsx_runtime: Some(core::config::JSXRuntime::Classic), + jsx_runtime_import: Some(core::config::JSXRuntimeImport { + source: "preact".to_string(), + ..Default::default() + }), + expand_props: core::config::ExpandProps::Bool(false), + ..Default::default() + }, + &core::state::InternalConfig { + ..Default::default() + }, + r#""#, + ); + } +} diff --git a/crates/svgr-rs/src/transform_svg_component/variables.rs b/crates/svgr-rs/src/transform_svg_component/variables.rs new file mode 100644 index 000000000..f3842817c --- /dev/null +++ b/crates/svgr-rs/src/transform_svg_component/variables.rs @@ -0,0 +1,607 @@ +use std::borrow::Borrow; +use std::sync::Arc; + +use swc_core::common::{FileName, SourceMap, SyntaxContext, DUMMY_SP}; +use swc_core::ecma::ast::*; +use swc_core::ecma::parser; + +use super::core; +use crate::SvgrError; + +pub struct TemplateVariables { + #[allow(dead_code)] + pub component_name: String, + pub interfaces: Vec, + pub props: Vec, + pub imports: Vec, + pub exports: Vec, + pub jsx: JSXElement, +} + +#[derive(Default)] +pub enum JSXRuntime { + Automatic, + #[default] + Classic, +} + +pub enum ExpandProps { + Bool(bool), + Start, + End, +} + +#[derive(Default)] +pub enum ExportType { + #[default] + Default, + Named, +} + +#[derive(Default)] +pub struct Options { + pub typescript: bool, + pub title_prop: bool, + pub desc_prop: bool, + pub expand_props: Option, + pub _ref: bool, + // pub template: Option>, + pub native: bool, + pub memo: bool, + pub export_type: ExportType, + pub named_export: Option, + pub jsx_runtime: JSXRuntime, + pub jsx_runtime_import: Option, + pub import_source: Option, +} + +pub fn get_variables( + opts: Options, + state: &core::state::InternalConfig, + jsx: JSXElement, +) -> Result { + let mut interfaces = vec![]; + let mut props = vec![]; + let mut imports = vec![]; + let mut exports = vec![]; + + let import_source = opts.import_source.unwrap_or("react".to_string()); + + let mut export_identifier = state.component_name.clone(); + + let is_automatic = matches!(opts.jsx_runtime, JSXRuntime::Automatic); + if !is_automatic { + match opts.jsx_runtime_import { + Some(jsx_runtime_import) => { + let jsx_runtime_import = get_jsx_runtime_import(&jsx_runtime_import)?; + imports.push(jsx_runtime_import); + } + None => { + let default_jsx_runtime_import = core::config::JSXRuntimeImport { + source: "react".to_string(), + namespace: Some("React".to_string()), + ..Default::default() + }; + let jsx_runtime_import = get_jsx_runtime_import(&default_jsx_runtime_import)?; + imports.push(jsx_runtime_import); + } + } + } + + if opts.native { + let specifier = ImportSpecifier::Default(ImportDefaultSpecifier { + span: DUMMY_SP, + local: Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: "Svg".into(), + optional: false, + }, + }); + get_or_create_import(&mut imports, "react-native-svg", specifier); + } + + if opts.title_prop || opts.desc_prop { + let mut properties = vec![]; + let mut property_signatures = vec![]; + + if opts.title_prop { + properties.push(create_property("title")); + properties.push(create_property("titleId")); + + if opts.typescript { + property_signatures.push(create_signature("title")); + property_signatures.push(create_signature("titleId")); + } + } + + if opts.desc_prop { + properties.push(create_property("desc")); + properties.push(create_property("descId")); + + if opts.typescript { + property_signatures.push(create_signature("desc")); + property_signatures.push(create_signature("descId")); + } + } + + let mut prop = ObjectPat { + span: DUMMY_SP, + props: properties, + optional: false, + type_ann: None, + }; + + if opts.typescript { + let interface = + ModuleItem::Stmt(Stmt::Decl(Decl::TsInterface(Box::new(TsInterfaceDecl { + id: Ident::new("SVGRProps".into(), DUMMY_SP, SyntaxContext::empty()), + span: DUMMY_SP, + declare: false, + type_params: None, + extends: vec![], + body: TsInterfaceBody { + span: DUMMY_SP, + body: property_signatures, + }, + })))); + interfaces.push(interface); + + prop.type_ann = Some(Box::new(TsTypeAnn { + span: DUMMY_SP, + type_ann: Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "SVGRProps".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: None, + })), + })); + } + + props.push(Pat::Object(prop)); + } + + let need_expand_props = match opts.expand_props { + None => false, + Some(ExpandProps::Bool(expand_props)) => expand_props, + _ => true, + }; + if need_expand_props { + let existing = if !props.is_empty() { + if let Pat::Object(ref mut object_pat) = props[0] { + let identifier = Pat::Ident(BindingIdent::from(Ident::new( + "props".into(), + DUMMY_SP, + SyntaxContext::empty(), + ))); + object_pat.props.push(ObjectPatProp::Rest(RestPat { + span: DUMMY_SP, + dot3_token: DUMMY_SP, + arg: Box::new(identifier), + type_ann: None, + })); + + if opts.typescript { + let svg_props_type = + ts_type_reference_svg_props(&mut imports, opts.native, &import_source); + let type_ann = Box::new(TsType::TsUnionOrIntersectionType( + TsUnionOrIntersectionType::TsIntersectionType(TsIntersectionType { + span: DUMMY_SP, + types: vec![ + svg_props_type, + Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "SVGRProps".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: None, + })), + ], + }), + )); + object_pat.type_ann = Some(Box::new(TsTypeAnn { + span: DUMMY_SP, + type_ann, + })); + } + + true + } else { + false + } + } else { + false + }; + + if !existing { + let mut prop = + BindingIdent::from(Ident::new("props".into(), DUMMY_SP, SyntaxContext::empty())); + + if opts.typescript { + let type_ann = + ts_type_reference_svg_props(&mut imports, opts.native, &import_source); + prop.type_ann = Some(Box::new(TsTypeAnn { + span: DUMMY_SP, + type_ann, + })); + } + + props.push(Pat::Ident(prop)); + } + } + + if opts._ref { + if props.is_empty() { + props.push(Pat::Ident(BindingIdent::from(Ident::new( + "_".into(), + DUMMY_SP, + SyntaxContext::empty(), + )))); + } + let mut prop = + BindingIdent::from(Ident::new("ref".into(), DUMMY_SP, SyntaxContext::empty())); + + if opts.typescript { + get_or_create_named_import(&mut imports, "react", "Ref"); + + prop.type_ann = Some(Box::new(TsTypeAnn { + span: DUMMY_SP, + type_ann: Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "Ref".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: Some(Box::new(TsTypeParamInstantiation { + span: DUMMY_SP, + params: vec![Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "SVGSVGElement".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: None, + }))], + })), + })), + })); + } + + props.push(Pat::Ident(prop)); + + get_or_create_named_import(&mut imports, &import_source, "forwardRef"); + let hoc = create_var_decl_init_hoc("ForwardRef", "forwardRef", &export_identifier); + exports.push(hoc); + export_identifier = "ForwardRef".to_string(); + } + + if opts.memo { + get_or_create_named_import(&mut imports, &import_source, "memo"); + let hoc = create_var_decl_init_hoc("Memo", "memo", &export_identifier); + exports.push(hoc); + export_identifier = "Memo".to_string(); + } + + let need_named_export = if state.caller.is_some() { + true + } else { + matches!(opts.export_type, ExportType::Named) + }; + if need_named_export { + if let Some(named_export) = opts.named_export { + let specifier = ExportSpecifier::Named(ExportNamedSpecifier { + span: DUMMY_SP, + orig: ModuleExportName::Ident(Ident::new( + export_identifier.clone().into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + exported: Some(ModuleExportName::Ident(Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: named_export.into(), + optional: false, + })), + is_type_only: false, + }); + + exports.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed( + NamedExport { + span: DUMMY_SP, + specifiers: vec![specifier], + src: None, + type_only: false, + with: None, + }, + ))); + + if let Some(caller) = &state.caller { + if let Some(previous_export) = caller.previous_export.clone() { + let cm = Arc::::default(); + let fm = cm.new_source_file(FileName::Anon.into(), previous_export); + + let mut recovered_errors = vec![]; + let module = parser::parse_file_as_module( + fm.borrow(), + parser::Syntax::Es(parser::EsSyntax { + jsx: true, + ..Default::default() + }), + EsVersion::Es2020, + None, + &mut recovered_errors, + ) + .unwrap(); + for module_item in module.body { + exports.push(module_item) + } + } + } + } else { + return Err(SvgrError::Configuration( + r#""namedExport" not specified"#.to_string(), + )); + } + } + + if !need_named_export { + exports.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr( + ExportDefaultExpr { + span: DUMMY_SP, + expr: Box::new(Expr::Ident(Ident::new( + export_identifier.into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + }, + ))); + } + + Ok(TemplateVariables { + component_name: state.component_name.clone(), + interfaces, + props, + imports, + exports, + jsx, + }) +} + +fn get_jsx_runtime_import(cfg: &core::config::JSXRuntimeImport) -> Result { + let specifiers = get_jsx_runtime_import_specifiers(cfg)?; + + Ok(ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + span: DUMMY_SP, + specifiers, + src: Box::new(Str { + span: DUMMY_SP, + value: cfg.source.clone().into(), + raw: None, + }), + type_only: false, + with: None, + phase: Default::default(), + }))) +} + +fn get_jsx_runtime_import_specifiers( + cfg: &core::config::JSXRuntimeImport, +) -> Result, SvgrError> { + if let Some(namespace) = cfg.namespace.clone() { + let specifier = ImportSpecifier::Namespace(ImportStarAsSpecifier { + span: DUMMY_SP, + local: Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: namespace.into(), + optional: false, + }, + }); + return Ok(vec![specifier]); + } + + if let Some(default_specifier) = cfg.default_specifier.clone() { + let specifier = ImportSpecifier::Default(ImportDefaultSpecifier { + span: DUMMY_SP, + local: Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: default_specifier.into(), + optional: false, + }, + }); + return Ok(vec![specifier]); + } + + if let Some(specifiers) = cfg.specifiers.clone() { + let mut import_specifiers = vec![]; + for specifier in specifiers { + import_specifiers.push(ImportSpecifier::Named(ImportNamedSpecifier { + span: DUMMY_SP, + local: Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: specifier.into(), + optional: false, + }, + imported: None, + is_type_only: false, + })); + } + return Ok(import_specifiers); + } + + Err(SvgrError::Configuration( + r#"Specify "namespace", "defaultSpecifier", or "specifiers" in "jsxRuntimeImport" option"# + .to_string(), + )) +} + +fn get_or_create_import( + imports: &mut Vec, + source_value: &str, + specifier: ImportSpecifier, +) { + let mut existing = None; + for import in imports.iter_mut() { + if let ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) = import { + let is_namespace_import = import_decl + .specifiers + .iter() + .any(|specifier| matches!(specifier, ImportSpecifier::Namespace(_))); + if !is_namespace_import && import_decl.src.value == source_value { + existing = Some(import_decl); + break; + } + } + } + + if let Some(import_decl) = existing { + import_decl.specifiers.push(specifier); + return; + } + + let module_item = ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + span: DUMMY_SP, + specifiers: vec![specifier], + src: Box::new(Str { + span: DUMMY_SP, + value: source_value.into(), + raw: None, + }), + type_only: false, + with: None, + phase: Default::default(), + })); + imports.push(module_item); +} + +fn get_or_create_named_import(imports: &mut Vec, source_value: &str, name: &str) { + let specifier = ImportSpecifier::Named(ImportNamedSpecifier { + span: DUMMY_SP, + local: Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: name.into(), + optional: false, + }, + imported: None, + is_type_only: false, + }); + get_or_create_import(imports, source_value, specifier) +} + +fn create_var_decl_init_hoc(var_name: &str, callee: &str, component_name: &str) -> ModuleItem { + ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + kind: VarDeclKind::Const, + declare: false, + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent::from(Ident::new( + var_name.into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + definite: false, + init: Some(Box::new(Expr::Call(CallExpr { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + callee.into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(Expr::Ident(Ident::new( + component_name.into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + }], + type_args: None, + }))), + }], + })))) +} + +fn create_property(key: &str) -> ObjectPatProp { + ObjectPatProp::Assign(AssignPatProp { + span: DUMMY_SP, + key: Ident::new(key.into(), DUMMY_SP, SyntaxContext::empty()).into(), + value: None, + }) +} + +fn create_signature(key: &str) -> TsTypeElement { + TsTypeElement::TsPropertySignature(TsPropertySignature { + span: DUMMY_SP, + readonly: false, + key: Box::new(Expr::Ident(Ident::new( + key.into(), + DUMMY_SP, + SyntaxContext::empty(), + ))), + computed: false, + optional: true, + type_ann: Some(Box::new(TsTypeAnn { + span: DUMMY_SP, + type_ann: Box::new(TsType::TsKeywordType(TsKeywordType { + span: DUMMY_SP, + kind: TsKeywordTypeKind::TsStringKeyword, + })), + })), + }) +} + +fn ts_type_reference_svg_props( + imports: &mut Vec, + native: bool, + import_source: &str, +) -> Box { + if native { + get_or_create_named_import(imports, "react-native-svg", "SvgProps"); + + return Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "SvgProps".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: None, + })); + } + + get_or_create_named_import(imports, import_source, "SVGProps"); + + Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "SVGProps".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: Some(Box::new(TsTypeParamInstantiation { + span: DUMMY_SP, + params: vec![Box::new(TsType::TsTypeRef(TsTypeRef { + span: DUMMY_SP, + type_name: TsEntityName::Ident(Ident::new( + "SVGSVGElement".into(), + DUMMY_SP, + SyntaxContext::empty(), + )), + type_params: None, + }))], + })), + })) +} diff --git a/docs/config.md b/docs/config.md index b7eec7cd8..2f6ed7799 100644 --- a/docs/config.md +++ b/docs/config.md @@ -392,11 +392,28 @@ Notice: This configuration can only be used with umd, because injecting CSS is n ### inlineLimit -- Type: `number` -- Default: `10000` +- Type: `string[]` +- Default: `[]` Specify the size limit of the assets file that needs to be converted to `base64` format. + +### inlineExcludesExtensions + +- Type: `string[]` +- Default: `[]` + +Excludes assets file extension list that don't need to be converted to `base64` format. + +e.g. + +```ts +{ + "inlineExcludesExtensions": ["webp"] +} +``` + + ### less - Type: `{ modifyVars?: Record, globalVars?: Record, sourceMap?: { sourceMapFileInline?: boolean, outputSourceFiles?: boolean }, math?: "always" | "strict" | "parens-division" | "parens" | "strict-legacy" | number, plugins?: ([string, Record]|string)[] }` @@ -527,6 +544,8 @@ Specify the plugins to use. }; }) => void; load?: (filePath: string) => Promise<{ content: string, type: 'css'|'js'|'jsx'|'ts'|'tsx' }>; + loadInclude?: (filePath: string) => boolean; + resolveId?: (id: string, importer: string, { isEntry: bool }) => Promise<{ id: string, external: bool }>; } ``` diff --git a/docs/config.zh-CN.md b/docs/config.zh-CN.md index 819f92a78..0e9845571 100644 --- a/docs/config.zh-CN.md +++ b/docs/config.zh-CN.md @@ -398,6 +398,22 @@ e.g. 指定需要转换为 `base64` 格式的资产文件的大小限制。 + +### inlineExcludesExtensions + +- 类型: `string[]` +- 默认值: `[]` + +指定不需要转换为 `base64` 格式的资产文件的后缀名列表。 + +例如: + +```ts +{ + "inlineExcludesExtensions": ["webp"] +} +``` + ### less - 类型:`{ modifyVars?: Record, globalVars?: Record, sourceMap?: { sourceMapFileInline?: boolean, outputSourceFiles?: boolean }, math?: "always" | "strict" | "parens-division" | "parens" | "strict-legacy" | number, plugins?: ([string, Record]|string)[] }` @@ -528,6 +544,8 @@ e.g. }; }) => void; load?: (filePath: string) => Promise<{ content: string, type: 'css'|'js'|'jsx'|'ts'|'tsx' }>; + loadInclude?: (filePath: string) => boolean; + resolveId?: (id: string, importer: string, { isEntry: bool }) => Promise<{ id: string, external: bool }>; } ``` diff --git a/e2e/fixtures/config.inline_excludes_regexes/expect.js b/e2e/fixtures/config.inline_excludes_regexes/expect.js new file mode 100644 index 000000000..11b0ea09f --- /dev/null +++ b/e2e/fixtures/config.inline_excludes_regexes/expect.js @@ -0,0 +1,8 @@ +const assert = require("assert"); +const { parseBuildResult } = require("../../../scripts/test-utils"); +const { files } = parseBuildResult(__dirname); + +const names = Object.keys(files).join(","); + +// check files +assert.match(names, /abc.(.*).webp/, "should have origin webp"); diff --git a/e2e/fixtures/config.inline_excludes_regexes/mako.config.json b/e2e/fixtures/config.inline_excludes_regexes/mako.config.json new file mode 100644 index 000000000..1706e6daf --- /dev/null +++ b/e2e/fixtures/config.inline_excludes_regexes/mako.config.json @@ -0,0 +1,4 @@ +{ + "inlineExcludesExtensions": ["webp"], + "inlineLimit": 1000000 +} diff --git a/e2e/fixtures/config.inline_excludes_regexes/src/abc.webp b/e2e/fixtures/config.inline_excludes_regexes/src/abc.webp new file mode 100644 index 000000000..71c4310e9 Binary files /dev/null and b/e2e/fixtures/config.inline_excludes_regexes/src/abc.webp differ diff --git a/e2e/fixtures/config.inline_excludes_regexes/src/index.tsx b/e2e/fixtures/config.inline_excludes_regexes/src/index.tsx new file mode 100644 index 000000000..a58cc868b --- /dev/null +++ b/e2e/fixtures/config.inline_excludes_regexes/src/index.tsx @@ -0,0 +1,3 @@ + +import a from './abc.webp' +console.log(a) diff --git a/e2e/fixtures/plugins/expect.js b/e2e/fixtures/plugins/expect.js index 848af158a..433942d89 100644 --- a/e2e/fixtures/plugins/expect.js +++ b/e2e/fixtures/plugins/expect.js @@ -8,3 +8,7 @@ assert(content.includes(`children: "foo.bar"`), `jsx in foo.bar works`); assert(content.includes(`children: ".bar"`), `jsx in hoo.bar works`); assert(content.includes(`children: ".haha"`), `plugin in node_modules works`); assert(content.includes(`children: ".hoo"`), `relative plugin works`); + +// resolve_id hook +assert(content.includes(`resolve_id mocked`), `resolve_id hook works`); +assert(content.includes(`module.exports = resolve_id_external;`), `resolve_id hook with external works`); diff --git a/e2e/fixtures/plugins/plugins.config.js b/e2e/fixtures/plugins/plugins.config.js index 5331b5b42..2dbeafc23 100644 --- a/e2e/fixtures/plugins/plugins.config.js +++ b/e2e/fixtures/plugins/plugins.config.js @@ -11,13 +11,26 @@ module.exports = [ } }, { - async load(path) { - if (path.endsWith('.bar')) { - return { - content: `export default () => .bar;`, - type: 'jsx', - }; + async loadInclude(path) { + return path.endsWith('.bar'); + }, + async load() { + return { + content: `export default () => .bar;`, + type: 'jsx', + }; + } + }, + { + async resolveId(source, importer, options) { + console.log('resolveId', source, importer, options); + if (source === 'resolve_id') { + return { id: require('path').join(__dirname, 'resolve_id_mock.js'), external: false }; } + if (source === 'resolve_id_external') { + return { id: 'resolve_id_external', external: true }; + } + return null; } - } + }, ]; diff --git a/e2e/fixtures/plugins/resolve_id_mock.js b/e2e/fixtures/plugins/resolve_id_mock.js new file mode 100644 index 000000000..39e08b0a5 --- /dev/null +++ b/e2e/fixtures/plugins/resolve_id_mock.js @@ -0,0 +1 @@ +console.log('resolve_id mocked'); diff --git a/e2e/fixtures/plugins/src/index.tsx b/e2e/fixtures/plugins/src/index.tsx index a936a668a..b53b90ae7 100644 --- a/e2e/fixtures/plugins/src/index.tsx +++ b/e2e/fixtures/plugins/src/index.tsx @@ -2,3 +2,5 @@ console.log(require('./foo.bar')); console.log(require('./hoo.bar')); console.log(require('./foo.haha')); console.log(require('./foo.hoo')); +console.log(require('resolve_id')); +console.log(require('resolve_id_external')); diff --git a/examples/dead-simple/app.tsx b/examples/dead-simple/app.tsx new file mode 100644 index 000000000..1a05af128 --- /dev/null +++ b/examples/dead-simple/app.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function App() { + return
Hello, world!
; +} diff --git a/examples/dead-simple/index.ts b/examples/dead-simple/index.ts index e53c31d05..400ee215a 100644 --- a/examples/dead-simple/index.ts +++ b/examples/dead-simple/index.ts @@ -1,6 +1,9 @@ -import { foo } from './foo'; -import './foo/foo'; +// import { foo } from './foo'; +// import './foo/foo'; + +import App from './app'; + /** * abcd */ -console.log(foo); +console.log(App); diff --git a/package.json b/package.json index 24c29a888..8e5651539 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test:e2e": "node scripts/test-e2e.mjs", "test:umi": "node scripts/test-e2e.mjs --fixtures e2e/fixtures.umi --umi", "test:hmr": "node scripts/test-hmr.mjs", - "release": "esno scripts/release.ts", + "release": "npm run release:mako && npm run release:bundler-mako", "release:mako": "pnpm --filter @umijs/mako release", "release:bundler-mako": "esno scripts/release-bundler-mako.ts", "release:rsc": "esno scripts/release-rsc.ts", diff --git a/packages/bundler-mako/index.js b/packages/bundler-mako/index.js index c9155ed36..43ff235df 100644 --- a/packages/bundler-mako/index.js +++ b/packages/bundler-mako/index.js @@ -120,6 +120,12 @@ exports.dev = async function (opts) { app.use( proxy(`http://127.0.0.1:${hmrPort}`, { + proxyReqOptDecorator: function (proxyReqOpts) { + // keep alive is on by default https://nodejs.org/docs/latest/api/http.html#httpglobalagent + // 禁用 keep-alive + proxyReqOpts.agent = false; + return proxyReqOpts; + }, filter: function (req, res) { return req.method == 'GET' || req.method == 'HEAD'; }, @@ -630,6 +636,8 @@ async function getMakoConfig(opts) { plugins: opts.config.lessLoader?.plugins, }, analyze: analyze || process.env.ANALYZE ? {} : undefined, + sass: sassLoader, + ...mako, experimental: { webpackSyntaxValidate: [], requireContext: true, @@ -637,9 +645,8 @@ async function getMakoConfig(opts) { ignores: ['node_modules', '\\.umi'], graphviz: false, }, + ...mako.experimental, }, - sass: sassLoader, - ...mako, }; return makoConfig; diff --git a/packages/bundler-mako/package.json b/packages/bundler-mako/package.json index e84d9a680..5bbed2d87 100644 --- a/packages/bundler-mako/package.json +++ b/packages/bundler-mako/package.json @@ -1,9 +1,9 @@ { "name": "@umijs/bundler-mako", - "version": "0.8.13", + "version": "0.8.15", "dependencies": { "@umijs/bundler-utils": "^4.0.81", - "@umijs/mako": "0.8.13", + "@umijs/mako": "0.8.15", "chalk": "^4.1.2", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", diff --git a/packages/mako/npm/darwin-arm64/package.json b/packages/mako/npm/darwin-arm64/package.json index f11dd650a..51f885afa 100644 --- a/packages/mako/npm/darwin-arm64/package.json +++ b/packages/mako/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-darwin-arm64", - "version": "0.8.13", + "version": "0.8.15", "os": [ "darwin" ], diff --git a/packages/mako/npm/darwin-x64/package.json b/packages/mako/npm/darwin-x64/package.json index 21a0a4f27..131214861 100644 --- a/packages/mako/npm/darwin-x64/package.json +++ b/packages/mako/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-darwin-x64", - "version": "0.8.13", + "version": "0.8.15", "os": [ "darwin" ], diff --git a/packages/mako/npm/linux-arm64-gnu/package.json b/packages/mako/npm/linux-arm64-gnu/package.json index 77a6d7e65..32dedc9f2 100644 --- a/packages/mako/npm/linux-arm64-gnu/package.json +++ b/packages/mako/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-linux-arm64-gnu", - "version": "0.8.13", + "version": "0.8.15", "os": [ "linux" ], diff --git a/packages/mako/npm/linux-arm64-musl/package.json b/packages/mako/npm/linux-arm64-musl/package.json index bb3e84d99..0fa3d86d4 100644 --- a/packages/mako/npm/linux-arm64-musl/package.json +++ b/packages/mako/npm/linux-arm64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-linux-arm64-musl", - "version": "0.8.13", + "version": "0.8.15", "os": [ "linux" ], diff --git a/packages/mako/npm/linux-x64-gnu/package.json b/packages/mako/npm/linux-x64-gnu/package.json index 43596f589..1a998460f 100644 --- a/packages/mako/npm/linux-x64-gnu/package.json +++ b/packages/mako/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-linux-x64-gnu", - "version": "0.8.13", + "version": "0.8.15", "os": [ "linux" ], diff --git a/packages/mako/npm/linux-x64-musl/package.json b/packages/mako/npm/linux-x64-musl/package.json index 02faf49c9..990c89d59 100644 --- a/packages/mako/npm/linux-x64-musl/package.json +++ b/packages/mako/npm/linux-x64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-linux-x64-musl", - "version": "0.8.13", + "version": "0.8.15", "os": [ "linux" ], diff --git a/packages/mako/npm/win32-ia32-msvc/package.json b/packages/mako/npm/win32-ia32-msvc/package.json index d725b4c9a..3b7d26795 100644 --- a/packages/mako/npm/win32-ia32-msvc/package.json +++ b/packages/mako/npm/win32-ia32-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-win32-ia32-msvc", - "version": "0.8.13", + "version": "0.8.15", "os": [ "win32" ], diff --git a/packages/mako/npm/win32-x64-msvc/package.json b/packages/mako/npm/win32-x64-msvc/package.json index 311bb4faf..7136d84fc 100644 --- a/packages/mako/npm/win32-x64-msvc/package.json +++ b/packages/mako/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako-win32-x64-msvc", - "version": "0.8.13", + "version": "0.8.15", "os": [ "win32" ], diff --git a/packages/mako/package.json b/packages/mako/package.json index 875b6f4e7..84b2b589a 100644 --- a/packages/mako/package.json +++ b/packages/mako/package.json @@ -1,6 +1,6 @@ { "name": "@umijs/mako", - "version": "0.8.13", + "version": "0.8.15", "main": "dist/index.js", "types": "dist/index.d.ts", "bin": { @@ -71,20 +71,18 @@ "universal": "napi universal", "version": "napi version", "release": "esno scripts/release.ts", - "release:quick": "esno scripts/quick-release.ts", - "release:build": "esno scripts/release.ts --build", "src:dev": "father dev", "src:build": "father build" }, "optionalDependencies": { - "@umijs/mako-darwin-arm64": "0.8.13", - "@umijs/mako-linux-arm64-gnu": "0.8.13", - "@umijs/mako-linux-arm64-musl": "0.8.13", - "@umijs/mako-win32-ia32-msvc": "0.8.13", - "@umijs/mako-darwin-x64": "0.8.13", - "@umijs/mako-win32-x64-msvc": "0.8.13", - "@umijs/mako-linux-x64-gnu": "0.8.13", - "@umijs/mako-linux-x64-musl": "0.8.13" + "@umijs/mako-darwin-arm64": "0.8.15", + "@umijs/mako-linux-arm64-gnu": "0.8.15", + "@umijs/mako-linux-arm64-musl": "0.8.15", + "@umijs/mako-win32-ia32-msvc": "0.8.15", + "@umijs/mako-darwin-x64": "0.8.15", + "@umijs/mako-win32-x64-msvc": "0.8.15", + "@umijs/mako-linux-x64-gnu": "0.8.15", + "@umijs/mako-linux-x64-musl": "0.8.15" }, "repository": "git@github.com:umijs/mako.git" -} \ No newline at end of file +} diff --git a/packages/mako/scripts/quick-release.ts b/packages/mako/scripts/quick-release.ts deleted file mode 100644 index ccd12ffe0..000000000 --- a/packages/mako/scripts/quick-release.ts +++ /dev/null @@ -1,58 +0,0 @@ -import assert from 'assert'; -import 'zx/globals'; -import { - ensureGitStatus, - loadPkg, - pushToGit, - queryNewVersion, - rootPkgPath, - setNewVersionToBundlerMako, -} from './utils'; - -(async () => { - await run(); -})().catch((e) => { - console.error(e); - process.exit(1); -}); - -async function run() { - await ensureGitStatus(); - - const commitId = (await $`git rev-parse HEAD`).stdout.trim(); - const artifactsFile = `artifacts-${commitId}.zip`; - const hasArtifacts = fs.existsSync(path.join(process.cwd(), artifactsFile)); - assert(hasArtifacts, `${artifactsFile} not found in cwd`); - - const nodePkgPath = rootPkgPath(); - const nodePkg = loadPkg(nodePkgPath); - const { newVersion, tag, branch } = await queryNewVersion(nodePkg); - - nodePkg.version = newVersion; - fs.writeFileSync(nodePkgPath, JSON.stringify(nodePkg, null, 2) + '\n'); - - await build(); - await artifacts(artifactsFile); - - await $`npm publish --tag ${tag} --access public`; - - setNewVersionToBundlerMako(nodePkg.version); - - await pushToGit(nodePkg, branch); -} - -async function build() { - await $`rm -rf ./*.node`; - await $`find ./npm -name '*.node' | xargs rm -f`; - await $`rm -rf ./dist`; - - await $`pnpm run build`; - await $`pnpm run src:build`; - await $`pnpm run format`; -} - -async function artifacts(artifactsFile: string) { - await $`rm -rf *.node`; - await $`unzip ${artifactsFile}`; - await $`npm run artifacts:local`; -} diff --git a/packages/mako/scripts/release.ts b/packages/mako/scripts/release.ts index 12372f602..ccd12ffe0 100644 --- a/packages/mako/scripts/release.ts +++ b/packages/mako/scripts/release.ts @@ -1,3 +1,4 @@ +import assert from 'assert'; import 'zx/globals'; import { ensureGitStatus, @@ -9,11 +10,7 @@ import { } from './utils'; (async () => { - if (argv.build) { - await build(); - } else { - await run(); - } + await run(); })().catch((e) => { console.error(e); process.exit(1); @@ -22,17 +19,20 @@ import { async function run() { await ensureGitStatus(); - // check docker status - console.log('Check docker status'); - await $`docker ps`; + const commitId = (await $`git rev-parse HEAD`).stdout.trim(); + const artifactsFile = `artifacts-${commitId}.zip`; + const hasArtifacts = fs.existsSync(path.join(process.cwd(), artifactsFile)); + assert(hasArtifacts, `${artifactsFile} not found in cwd`); const nodePkgPath = rootPkgPath(); const nodePkg = loadPkg(nodePkgPath); const { newVersion, tag, branch } = await queryNewVersion(nodePkg); + nodePkg.version = newVersion; fs.writeFileSync(nodePkgPath, JSON.stringify(nodePkg, null, 2) + '\n'); await build(); + await artifacts(artifactsFile); await $`npm publish --tag ${tag} --access public`; @@ -42,84 +42,17 @@ async function run() { } async function build() { - // clean await $`rm -rf ./*.node`; await $`find ./npm -name '*.node' | xargs rm -f`; await $`rm -rf ./dist`; - // build linux *.node - console.log('linux building started...'); - const start = Date.now(); - const cargoRoot = path.join(__dirname, '../../..'); - // clean sailfish - // since its lock files may cause build error - await $`rm -rf ${cargoRoot}/target/release/build/sailfish*`; - await build_linux_binding('gnu'); - await build_linux_binding('musl'); - await $`pnpm run format`; - const duration = (Date.now() - start) / 1000; - console.log(`linux building done ${duration}s`); - - // build macos *.node - await $`cargo build --lib -r --target x86_64-apple-darwin`; - await $`pnpm run build:mac:x86`; - await $`cargo build --lib -r --target aarch64-apple-darwin`; - await $`pnpm run build:mac:aarch`; - await $`strip -x ./mako.darwin-*.node`; - - // build src + await $`pnpm run build`; await $`pnpm run src:build`; await $`pnpm run format`; - - // move artifacts to npm - await $`pnpm run artifacts:local`; } -async function build_linux_binding(cLib: 'musl' | 'gnu') { - const isArm = process.arch === 'arm64'; - const cargoBase = path.join( - process.env['CARGO_HOME'] || process.env['HOME']!, - '.cargo', - ); - const cargoMapOption = (p: string) => [ - '-v', - `${path.join(cargoBase, p)}:${path.join('/usr/local/cargo', p)}`, - ]; - const rustupRoot = path.join(os.homedir(), '.rustup'); - const makoRoot = path.join(__dirname, '../../..'); - const volumeOptions = [ - ...cargoMapOption('config'), - ...cargoMapOption('git/db'), - ...cargoMapOption('registry/cache'), - ...cargoMapOption('registry/index'), - ...[`-v`, `${makoRoot}:/build`], - ...[`-v`, `${rustupRoot}:/usr/local/rustup`], - ...[`-w`, `/build`], - ]; - const containerCMD = [ - `cargo build -r --lib --target x86_64-unknown-linux-${cLib}`, - 'cd packages/mako', - `npm run build:linux:${cLib}`, - 'strip mako.linux*.node', - ].join('&&'); - const envOptions: string[] = []; - if (process.env['RUSTUP_DIST_SERVER']) { - envOptions.push( - ...['-e', `RUSTUP_DIST_SERVER=${process.env['RUSTUP_DIST_SERVER']}`], - ); - } - if (process.env[`RUSTUP_UPDATE_ROOT`]) { - envOptions.push( - ...['-e', `RUSTUP_UPDATE_ROOT=${process.env[`RUSTUP_UPDATE_ROOT`]}`], - ); - } - const options = ['--rm', ...volumeOptions, ...envOptions]; - if (isArm) { - options.push(...['--platform', 'linux/amd64']); - } - const image = - cLib === 'gnu' - ? 'ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian' - : 'ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine'; - await $`docker run ${options} ${image} bash -c ${containerCMD}`; +async function artifacts(artifactsFile: string) { + await $`rm -rf *.node`; + await $`unzip ${artifactsFile}`; + await $`npm run artifacts:local`; } diff --git a/packages/mako/src/binding.d.ts b/packages/mako/src/binding.d.ts index a9989c8a2..b99643f94 100644 --- a/packages/mako/src/binding.d.ts +++ b/packages/mako/src/binding.d.ts @@ -8,6 +8,7 @@ export interface JsHooks { load?: ( filePath: string, ) => Promise<{ content: string; type: 'css' | 'js' } | void> | void; + loadInclude?: (filePath: string) => Promise | bool; generateEnd?: (data: { isFirstCompile: boolean; time: number; @@ -51,6 +52,26 @@ export interface JsHooks { }) => void; onGenerateFile?: (path: string, content: Buffer) => Promise; buildStart?: () => Promise; + resolveId?: ( + source: string, + importer: string, + { isEntry: bool }, + ) => Promise<{ id: string }>; +} +export interface WriteFile { + path: string; + content: Buffer; +} +export interface LoadResult { + content: string; + type: string; +} +export interface ResolveIdResult { + id: string; + external: boolean | null; +} +export interface ResolveIdParams { + isEntry: boolean; } export interface BuildParams { root: string; @@ -223,4 +244,4 @@ export interface BuildParams { plugins: Array; watch: boolean; } -export function build(buildParams: BuildParams): Promise; +export declare function build(buildParams: BuildParams): Promise; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfcfdddd8..a770e96ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -436,7 +436,7 @@ importers: specifier: ^4.0.81 version: 4.1.6 '@umijs/mako': - specifier: 0.8.13 + specifier: 0.8.15 version: link:../mako chalk: specifier: ^4.1.2 @@ -537,29 +537,29 @@ importers: version: 21.1.1 optionalDependencies: '@umijs/mako-darwin-arm64': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-darwin-x64': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-linux-arm64-gnu': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-linux-arm64-musl': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-linux-x64-gnu': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-linux-x64-musl': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-win32-ia32-msvc': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 '@umijs/mako-win32-x64-msvc': - specifier: 0.8.13 - version: 0.8.13 + specifier: 0.8.15 + version: 0.8.15 devDependencies: '@napi-rs/cli': specifier: ^2.18.0 @@ -6512,8 +6512,8 @@ packages: dev: true optional: true - /@umijs/mako-darwin-arm64@0.8.13: - resolution: {integrity: sha512-PyFNH4GIUHJVXPNcs5g6GzHWoRpesBToNleYbsiih1hYNYX2nS6XDrufth4zhm10X/JZ/FCyW5rQOF57t5w+dw==} + /@umijs/mako-darwin-arm64@0.8.15: + resolution: {integrity: sha512-wuOB43kmCFDj5tK1xKI7vUDtPaU+qLxQcvxFCpgSuMlTLPzm5lvKr47nCZ1/46KWvt+ns5OMEYmwD7XwVy75mQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -6530,8 +6530,8 @@ packages: dev: true optional: true - /@umijs/mako-darwin-x64@0.8.13: - resolution: {integrity: sha512-LS6XHhKiSn2fPdKa2Sb0W2o5Ftl93/AC+JNQdeM+ya7sCD+qn55HrT20s2/u7xIMKg7nsy7soGy2+gBrcPu1lQ==} + /@umijs/mako-darwin-x64@0.8.15: + resolution: {integrity: sha512-L4bC7YG1t6MDO87Hmc6E8IOVWqKYT4Anneegc9QOVlBbvGWuJQcUBQaTrlceXbhSTkEEJVAJ7nl7qhBZDBM9qw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -6539,8 +6539,8 @@ packages: dev: false optional: true - /@umijs/mako-linux-arm64-gnu@0.8.13: - resolution: {integrity: sha512-lvz8fnY5TzArfk9h+Kfuq+L586l8oEEa9s7BHzSf7Lpv0/BCvjusTt8UjhyryHGeC05O87XXhs16jO7vLhSbBQ==} + /@umijs/mako-linux-arm64-gnu@0.8.15: + resolution: {integrity: sha512-SWzw6lYd5JNmBbqEZfobfK5QFl3tanFm3KJm2sUmXDsruTCCWDd4sLNxcg7b+zh1ptsBT7aghc6fl4g+r0rXaw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -6548,8 +6548,8 @@ packages: dev: false optional: true - /@umijs/mako-linux-arm64-musl@0.8.13: - resolution: {integrity: sha512-iVChkN2Zf1UiXZEVjfYxmjZiMJp2IDbPiysP8zpF7Wl8NvtvrlT7w9V+7U/2CR7VLYzmwWUc7X94PJUXKAXdMw==} + /@umijs/mako-linux-arm64-musl@0.8.15: + resolution: {integrity: sha512-uQxwLmxBijaIuge+uPNaGgaO7NhywiD9oOvJGcLjReKYZ24YigN9vDjrCQU9lbUF103d5oxpd5T8caViABwJuw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -6566,8 +6566,8 @@ packages: dev: true optional: true - /@umijs/mako-linux-x64-gnu@0.8.13: - resolution: {integrity: sha512-0tLZ1vD3B9wRr0lruI8/520IlMbnFTbfzOArGyaAQechGmCaPQx1mQcw+KVWqGUxk5z6U/XNMrP/EC9629i3Sw==} + /@umijs/mako-linux-x64-gnu@0.8.15: + resolution: {integrity: sha512-S0QCESwrmYeB8WQeUfe0oj7F83nsH3YHH6wS0wnIGcE3K6yHWQB73ygjReyz4RHsQZ6kay8bAEIpg24rlfJKyw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -6584,8 +6584,8 @@ packages: dev: true optional: true - /@umijs/mako-linux-x64-musl@0.8.13: - resolution: {integrity: sha512-Z+/mJ4cFCLLblK1dkVi3sfkOTnFFmHLF89YYF4tZ1OsO9709kQAooe4LVeKBUdVGbdldvHVSZscMRRLmDhp+/w==} + /@umijs/mako-linux-x64-musl@0.8.15: + resolution: {integrity: sha512-E8bcYdCtVIky8FX5rIcwKn4Hvotqjd3+hFRZ27+RjuerxktB0Yb0kh1JGSu0UWc/xRk9dDjB20L8nfX3eKwjmw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -6593,8 +6593,8 @@ packages: dev: false optional: true - /@umijs/mako-win32-ia32-msvc@0.8.13: - resolution: {integrity: sha512-7thhScKlCaepDnppy2wGJsiz0yiBjRPT6KmYGi5dRMv/dsgv1Lfhy39wSBX6LiD3pIWgfYHCUUQgRc6yzDVrAA==} + /@umijs/mako-win32-ia32-msvc@0.8.15: + resolution: {integrity: sha512-aWXbaq6IxmtfgL+jn6UsiJFzaX1whN2+hzfS0eP31S1hRdeMjBvr6tLFiNcMfm9LmI/tlydjRR0n1WPgIlk5PA==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -6602,8 +6602,8 @@ packages: dev: false optional: true - /@umijs/mako-win32-x64-msvc@0.8.13: - resolution: {integrity: sha512-Mxr12n0xGK0IdeQnVj+2rrl+3Yj3fSA87eMgAgWFr01fzQURYeV4RXMgLx+vtZWJFESUPxJbmBRwgRVEkqLH6A==} + /@umijs/mako-win32-x64-msvc@0.8.15: + resolution: {integrity: sha512-SsrlUA/9TFRnmEWgripCyZMBrbqXXYdh/sJG2kUqk5Tp9KDVvpHbFhymNLaerpjaZwTw5qunI6+G5Ge+O/PA3g==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -9868,6 +9868,7 @@ packages: /eslint@8.41.0: resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.41.0) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 36e64a7ab..15a2e5e84 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] profile = "default" -channel = "nightly-2023-10-24" +channel = "nightly-2024-07-21" diff --git a/scripts/release.ts b/scripts/release.ts deleted file mode 100644 index 03d9f1d9c..000000000 --- a/scripts/release.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { parse } from 'semver'; -import 'zx/globals'; - -(async () => { - // check branch - console.log('Check branch'); - const branch = (await $`git branch --show-current`).stdout.trim(); - if (branch !== 'master') { - throw new Error('Please run this script in master branch'); - } - - // check git status - console.log('Check git status'); - const status = (await $`git status --porcelain`).stdout.trim(); - if (status) { - throw new Error('Please commit all changes before release'); - } - - // bump version - console.log('Bump version'); - const nodePkgDir = path.join(__dirname, '../crates/node'); - const nodePkgPath = path.join(nodePkgDir, 'package.json'); - const nodePkg = JSON.parse(fs.readFileSync(nodePkgPath, 'utf-8')); - const version = nodePkg.version; - const parsedVersion = parse(version); - if (!parsedVersion) { - throw new Error(`Invalid version: ${version}`); - } - parsedVersion.patch += 1; - let newVersion = parsedVersion.format(); - // remove prerelease tag - newVersion = newVersion.replace(/-.+/, ''); - nodePkg.version = newVersion; - fs.writeFileSync(nodePkgPath, JSON.stringify(nodePkg, null, 2) + '\n'); - - // set new version to bundler-okam - console.log('Set new version to bundler-okam'); - const bundlerOkamPkgPath = path.join( - __dirname, - '../packages/bundler-okam/package.json', - ); - const bundlerOkamPkg = JSON.parse( - fs.readFileSync(bundlerOkamPkgPath, 'utf-8'), - ); - bundlerOkamPkg.dependencies['@okamjs/okam'] = `${newVersion}`; - fs.writeFileSync( - bundlerOkamPkgPath, - JSON.stringify(bundlerOkamPkg, null, 2) + '\n', - ); - - // pnpm install to update lockfile - console.log('pnpm install'); - await $`pnpm install`; - - // commit - console.log('Commit'); - await $`git add ./`; - await $`git commit -m "Release ${newVersion}"`; - - // tag - console.log('Tag'); - await $`git tag v${newVersion}`; - - // push - console.log('Push'); - await $`git push origin ${branch} --tags`; -})().catch((e) => { - console.error(e); - process.exit(1); -}); diff --git a/scripts/test-hmr.mjs b/scripts/test-hmr.mjs index 8d12ecc24..b61ec59e9 100644 --- a/scripts/test-hmr.mjs +++ b/scripts/test-hmr.mjs @@ -1807,7 +1807,7 @@ runTest('js: response correct content-type', async () => { const headers = response.headers(); assert.equal( headers['content-type'], - 'application/javascript; charset=utf-8', + 'text/javascript; charset=utf-8', 'hot-update content-type', ); cleanup({ process, browser });