Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Replace protobuf.js #1058

Merged
merged 21 commits into from
Aug 15, 2024
Merged

Conversation

timostamm
Copy link
Contributor

@timostamm timostamm commented Jun 10, 2024

This PR replaces protobuf.js with @bufbuild/protobuf in generated code. The libraries are used for low-level wire encoding. Since they have a similar API, the changes to main.ts are relatively simple.

The main advantage is that Long.js is no longer a dependency, unless you explicitly want to use Long.js (plugin option forceLong=long).

The signatures of encode and decode change - they no longer use Reader and Writer from protobuf.js, but the counterparts from @bufbuild/protobuf. This will be a breaking change for users that manually pass in readers, or rely on the returned writer to be a specific type.

Follow-ups:

  • Replace Reader in src/schema.ts 0d763e9
  • Re-generate code for ts-proto-descriptors 3ae8889
  • Move protobufjs from dependencies to devDependencies 7ef0c73

Replaces Reader from protobuf.js with BinaryReader from @bufbuild/protobuf/wire.

Next up: Replace Writer with BinaryWriter, and sort out Long.js

Note: This feature should be behind a plugin option, but it isn't yet.
protobuf.js' Reader uses Node.js' Buffer when running on Node.js. This means that tests were expecting a Buffer, even when they do not set env=node. BinaryReader from @bufbuild/protobuf/wire always uses Uint8Array, causing the expectations to fail.

To solve the problem, we update the tests to expect Uint8Array. There is one odd case in integration/unknown-fields/unknown-fields-test.ts that required a workaround (see comments). The workaround can be removed after migrating Reader as well.

With this change, all tests pass, except simple-esmodule-interop.
stephenh@c307550 changed generated code. Merging it in reverted our changes.
The PR added new tests, and we need to re-generate the proto files.
BinaryReader already returns a BigInt for 64-bit integers. We don't need to convert it.

If BigInt is not supported in the current runtime (Safari was the last to catch up in 2020), it returns a string. In that case, it isn't possible to convert to a BigInt anyway.

This should be a regression, because the old code relied on BigInt as well.
protobuf.js automagically loads Long.js from node_modules, and uses it in Reader. If the magic fails (easily happens with bundlers), it falls back to an alternative and returns Number instead of Long.

Since the generated code no longer uses Reader, it is no longer necessary to explicitly configure protobuf.js to use Long.js
The conversion function just calls toString() on the value. We can do that without a conversion function.
@timostamm timostamm changed the title Replace protobuf.js feat: Replace protobuf.js Jun 10, 2024
@timostamm timostamm changed the title feat: Replace protobuf.js feat!: Replace protobuf.js Jun 10, 2024
Comment on lines +494 to +495
function longToNumber(int64: { toString(): string }): number {
const num = ${bytes.globalThis}.Number(int64.toString());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've verified that this check is reliable in #1057 (comment).

Since the package is not published yet, use the tsconfig option "path" to redirect imports from the npm package to the local sources.
And in ts-proto-descriptors, replace long and protobufjs with @bufbuild/protobuf
@timostamm
Copy link
Contributor Author

@stephenh, I took care of the follow-ups.

This is using an alpha of @bufbuild/protobuf v2. I promise we won't break it if you want to publish as is. A stable v2 is about a month out in case you prefer to wait.

ts-proto-descriptors should be published first - the ts-proto package.json has a dep on it.

@stephenh
Copy link
Owner

Amazing, thank you @timostamm !

@timostamm
Copy link
Contributor Author

A beta of @bufbuild/protobuf is available, and it won't be long until it's stable. I'll update this PR once the stable v2 is published.

@stephenh
Copy link
Owner

Awesome! Thanks for the update @timostamm !

@corwinsheahan-wf
Copy link

@timostamm @stephenh It looks like @bufbuild/protobuf v2 stable has been released. Any chance we can now get this PR merged/released?

@stephenh stephenh merged commit 61ea1f1 into stephenh:main Aug 15, 2024
6 checks passed
@stephenh
Copy link
Owner

This is amazing, as usual, @timostamm , thank you for the bump to the latest!

I merged this to main, with a semantic-release change to hopefully push it out as an alpha release, and we can see if that works! 🤞

@stephenh
Copy link
Owner

Just wanted to say thanks again @timostamm ! Really appreciate the help on this PR, and looking forward to @bufbuild/protobuf being a much better runtime for us! 🙏

@timostamm
Copy link
Contributor Author

Sorry, I was out for a couple of days. This was fun 😃 Congratulations on the v2 release!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants