diff --git a/.bazelrc b/.bazelrc index 65cc8c4..01314ff 100644 --- a/.bazelrc +++ b/.bazelrc @@ -23,10 +23,6 @@ build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748 build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr -# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel -# https://github.com/protocolbuffers/protobuf/issues/14313 -common --noenable_bzlmod - # Important: this flag ensures that we remain compliant with the C++ layering # check. build --features=layering_check diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15b7a35..eca575f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 27.1 + PROTOC_VERSION: "31.0" jobs: build: @@ -27,10 +27,6 @@ jobs: node-version: 20 cache: ${{ !env.ACT && 'npm' || '' }} # cache API not available in ACT - - uses: bazel-contrib/setup-bazel@0.8.5 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Install Protoc run: | echo "Fetching protoc" @@ -108,7 +104,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: releases + name: release-${{ matrix.os }}-${{ matrix.cpu }} path: out release: @@ -122,7 +118,7 @@ jobs: steps: - uses: actions/download-artifact@v4 with: - name: releases + name: release-${{ matrix.os }}-${{ matrix.cpu }} - name: Release uses: svenstaro/upload-release-action@v2 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 7136068..197cb6e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,7 +15,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 27.1 + PROTOC_VERSION: "31.0" on: push: diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..d4588b0 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,73 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '32 5 * * 0' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml deleted file mode 100644 index f266af0..0000000 --- a/.github/workflows/scorecards.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Scorecards supply-chain security -on: - # Only the default branch is supported. - branch_protection_rule: - schedule: - - cron: '24 19 * * 0' - push: - branches: [ "main" ] - -# Declare default permissions as read only. -permissions: read-all - -jobs: - analysis: - name: Scorecards analysis - runs-on: ubuntu-latest - permissions: - # Needed to upload the results to code-scanning dashboard. - security-events: write - # Used to receive a badge. (Upcoming feature) - id-token: write - # Needs for private repositories. - contents: read - actions: read - - steps: - - name: "Checkout code" - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 - with: - persist-credentials: false - - - name: "Run analysis" - uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # v1.1.1 - with: - results_file: results.sarif - results_format: sarif - # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecards on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - # repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} - - # Publish the results for public repositories to enable scorecard badges. For more details, see - # https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories, `publish_results` will automatically be set to `false`, regardless - # of the value entered here. - publish_results: true - - # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF - # format to the repository Actions tab. - - name: "Upload artifact" - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard. - - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26 - with: - sarif_file: results.sarif diff --git a/MODULE.bazel b/MODULE.bazel index a639a78..75b5ed7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,4 +1,5 @@ module(name = "protobuf_javascript", version = "3.21.4") -bazel_dep(name = "protobuf", version = "27.1", repo_name = "com_google_protobuf") -bazel_dep(name = "rules_pkg", version = "0.7.0") +bazel_dep(name = "protobuf", version = "31.0", repo_name = "com_google_protobuf") +bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "abseil-cpp", version = "20250127.0") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 22cecad..a17bf63 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -1,121 +1,267 @@ { - "lockFileVersion": 11, + "lockFileVersion": 18, "registryFileHashes": { "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/source.json": "14892cc698e02ffedf4967546e6bedb7245015906888d3465fcf27c90a26da10", - "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", - "https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/source.json": "1b996859f840d8efc7c720efc61dcf2a84b1261cb3974cbbe9b6666ebf567775", + "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", + "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", + "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", - "https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/source.json": "c72c61b722d7c3f884994fe647afeb2ed1ae66c437f8f370753551f7b4d8be7f", + "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", - "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/source.json": "082ed5f9837901fada8c68c2f3ddc958bb22b6d654f71dd73f3df30d45d4b749", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.14.0/source.json": "2478949479000fdd7de9a3d0107ba2c85bb5f961c3ecb1aa448f52549ce310b5", + "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470", "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29", "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", - "https://bcr.bazel.build/modules/platforms/0.0.9/source.json": "cd74d854bf16a9e002fb2ca7b1a421f4403cda29f824a765acd3a8c56f8d43e6", "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", - "https://bcr.bazel.build/modules/protobuf/27.1/source.json": "11a2567425ffebb89ff59e94fc8a55bc78a418d52a4cc415069ce7c793571352", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", + "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/protobuf/31.0/MODULE.bazel": "cce0f305064713b382211c4c5af1d4fc1466e1fbc9059aa0941801970f6add5c", + "https://bcr.bazel.build/modules/protobuf/31.0/source.json": "266920c7b95f467db2dc38a640aed7265d948fc38dfb752bb91a027932ee2a99", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", + "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/source.json": "d8b5fe461272018cc07cfafce11fe369c7525330804c37eec5a82f84cd475366", "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5", "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", + "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/7.6.1/source.json": "8f3f3076554e1558e8e468b2232991c510ecbcbed9e6f8c06ac31c93bcf38362", + "https://bcr.bazel.build/modules/rules_java/8.11.0/MODULE.bazel": "c3d280bc5ff1038dcb3bacb95d3f6b83da8dd27bba57820ec89ea4085da767ad", + "https://bcr.bazel.build/modules/rules_java/8.11.0/source.json": "302b52a39259a85aa06ca3addb9787864ca3e03b432a5f964ea68244397e7544", + "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", + "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", + "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", - "https://bcr.bazel.build/modules/rules_jvm_external/5.1/source.json": "5abb45cc9beb27b77aec6a65a11855ef2b55d95dfdc358e9f312b78ae0ba32d5", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", + "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/0.0.7/source.json": "355cc5737a0f294e560d52b1b7a6492d4fff2caf0bef1a315df5a298fca2d34a", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", - "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json": "d57902c052424dfda0e71646cb12668d39c4620ee0544294d9d941e7d12bc3a9", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", - "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", - "https://bcr.bazel.build/modules/rules_python/0.22.1/source.json": "57226905e783bae7c37c2dd662be078728e48fa28ee4324a7eabcafb5a43d014", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", + "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", + "https://bcr.bazel.build/modules/rules_python/1.0.0/source.json": "b0162a65c6312e45e7912e39abd1a7f8856c2c7e41ecc9b6dc688a6f6400a917", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3", + "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.5.3/source.json": "cd53fe968dc8cd98197c052db3db6d82562960c87b61e7a90ee96f8e4e0dda97", + "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", + "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", + "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", - "https://bcr.bazel.build/modules/zlib/1.3/MODULE.bazel": "6a9c02f19a24dcedb05572b2381446e27c272cd383aed11d41d99da9e3167a72", - "https://bcr.bazel.build/modules/zlib/1.3/source.json": "b6b43d0737af846022636e6e255fd4a96fee0d34f08f3830e6e0bac51465c37c" + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" }, "selectedYankedVersions": {}, "moduleExtensions": { - "@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": { + "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { "general": { - "bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=", - "usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=", + "bzlTransitiveDigest": "okb7JAyJ9zeL+SDmtbWT0XBLq8WRoLJ0zWAG783RLVI=", + "usagesDigest": "EJfdUgbJdIRboG70S9dz8HhGVkL2/s3qFQ9xht8y2Rs=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { - "local_config_apple_cc": { - "bzlFile": "@@apple_support~//crosstool:setup.bzl", - "ruleClassName": "_apple_cc_autoconf", + "local_config_apple_cc_toolchains": { + "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf_toolchains", "attributes": {} }, - "local_config_apple_cc_toolchains": { - "bzlFile": "@@apple_support~//crosstool:setup.bzl", - "ruleClassName": "_apple_cc_autoconf_toolchains", + "local_config_apple_cc": { + "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf", "attributes": {} } }, "recordedRepoMappingEntries": [ [ - "apple_support~", + "apple_support+", "bazel_tools", "bazel_tools" + ], + [ + "bazel_tools", + "rules_cc", + "rules_cc+" ] ] } }, - "@@platforms//host:extension.bzl%host_platform": { + "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { - "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=", - "usagesDigest": "meSzxn3DUCcYEhq4HQwExWkWtU4EjriRBQLsZN+Q0SU=", + "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", + "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { - "host_platform": { - "bzlFile": "@@platforms//host:extension.bzl", - "ruleClassName": "host_platform_repo", - "attributes": {} + "com_github_jetbrains_kotlin_git": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } } }, - "recordedRepoMappingEntries": [] + "recordedRepoMappingEntries": [ + [ + "rules_kotlin+", + "bazel_tools", + "bazel_tools" + ] + ] } } } diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 18e9262..0000000 --- a/WORKSPACE +++ /dev/null @@ -1,30 +0,0 @@ -workspace(name = "com_google_protobuf_javascript") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "com_google_protobuf", - urls = ["https://github.com/protocolbuffers/protobuf/archive/refs/tags/v27.1.zip"], - sha256 = "9e6dbaefbfc670037e1a25ac4434adea1403821950444ec40fab8b2a9423c2ea", - strip_prefix = "protobuf-27.1", -) - -load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") -protobuf_deps() - - -# Taken from -# https://github.com/bazelbuild/rules_pkg/blob/main/pkg/deps.bzl. -# -# This is required under bazel 6 according to -# https://github.com/bazelbuild/rules_pkg/issues/872, otherwise we -# will see the same error. -http_archive( - name = "rules_python", - sha256 = "0a8003b044294d7840ac7d9d73eef05d6ceb682d7516781a4ec62eeb34702578", - strip_prefix = "rules_python-0.24.0", - url = "https://github.com/bazelbuild/rules_python/releases/download/0.24.0/rules_python-0.24.0.tar.gz", -) - -load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") -rules_pkg_dependencies() diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod deleted file mode 100644 index 7de259e..0000000 --- a/WORKSPACE.bzlmod +++ /dev/null @@ -1,2 +0,0 @@ -# When Bzlmod is enabled, this file replaces the content of the original WORKSPACE and -# makes sure no WORKSPACE prefix or suffix are added when Bzlmod is enabled. diff --git a/binary/decoder.js b/binary/decoder.js index 1186add..5dac0dd 100644 --- a/binary/decoder.js +++ b/binary/decoder.js @@ -47,7 +47,7 @@ goog.provide('jspb.BinaryDecoder'); goog.require('jspb.asserts'); -goog.require('goog.crypt'); +goog.require('jspb.binary.utf8'); goog.require('jspb.utils'); @@ -256,7 +256,7 @@ jspb.BinaryDecoder.prototype.setCursor = function(cursor) { */ jspb.BinaryDecoder.prototype.advance = function(count) { this.cursor_ += count; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); }; @@ -397,6 +397,17 @@ jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) { return convert(lowBits, highBits); }; +/** + * Asserts that our cursor is in bounds. + * + * @private + * @return {void} + */ +jspb.BinaryDecoder.prototype.checkCursor = function () { + if (this.cursor_ > this.end_) { + jspb.asserts.fail('Read past the end ' + this.cursor_ + ' > ' + this.end_); + } +} /** * Skips over a varint in the block without decoding it. @@ -452,7 +463,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { var x = (temp & 0x7F); if (temp < 128) { this.cursor_ += 1; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -460,7 +471,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x7F) << 7; if (temp < 128) { this.cursor_ += 2; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -468,7 +479,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x7F) << 14; if (temp < 128) { this.cursor_ += 3; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -476,7 +487,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x7F) << 21; if (temp < 128) { this.cursor_ += 4; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -486,7 +497,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { // We're reading the high bits of an unsigned varint. The byte we just read // also contains bits 33 through 35, which we're going to discard. this.cursor_ += 5; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x >>> 0; } @@ -500,7 +511,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { jspb.asserts.assert(false); } - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; }; @@ -679,7 +690,7 @@ jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() { jspb.BinaryDecoder.prototype.readUint8 = function() { var a = this.bytes_[this.cursor_ + 0]; this.cursor_ += 1; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return a; }; @@ -694,7 +705,7 @@ jspb.BinaryDecoder.prototype.readUint16 = function() { var a = this.bytes_[this.cursor_ + 0]; var b = this.bytes_[this.cursor_ + 1]; this.cursor_ += 2; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (a << 0) | (b << 8); }; @@ -711,7 +722,7 @@ jspb.BinaryDecoder.prototype.readUint32 = function() { var c = this.bytes_[this.cursor_ + 2]; var d = this.bytes_[this.cursor_ + 3]; this.cursor_ += 4; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0; }; @@ -756,7 +767,7 @@ jspb.BinaryDecoder.prototype.readUint64String = function() { jspb.BinaryDecoder.prototype.readInt8 = function() { var a = this.bytes_[this.cursor_ + 0]; this.cursor_ += 1; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (a << 24) >> 24; }; @@ -771,7 +782,7 @@ jspb.BinaryDecoder.prototype.readInt16 = function() { var a = this.bytes_[this.cursor_ + 0]; var b = this.bytes_[this.cursor_ + 1]; this.cursor_ += 2; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (((a << 0) | (b << 8)) << 16) >> 16; }; @@ -788,7 +799,7 @@ jspb.BinaryDecoder.prototype.readInt32 = function() { var c = this.bytes_[this.cursor_ + 2]; var d = this.bytes_[this.cursor_ + 3]; this.cursor_ += 4; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (a << 0) | (b << 8) | (c << 16) | (d << 24); }; @@ -858,7 +869,9 @@ jspb.BinaryDecoder.prototype.readDouble = function() { * @export */ jspb.BinaryDecoder.prototype.readBool = function() { - return !!this.bytes_[this.cursor_++]; + const b = !!this.bytes_[this.cursor_++]; + this.checkCursor(); + return b; }; @@ -879,75 +892,20 @@ jspb.BinaryDecoder.prototype.readEnum = function() { * Supports codepoints from U+0000 up to U+10FFFF. * (http://en.wikipedia.org/wiki/UTF-8). * @param {number} length The length of the string to read. + * @param {boolean} requireUtf8 Whether to throw when invalid utf8 is found. * @return {string} The decoded string. * @export */ -jspb.BinaryDecoder.prototype.readString = function(length) { - var bytes = this.bytes_; - var cursor = this.cursor_; - var end = cursor + length; - var codeUnits = []; - - var result = ''; - while (cursor < end) { - var c = bytes[cursor++]; - if (c < 128) { // Regular 7-bit ASCII. - codeUnits.push(c); - } else if (c < 192) { - // UTF-8 continuation mark. We are out of sync. This - // might happen if we attempted to read a character - // with more than four bytes. - continue; - } else if (c < 224) { // UTF-8 with two bytes. - var c2 = bytes[cursor++]; - codeUnits.push(((c & 31) << 6) | (c2 & 63)); - } else if (c < 240) { // UTF-8 with three bytes. - var c2 = bytes[cursor++]; - var c3 = bytes[cursor++]; - codeUnits.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - } else if (c < 248) { // UTF-8 with 4 bytes. - var c2 = bytes[cursor++]; - var c3 = bytes[cursor++]; - var c4 = bytes[cursor++]; - // Characters written on 4 bytes have 21 bits for a codepoint. - // We can't fit that on 16bit characters, so we use surrogates. - var codepoint = - ((c & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63); - // Surrogates formula from wikipedia. - // 1. Subtract 0x10000 from codepoint - codepoint -= 0x10000; - // 2. Split this into the high 10-bit value and the low 10-bit value - // 3. Add 0xD800 to the high value to form the high surrogate - // 4. Add 0xDC00 to the low value to form the low surrogate: - var low = (codepoint & 1023) + 0xDC00; - var high = ((codepoint >> 10) & 1023) + 0xD800; - codeUnits.push(high, low); - } - // Avoid exceeding the maximum stack size when calling `apply`. - if (codeUnits.length >= 8192) { - result += String.fromCharCode.apply(null, codeUnits); - codeUnits.length = 0; - } - } - result += goog.crypt.byteArrayToString(codeUnits); - this.cursor_ = cursor; +jspb.BinaryDecoder.prototype.readString = function (length, requireUtf8) { + const cursor = this.cursor_; + this.cursor_ += length; + this.checkCursor(); + const result = + jspb.binary.utf8.decodeUtf8(jspb.asserts.assert(this.bytes_), cursor, length, requireUtf8); return result; }; - -/** - * Reads and parses a UTF-8 encoded unicode string (with length prefix) from - * the stream. - * @return {string} The decoded string. - * @export - */ -jspb.BinaryDecoder.prototype.readStringWithLength = function() { - var length = this.readUnsignedVarint32(); - return this.readString(length); -}; - - /** * Reads a block of raw bytes from the binary stream. * @@ -966,7 +924,7 @@ jspb.BinaryDecoder.prototype.readBytes = function(length) { var result = this.bytes_.subarray(this.cursor_, this.cursor_ + length); this.cursor_ += length; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return result; }; diff --git a/binary/decoder_test.js b/binary/decoder_test.js index 77f6877..7a71c0d 100644 --- a/binary/decoder_test.js +++ b/binary/decoder_test.js @@ -354,7 +354,7 @@ describe('binaryDecoderTest', () => { const decoder = jspb.BinaryDecoder.alloc(encoder.end()); - expect(decoder.readString(len)).toEqual(long_string); + expect(decoder.readString(len, true)).toEqual(long_string); }); /** @@ -375,11 +375,11 @@ describe('binaryDecoderTest', () => { const decoder = jspb.BinaryDecoder.alloc(encoder.end()); - expect(decoder.readString(ascii.length)).toEqual(ascii); - expect(utf8_two_bytes).toEqual(decoder.readString(utf8_two_bytes.length)); + expect(decoder.readString(ascii.length, /* enforceUtf8= */ true)).toEqual(ascii); + expect(utf8_two_bytes).toEqual(decoder.readString(2, /* enforceUtf8= */ true)); expect(utf8_three_bytes) - .toEqual(decoder.readString(utf8_three_bytes.length)); - expect(utf8_four_bytes).toEqual(decoder.readString(utf8_four_bytes.length)); + .toEqual(decoder.readString(3, /* enforceUtf8= */ true)); + expect(utf8_four_bytes).toEqual(decoder.readString(4, /* enforceUtf8= */ true)); }); /** diff --git a/binary/reader.js b/binary/reader.js index 7be3b58..0f8c961 100644 --- a/binary/reader.js +++ b/binary/reader.js @@ -52,6 +52,26 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.utils'); +/** + * Whether to enforce that string fields are valid utf8. + * + *

Currently set to `ALWAYS`, can be set to `DEPRECATED_PROTO3_ONLY` to only + * enforce utf8 for proto3 string fields, for proto2 string fields it will use + * replacement characters when encoding errors are found. + * + *

TODO: Remove the flag, simplify BinaryReader to remove + * readStringRequireUtf8 and related support in the code generator et. al. + * + * @define {string} + */ +const ENFORCE_UTF8 = goog.define('jspb.binary.ENFORCE_UTF8', 'ALWAYS'); + +// Constrain the set of values to only these two. +jspb.asserts.assert( + ENFORCE_UTF8 === 'DEPRECATED_PROTO3_ONLY' || ENFORCE_UTF8 === 'ALWAYS'); + +const /** boolean */ UTF8_PARSING_ERRORS_ARE_FATAL = ENFORCE_UTF8 === 'ALWAYS'; + /** @@ -996,10 +1016,29 @@ jspb.BinaryReader.prototype.readEnum = function() { * @export */ jspb.BinaryReader.prototype.readString = function() { + // delegate to the other reader so that inlining can eliminate this method + // in the common case. + if (UTF8_PARSING_ERRORS_ARE_FATAL) { + return this.readStringRequireUtf8(); + } + jspb.asserts.assert( this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); var length = this.decoder_.readUnsignedVarint32(); - return this.decoder_.readString(length); + return this.decoder_.readString(length, /*requireUtf8=*/ false); +}; + +/** + * Reads a string field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type, or if the string is + * not valid utf8. + * + * @return {string} The value of the string field. + */ +jspb.BinaryReader.prototype.readStringRequireUtf8 = function () { + jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + const length = this.decoder_.readUnsignedVarint32(); + return this.decoder_.readString(length, /*requireUtf8=*/ true); }; diff --git a/binary/utf8.js b/binary/utf8.js new file mode 100644 index 0000000..371982d --- /dev/null +++ b/binary/utf8.js @@ -0,0 +1,425 @@ +/** + * @fileoverview UTF8 encoding and decoding routines + */ +goog.provide('jspb.binary.utf8'); + +goog.require('jspb.asserts'); + + +/** + * Whether to use the browser based `TextEncoder` and `TextDecoder` APIs for + * handling utf8. + * + *

Enabled by default for `goog.FEATURESET_YEAR >= 2020`. The code also + * performs feature detection for this API and will always use it if available, + * this variable enables us to not ship the polyfill. + * + *

See http://go/jscompiler-flags#browser-featureset-year-options for the + * behavior here. + * + * @define {boolean} + */ +const USE_TEXT_ENCODING = + goog.define('jspb.binary.USE_TEXTENCODING', goog.FEATURESET_YEAR >= 2020); + +const /** number */ MIN_SURROGATE = 0xD800; +const /** number */ MIN_HIGH_SURROGATE = MIN_SURROGATE; +const /** number */ MAX_HIGH_SURROGATE = 0xDBFF; +const /** number */ MIN_LOW_SURROGATE = 0xDC00; +const /** number */ MAX_LOW_SURROGATE = 0xDFFF; +const /** number */ MAX_SURROGATE = MAX_LOW_SURROGATE; + +/** + * Returns whether the byte is not a valid continuation of the form + * '10XXXXXX'. + * @return {boolean} + */ +function isNotTrailingByte(/** number */ byte) { + // 0xC0 is '11000000' in binary + // 0x80 is '10000000' in binary + return (byte & 0xC0) !== 0x80; +} + + +/** + * Either throws an error or appends a replacement codepoint of invalid utf8 + */ +function invalid( + /** boolean */ parsingErrorsAreFatal, /** !Array */ codeUnits) { + if (parsingErrorsAreFatal) { + throw new Error('Invalid UTF8'); + } + codeUnits.push(0xFFFD); // utf8 replacement character +} + +/** @return {string} */ +function codeUnitsToString( + /** string? */ accum, /** !Array */ utf16CodeUnits) { + const suffix = String.fromCharCode.apply(null, utf16CodeUnits); + return accum == null ? suffix : accum + suffix; +} + +/** + * Our handwritten UTF8 decoder. + * + * https://en.wikipedia.org/wiki/UTF-8#Encoding describes the bit layout + * + * https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling + * describes important cases to check for which are namely: + * - overlong encodings, meaning a value expressable in N bytes could have been + * expressed in fewer bytes + * - invalid bytes, meaning bytes that are generally out of range + * - surrogate codepoints, utf8 never encodes directly a utf16 surrogate value + * - underflow where there aren't enough bytes for the sequence we are parsing + * - out of range codepoints. + * + * @return {string} + */ +jspb.binary.utf8.polyfillDecodeUtf8 = function ( + /** !Uint8Array */ bytes, /** number */ offset, /** number */ length, + /** boolean */ parsingErrorsAreFatal) { + let cursor = offset; + const end = cursor + length; + const codeUnits = []; + let result = null; + + // This is significantly slower than the TextDecoder implementation. + // Ideas for improving performance: + // 1. Reduce branching with non-shortcircuting operators, e.g. + // https://stackoverflow.com/q/5652363 + // 2. improve isNotTrailingByte using xor? + // 3. consider having a dedicate ascii loop (java impls do this) + let c1, c2, c3, c4; + while (cursor < end) { + c1 = bytes[cursor++]; + if (c1 < 0x80) { // Regular 7-bit ASCII. + codeUnits.push(c1); + } else if (c1 < 0xE0) { // UTF-8 with two bytes. + if (cursor >= end) { + invalid(parsingErrorsAreFatal, codeUnits); + } else { + c2 = bytes[cursor++]; + // Make sure that c1 is a valid leading byte and c2 is a valid + // trailing byte + // 0xC2 is '11000010', if c1 is less than this then we have an overlong + // encoding because there would only be 7 significant bits. + if (c1 < 0xC2 || isNotTrailingByte(c2)) { + cursor--; // push c2 back since it isn't 'accepted' + invalid(parsingErrorsAreFatal, codeUnits); + } else { + // The codeUnit is the lower 6 bits from c2 and the lower 5 bits from + // c1 + const codeUnit = ((c1 & 0x1F) << 6) | (c2 & 0x3F); + // Consistency check that the computed code is in range for a 2 byte + // sequence. + jspb.asserts.assert(codeUnit >= 0x80 && codeUnit <= 0x07FF); + codeUnits.push(codeUnit); + } + } + } else if (c1 < 0xF0) { // UTF-8 with three bytes. + if (cursor >= end - 1) { + invalid(parsingErrorsAreFatal, codeUnits); + } else { + c2 = bytes[cursor++]; + if (isNotTrailingByte(c2) || + // These checks were taken from + // java/com/google/protobuf/Utf8.java + // overlong? 5 most significant bits must not all be zero + (c1 === 0xE0 && c2 < 0xA0) + // check for illegal surrogate codepoints + || (c1 === 0xED && c2 >= 0xA0) || + // We delay reading c3 until now so than an error in c2 or c1 will + // preserve c3 for the next loop iteration + isNotTrailingByte(c3 = bytes[cursor++])) { + cursor--; // push back c2 or c3, depending on how far we made it + invalid(parsingErrorsAreFatal, codeUnits); + } else { + // 4 bits from the first byte + // 6 bits from each of the two lower bytes + // == 16 bits total + const codeUnit = + ((c1 & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); + // Consistency check, this is the valid range for a 3 byte character + jspb.asserts.assert(codeUnit >= 0x800 && codeUnit <= 0xFFFF); + // And that Utf16 surrogates are disallowed + jspb.asserts.assert(codeUnit < MIN_SURROGATE || codeUnit > MAX_SURROGATE); + codeUnits.push(codeUnit); + } + } + } else if (c1 <= 0xF4) { // UTF-8 with 4 bytes. + // 0xF8 matches the bitpattern for utf8 with 4 bytes, but all leading + // bytes > 0xF4 are either overlong encodings or exceed the valid range. + if (cursor >= end - 2) { + invalid(parsingErrorsAreFatal, codeUnits); + } else { + c2 = bytes[cursor++]; + if (isNotTrailingByte(c2) || + // This check was inspired by + // java/com/google/protobuf/Utf8.java + // Tricky optimized form of: + // valid 4-byte leading byte? + // if (byte1 > (byte) 0xF4 || + // overlong? 4 most significant bits must not all be zero + // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || + // codepoint larger than the highest code point (U+10FFFF)? + // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) + (((c1 << 28) + (c2 - 0x90)) >> 30) !== 0 || + // We delay reading c3 and c4 until now so than an error in c2 or c1 + // will preserve them for the next loop iteration. + isNotTrailingByte(c3 = bytes[cursor++]) || + isNotTrailingByte(c4 = bytes[cursor++])) { + cursor--; // push back c2, c3 or c4 depending on how far we made it + invalid(parsingErrorsAreFatal, codeUnits); + } else { + // Characters written on 4 bytes have 21 bits for a codepoint. + // We can't fit that on 16bit characters, so we use surrogates. + // 3 bits from the uppermost byte, 6 bits from each of the lower 3 + // bytes. This is 21 bits which is too big for a 16 bit utf16 code + // unit so we use surrogates. + let codepoint = ((c1 & 0x7) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + // Consistency check, this is the valid range for a 4 byte character. + jspb.asserts.assert(codepoint >= 0x10000 && codepoint <= 0x10FFFF); + // Surrogates formula from wikipedia. + // 1. Subtract 0x10000 from codepoint + codepoint -= 0x10000; + // 2. Split this into the high 10-bit value and the low 10-bit value + // 3. Add 0xD800 to the high value to form the high surrogate + // 4. Add 0xDC00 to the low value to form the low surrogate: + const low = (codepoint & 0x3FF) + MIN_LOW_SURROGATE; + const high = ((codepoint >> 10) & 0x3FF) + MIN_HIGH_SURROGATE; + codeUnits.push(high, low); + } + } + } else { + // initial byte is too large for utf8 + invalid(parsingErrorsAreFatal, codeUnits); + } + // Accumulate as we go to avoid exceeding the maximum stack size when + // calling `apply`. + if (codeUnits.length >= 8192) { + result = codeUnitsToString(result, codeUnits); + codeUnits.length = 0; + } + } + // ensure we don't overflow or underflow + jspb.asserts.assert(cursor === end, `expected ${cursor} === ${end}`); + return codeUnitsToString(result, codeUnits); +} + + +/** @type {boolean|undefined} */ +let isFatalTextDecoderCachableAfterThrowing_ = + // chrome version >= 2020 are not subject to https://crbug.com/910292 + goog.FEATURESET_YEAR >= 2020 ? true : undefined; + +/** @return {boolean} */ +function isFatalTextDecoderCachableAfterThrowing(/** !TextDecoder */ decoder) { + // Test if the decoder is subject to https://crbug.com/910292 + // chrome versions with this bug cause one failed decode to cause all later + // decodes to throw. + if (isFatalTextDecoderCachableAfterThrowing_ === undefined) { + // In theory we shouldn't need to generate an error here since this function + // is only called in the context of a failed decode. However, the buggy + // chrome versions are not 'consistent' in corrupting their internal state + // since it depends on where in the decode stream the error occurs. This + // error however does consistently trigger the bug based on manual testing. + try { + // A lonely continuation byte + decoder.decode(new Uint8Array([0x80])); + } catch (e) { + // expected + } + try { + // 'a' in hex + decoder.decode(new Uint8Array([0x61])); + isFatalTextDecoderCachableAfterThrowing_ = true; + } catch (e) { + // This decode should not throw, if it does it means our chrome version + // is buggy and we need to flush our cached decoder when failures occur + isFatalTextDecoderCachableAfterThrowing_ = false; + } + } + return isFatalTextDecoderCachableAfterThrowing_; +} + +/** @type {!TextDecoder|undefined} */ +let fatalDecoderInstance; + +/** @return {!TextDecoder}*/ +function getFatalDecoderInstance() { + let instance = fatalDecoderInstance; + if (!instance) { + instance = fatalDecoderInstance = new TextDecoder('utf-8', { fatal: true }); + } + return instance; +} + +/** @type {!TextDecoder|undefined} */ +let nonFatalDecoderInstance; + +/** @return {!TextDecoder}*/ +function getNonFatalDecoderInstance() { + let instance = nonFatalDecoderInstance; + if (!instance) { + instance = nonFatalDecoderInstance = + new TextDecoder('utf-8', { fatal: false }); + } + return instance; +} + +/** + * A `subarray` implementation that avoids calling `subarray` if it isn't needed + * + * `subarray` tends to be surprisingly slow. + * @return {!Uint8Array} + */ +function subarray( + /** !Uint8Array*/ bytes, /** number */ offset, /** number */ end) { + return offset === 0 && end === bytes.length ? bytes : + bytes.subarray(offset, end); +} + +/** + * @return {string} + */ +jspb.binary.utf8.textDecoderDecodeUtf8 = function ( + /** !Uint8Array*/ bytes, /** number */ offset, /** number */ length, + /** boolean*/ parsingErrorsAreFatal) { + const /** !TextDecoder */ decoder = parsingErrorsAreFatal ? + getFatalDecoderInstance() : + getNonFatalDecoderInstance(); + + bytes = subarray(bytes, offset, offset + length); + try { + return decoder.decode(bytes); + } catch (e) { + if (parsingErrorsAreFatal && + !isFatalTextDecoderCachableAfterThrowing(decoder)) { + fatalDecoderInstance = undefined; + } + throw e; + } +} + +/** @const {boolean} */ +const useTextDecoderDecode = + USE_TEXT_ENCODING || typeof TextDecoder !== 'undefined'; + +/** + * A utf8 decoding routine either based upon TextDecoder if available or using + * our polyfill implementation + * @return {string} + */ +jspb.binary.utf8.decodeUtf8 = function ( + /** !Uint8Array*/ bytes, /** number */ offset, /** number */ length, + /** boolean*/ parsingErrorsAreFatal) { + return useTextDecoderDecode ? + jspb.binary.utf8.textDecoderDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal) : + jspb.binary.utf8.polyfillDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal); +} + +/** @type {!TextEncoder|undefined} */ +let textEncoderInstance; + +/** @return {!Uint8Array} */ +jspb.binary.utf8.textEncoderEncode = function ( + /** string */ s, /** boolean */ rejectUnpairedSurrogates) { + if (rejectUnpairedSurrogates) { + jspb.binary.utf8.checkWellFormed(s); + } + + if (!textEncoderInstance) { + textEncoderInstance = new TextEncoder(); + } + return textEncoderInstance.encode(s); +} + +// isWellFormed landed in major browsers in early 2023 so it will only be +// definitely available in 2024 See +// http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed +const /** boolean */ HAS_WELL_FORMED_METHOD = goog.FEATURESET_YEAR > 2023 || + typeof String.prototype.isWellFormed === 'function'; + +jspb.binary.utf8.checkWellFormed = function (/** string */ text) { + if (HAS_WELL_FORMED_METHOD ? + // Externs don't contain the definition of this function yet. + // http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed + !(/** @type{{isWellFormed:function():boolean}}*/ ( + /** @type {?} */ (text)) + .isWellFormed()) : + /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/ + .test(text)) { + throw new Error('Found an unpaired surrogate'); + } +} + + +/** @return {!Uint8Array} */ +jspb.binary.utf8.polyfillEncode = function ( + /** string */ s, /** boolean */ rejectUnpairedSurrogates) { + let bi = 0; + // The worse case is that every character requires 3 output bytes, so we + // allocate for this. This assumes that the buffer will be short lived. + // Callers can always `slice` if needed + const buffer = new Uint8Array(3 * s.length); + for (let ci = 0; ci < s.length; ci++) { + let c = s.charCodeAt(ci); + if (c < 0x80) { + buffer[bi++] = c; + } else if (c < 0x800) { + buffer[bi++] = (c >> 6) | 0xC0; + buffer[bi++] = (c & 63) | 0x80; + } else { + jspb.asserts.assert(c < 65536); + // Look for surrogates + // First check if it is surrogate range + if (c >= MIN_SURROGATE && c <= MAX_SURROGATE) { + // is it a high surrogate? + if (c <= MAX_HIGH_SURROGATE && ci < s.length) { + const c2 = s.charCodeAt(++ci); + if (c2 >= MIN_LOW_SURROGATE && c2 <= MAX_LOW_SURROGATE) { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + const codePoint = + (c - MIN_SURROGATE) * 0x400 + c2 - MIN_LOW_SURROGATE + 0x10000; + buffer[bi++] = (codePoint >> 18) | 0xF0; + buffer[bi++] = ((codePoint >> 12) & 63) | 0x80; + buffer[bi++] = ((codePoint >> 6) & 63) | 0x80; + buffer[bi++] = (codePoint & 63) | 0x80; + continue; + } else { + // else c2 not in low surrogate range, treat c as a lone surrogate + // and back up ci so we process c2 on the next loop as an + // independent character + ci--; + } + } // else c not a high surrogate + if (rejectUnpairedSurrogates) { + throw new Error('Found an unpaired surrogate'); + } + c = 0xFFFD; // Error! Unpaired surrogate + } + buffer[bi++] = (c >> 12) | 0xE0; + buffer[bi++] = ((c >> 6) & 63) | 0x80; + buffer[bi++] = (c & 63) | 0x80; + } + } + return subarray(buffer, 0, bi); +} + +/** @const {boolean} */ +const useTextEncoderEncode = + (USE_TEXT_ENCODING || typeof TextEncoder !== 'undefined'); + +/** + * A utf8 encoding routine either based upon TextEncoder if available or using + * our polyfill implementation + * @return {!Uint8Array} + */ +jspb.binary.utf8.encodeUtf8 = function ( + /**string*/ string, /** boolean=*/ rejectUnpairedSurrogates = false) { + jspb.asserts.assertString(string); + return useTextEncoderEncode ? + jspb.binary.utf8.textEncoderEncode(string, rejectUnpairedSurrogates) : + jspb.binary.utf8.polyfillEncode(string, rejectUnpairedSurrogates); +} diff --git a/generator/BUILD.bazel b/generator/BUILD.bazel index ff3fb8b..b2df875 100644 --- a/generator/BUILD.bazel +++ b/generator/BUILD.bazel @@ -15,8 +15,8 @@ cc_binary( "@com_google_protobuf//src/google/protobuf/io:printer", "@com_google_protobuf//src/google/protobuf/io:tokenizer", "@com_google_protobuf//:protoc_lib", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", + "@abseil-cpp//absl/strings", + "@abseil-cpp//absl/strings:str_format", ], ) diff --git a/generator/js_generator.cc b/generator/js_generator.cc index 84365dc..a881c3d 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -89,7 +89,7 @@ enum BytesMode { BYTES_U8, // Explicitly coerce to Uint8Array where needed. }; -bool IsReserved(const std::string& ident) { +bool IsReserved(absl::string_view ident) { for (int i = 0; i < kNumKeyword; i++) { if (ident == kKeyword[i]) { return true; @@ -98,9 +98,8 @@ bool IsReserved(const std::string& ident) { return false; } -std::string GetSnakeFilename(const std::string& filename) { - std::string snake_name = filename; - return absl::StrReplaceAll(snake_name, {{"/", "_"}}); +std::string GetSnakeFilename(absl::string_view filename) { + return absl::StrReplaceAll(filename, {{"/", "_"}}); } // Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript @@ -135,7 +134,7 @@ std::string GetRootPath(const std::string& from_filename, // Returns the alias we assign to the module of the given .proto filename // when importing. -std::string ModuleAlias(const std::string& filename) { +std::string ModuleAlias(absl::string_view filename) { // This scheme could technically cause problems if a file includes any 2 of: // foo/bar_baz.proto // foo_bar_baz.proto @@ -157,7 +156,7 @@ std::string GetNamespace(const GeneratorOptions& options, if (!options.namespace_prefix.empty()) { return options.namespace_prefix; } else if (!file->package().empty()) { - return "proto." + file->package(); + return absl::StrCat("proto.", file->package()); } else { return "proto"; } @@ -204,7 +203,7 @@ std::string GetMessagePathPrefix(const GeneratorOptions& options, // message descriptor. std::string GetMessagePath(const GeneratorOptions& options, const Descriptor* descriptor) { - return GetMessagePathPrefix(options, descriptor) + descriptor->name(); + return absl::StrCat(GetMessagePathPrefix(options, descriptor), descriptor->name()); } // Returns the fully normalized JavaScript path prefix for the given @@ -219,7 +218,7 @@ std::string GetEnumPathPrefix(const GeneratorOptions& options, // enumeration descriptor. std::string GetEnumPath(const GeneratorOptions& options, const EnumDescriptor* enum_descriptor) { - return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name(); + return absl::StrCat(GetEnumPathPrefix(options, enum_descriptor), enum_descriptor->name()); } std::string MaybeCrossFileRef(const GeneratorOptions& options, @@ -230,9 +229,9 @@ std::string MaybeCrossFileRef(const GeneratorOptions& options, from_file != to_message->file()) { // Cross-file ref in CommonJS needs to use the module alias instead of // the global name. - return ModuleAlias(to_message->file()->name()) + - GetNestedMessageName(to_message->containing_type()) + "." + - to_message->name(); + return absl::StrCat(ModuleAlias(to_message->file()->name()), + GetNestedMessageName(to_message->containing_type()), ".", + to_message->name()); } else { // Within a single file we use a full name. return GetMessagePath(options, to_message); @@ -262,7 +261,7 @@ char ToLowerASCII(char c) { } } -std::vector ParseLowerUnderscore(const std::string& input) { +std::vector ParseLowerUnderscore(absl::string_view input) { std::vector words; std::string running = ""; for (auto c : input) { @@ -281,7 +280,7 @@ std::vector ParseLowerUnderscore(const std::string& input) { return words; } -std::vector ParseUpperCamel(const std::string& input) { +std::vector ParseUpperCamel(absl::string_view input) { std::vector words; std::string running = ""; for (auto c : input) { @@ -326,7 +325,7 @@ std::string ToUpperCamel(const std::vector& words) { // Based on code from descriptor.cc (Thanks Kenton!) // Uppercases the entire string, turning ValueName into // VALUENAME. -std::string ToEnumCase(const std::string& input) { +std::string ToEnumCase(absl::string_view input) { std::string result; result.reserve(input.size()); @@ -341,7 +340,7 @@ std::string ToEnumCase(const std::string& input) { return result; } -std::string ToLower(const std::string& input) { +std::string ToLower(absl::string_view input) { std::string result; result.reserve(input.size()); @@ -625,7 +624,7 @@ uint16_t DecodeUTF8Codepoint(uint8_t* bytes, size_t* length) { // Returns false if |out| was truncated because |in| contained invalid UTF-8 or // codepoints outside the BMP. // TODO(b/115551870): Support codepoints outside the BMP. -bool EscapeJSString(const std::string& in, std::string* out) { +bool EscapeJSString(absl::string_view in, std::string* out) { size_t decoded = 0; for (size_t i = 0; i < in.size(); i += decoded) { uint16_t codepoint = 0; @@ -697,7 +696,7 @@ bool EscapeJSString(const std::string& in, std::string* out) { return true; } -std::string EscapeBase64(const std::string& in) { +std::string EscapeBase64(absl::string_view in) { static const char* kAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string result; @@ -965,7 +964,7 @@ bool UseBrokenPresenceSemantics(const GeneratorOptions& options, bool ReturnsNullWhenUnset(const GeneratorOptions& options, const FieldDescriptor* field) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - field->is_optional()) { + !field->is_required() && !field->is_repeated()) { return true; } @@ -1073,17 +1072,21 @@ std::string JSFieldTypeAnnotation(const GeneratorOptions& options, return jstype; } -std::string JSBinaryReaderMethodType(const FieldDescriptor* field) { - std::string name = field->type_name(); +std::string JSBinaryMethodType(const FieldDescriptor* field, bool is_writer) { + std::string name = std::string(field->type_name()); if (name[0] >= 'a' && name[0] <= 'z') { name[0] = (name[0] - 'a') + 'A'; } + if (!is_writer && field->type() == FieldDescriptor::TYPE_STRING && + field->requires_utf8_validation()) { + name = name + "RequireUtf8"; + } return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name; } std::string JSBinaryReadWriteMethodName(const FieldDescriptor* field, bool is_writer) { - std::string name = JSBinaryReaderMethodType(field); + std::string name = JSBinaryMethodType(field, is_writer); if (field->is_packed()) { name = "Packed" + name; } else if (is_writer && field->is_repeated()) { @@ -1222,9 +1225,9 @@ std::string RelativeTypeName(const FieldDescriptor* field) { field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); // For a field with an enum or message type, compute a name relative to the // path name of the message type containing this field. - std::string package = field->file()->package(); - std::string containing_type = field->containing_type()->full_name() + "."; - std::string type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) + absl::string_view package = field->file()->package(); + std::string containing_type = absl::StrCat(field->containing_type()->full_name(), "."); + absl::string_view type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) ? field->enum_type()->full_name() : field->message_type()->full_name(); @@ -1241,7 +1244,7 @@ std::string RelativeTypeName(const FieldDescriptor* field) { } } - return type.substr(prefix); + return std::string(type).substr(prefix); } std::string JSExtensionsObjectName(const GeneratorOptions& options, @@ -1281,13 +1284,13 @@ std::string FieldDefinition(const GeneratorOptions& options, } else { value_type = ProtoTypeName(options, value_field); } - return absl::StrFormat("map<%s, %s> %s = %d;", key_type.c_str(), - value_type.c_str(), field->name().c_str(), + return absl::StrFormat("map<%s, %s> %s = %d;", key_type, + value_type, field->name(), field->number()); } else { std::string qualifier = field->is_repeated() ? "repeated" - : (field->is_optional() ? "optional" : "required"); + : (field->is_required() ? "required" : "optional"); std::string type, name; if (field->type() == FieldDescriptor::TYPE_ENUM || field->type() == FieldDescriptor::TYPE_MESSAGE) { @@ -2628,7 +2631,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "rpt", (field->is_repeated() ? "Repeated" : ""), "index", JSFieldIndex(field), "wrapperclass", SubmessageTypeRef(options, field), "required", - (field->label() == FieldDescriptor::LABEL_REQUIRED ? ", 1" : "")); + (field->is_required() ? ", 1" : "")); printer->Annotate("gettername", field); printer->Print( "/**\n" @@ -3128,11 +3131,11 @@ void Generator::GenerateClassDeserializeBinaryField( printer->Print( " var values = /** @type {$fieldtype$} */ " "(reader.isDelimited() " - "? reader.readPacked$reader$() : [reader.read$reader$()]);\n", + "? reader.read$reader$() : [reader.read$reader$()]);\n", "fieldtype", JSFieldTypeAnnotation(options, field, false, true, /* singular_if_not_packed */ false, BYTES_U8), - "reader", JSBinaryReaderMethodType(field)); + "reader", JSBinaryReadWriteMethodName(field, /* is_writer=*/false)); } else { printer->Print( " var value = /** @type {$fieldtype$} */ " @@ -3584,8 +3587,8 @@ bool Generator::GenerateFile(const FileDescriptor* file, std::string filename = options.output_dir + "/" + GetJSFilename(options, use_short_name - ? file->name().substr(file->name().rfind('/')) - : file->name()); + ? std::string(file->name().substr(file->name().rfind('/'))) + : std::string(file->name())); std::unique_ptr output(context->Open(filename)); ABSL_CHECK(output); GeneratedCodeInfo annotations; @@ -3645,12 +3648,12 @@ void Generator::GenerateFile(const GeneratorOptions& options, } for (int i = 0; i < file->dependency_count(); i++) { - const std::string& name = file->dependency(i)->name(); + const std::string name = std::string(file->dependency(i)->name()); printer->Print( "var $alias$ = require('$file$');\n" "goog.object.extend(proto, $alias$);\n", "alias", ModuleAlias(name), "file", - GetRootPath(file->name(), name) + GetJSFilename(options, name)); + GetRootPath(std::string(file->name()), name) + GetJSFilename(options, name)); } } diff --git a/gulpfile.js b/gulpfile.js index e7f7511..426e0f1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -145,6 +145,7 @@ function getClosureCompilerCommand(exportsFile, outputFile) { '--js=binary/decoder.js', '--js=binary/encoder.js', '--js=binary/reader.js', + '--js=binary/utf8.js', '--js=binary/utils.js', '--js=binary/writer.js', `--js=${exportsFile}`, @@ -194,7 +195,7 @@ function commonjs_out(cb) { function closure_make_deps(cb) { exec( - './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js asserts.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', + './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utf8.js binary/utils.js binary/writer.js asserts.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', make_exec_logging_callback(cb)); } diff --git a/package-lock.json b/package-lock.json index 556297d..4fe22bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "google-protobuf", - "version": "3.21.2", + "version": "3.21.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "google-protobuf", - "version": "3.21.2", + "version": "3.21.4", "license": "(BSD-3-Clause AND Apache-2.0)", "devDependencies": { "glob": "~7.1.4", @@ -1279,9 +1279,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { "braces": "^3.0.3", @@ -3036,9 +3036,9 @@ "dev": true }, "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { "braces": "^3.0.3", diff --git a/protobuf_javascript_release.bzl b/protobuf_javascript_release.bzl index 650fc2c..3f9090a 100644 --- a/protobuf_javascript_release.bzl +++ b/protobuf_javascript_release.bzl @@ -1,7 +1,7 @@ """Generates package naming variables for use with rules_pkg.""" load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -load("@rules_pkg//:providers.bzl", "PackageVariablesInfo") +load("@rules_pkg//pkg:providers.bzl", "PackageVariablesInfo") _PROTOBUF_JAVASCRIPT_VERSION = "3.21.4" diff --git a/yarn.lock b/yarn.lock index 031949d..4f70eed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -744,9 +744,9 @@ map-cache@^0.2.0: integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + version "4.0.8" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1"